LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogQ29weXJpZ2h0IChjKSAyMDAxLCAyMDA3IElCTSBDb3Jwb3JhdGlvbiBhbmQgb3RoZXJzLgogKiBBbGwgcmlnaHRzIHJlc2VydmVkLiBUaGlzIHByb2dyYW0gYW5kIHRoZSBhY2NvbXBhbnlpbmcgbWF0ZXJpYWxzCiAqIGFyZSBtYWRlIGF2YWlsYWJsZSB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEVjbGlwc2UgUHVibGljIExpY2Vuc2UgdjEuMAogKiB3aGljaCBhY2NvbXBhbmllcyB0aGlzIGRpc3RyaWJ1dGlvbiwgYW5kIGlzIGF2YWlsYWJsZSBhdAogKiBodHRwOi8vd3d3LmVjbGlwc2Uub3JnL2xlZ2FsL2VwbC12MTAuaHRtbAogKiAKICogQ29udHJpYnV0b3JzOgogKiAgICAgSUJNIENvcnBvcmF0aW9uIC0gaW5pdGlhbCBBUEkgYW5kIGltcGxlbWVudGF0aW9uCiAqICAgICBKZW5zIEx1a293c2tpL0lubm9vcHJhY3QgLSBpbml0aWFsIHJlbmFtaW5nL3Jlc3RydWN0dXJpbmcKICogICAgIEplc3BlciBTdGVlbiBN+GxsZXIgLSBpbml0aWFsIElEb2N1bWVudEV4dGVuc2lvbjQgc3VwcG9ydCAtICMxMDI4MjIKICogICAgIAogKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KcGFja2FnZSBvcmcuZWNsaXBzZS53c3Quc3NlLmNvcmUuaW50ZXJuYWwudGV4dDsKCmltcG9ydCBqYXZhLmlvLlJlYWRlcjsKaW1wb3J0IGphdmEudXRpbC5BcnJheUxpc3Q7CmltcG9ydCBqYXZhLnV0aWwuQ29sbGVjdGlvbnM7CmltcG9ydCBqYXZhLnV0aWwuSGFzaE1hcDsKaW1wb3J0IGphdmEudXRpbC5JdGVyYXRvcjsKaW1wb3J0IGphdmEudXRpbC5MaXN0OwppbXBvcnQgamF2YS51dGlsLk1hcDsKCmltcG9ydCBvcmcuZWNsaXBzZS5jb3JlLnJ1bnRpbWUuUGxhdGZvcm07CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LkJhZExvY2F0aW9uRXhjZXB0aW9uOwppbXBvcnQgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5CYWRQYXJ0aXRpb25pbmdFeGNlcHRpb247CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LkJhZFBvc2l0aW9uQ2F0ZWdvcnlFeGNlcHRpb247CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LkRlZmF1bHRMaW5lVHJhY2tlcjsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuRG9jdW1lbnRFdmVudDsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuRG9jdW1lbnRQYXJ0aXRpb25pbmdDaGFuZ2VkRXZlbnQ7CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LkRvY3VtZW50UmV3cml0ZVNlc3Npb247CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LkRvY3VtZW50UmV3cml0ZVNlc3Npb25FdmVudDsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuRG9jdW1lbnRSZXdyaXRlU2Vzc2lvblR5cGU7CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LkZpbmRSZXBsYWNlRG9jdW1lbnRBZGFwdGVyOwppbXBvcnQgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5JRG9jdW1lbnQ7CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklEb2N1bWVudEV4dGVuc2lvbjsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSURvY3VtZW50RXh0ZW5zaW9uMzsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSURvY3VtZW50RXh0ZW5zaW9uNDsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSURvY3VtZW50TGlzdGVuZXI7CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklEb2N1bWVudFBhcnRpdGlvbmVyOwppbXBvcnQgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5JRG9jdW1lbnRQYXJ0aXRpb25lckV4dGVuc2lvbjsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSURvY3VtZW50UGFydGl0aW9uZXJFeHRlbnNpb24yOwppbXBvcnQgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5JRG9jdW1lbnRQYXJ0aXRpb25lckV4dGVuc2lvbjM7CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklEb2N1bWVudFBhcnRpdGlvbmluZ0xpc3RlbmVyOwppbXBvcnQgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5JRG9jdW1lbnRQYXJ0aXRpb25pbmdMaXN0ZW5lckV4dGVuc2lvbjsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSURvY3VtZW50UGFydGl0aW9uaW5nTGlzdGVuZXJFeHRlbnNpb24yOwppbXBvcnQgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5JRG9jdW1lbnRSZXdyaXRlU2Vzc2lvbkxpc3RlbmVyOwppbXBvcnQgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5JTGluZVRyYWNrZXI7CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklMaW5lVHJhY2tlckV4dGVuc2lvbjsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSVBvc2l0aW9uVXBkYXRlcjsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSVJlZ2lvbjsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSVRleHRTdG9yZTsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSVR5cGVkUmVnaW9uOwppbXBvcnQgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5Qb3NpdGlvbjsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuU2VxdWVudGlhbFJld3JpdGVUZXh0U3RvcmU7CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LlR5cGVkUmVnaW9uOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNzZS5jb3JlLmludGVybmFsLkxvZ2dlcjsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zc2UuY29yZS5pbnRlcm5hbC5kb2N1bWVudC5TdHJ1Y3R1cmVkRG9jdW1lbnRGYWN0b3J5OwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNzZS5jb3JlLmludGVybmFsLmVuY29kaW5nLkVuY29kaW5nTWVtZW50bzsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zc2UuY29yZS5pbnRlcm5hbC5sdGsucGFyc2VyLlJlZ2lvblBhcnNlcjsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zc2UuY29yZS5pbnRlcm5hbC5wcm92aXNpb25hbC5ldmVudHMuQWJvdXRUb0JlQ2hhbmdlZEV2ZW50OwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNzZS5jb3JlLmludGVybmFsLnByb3Zpc2lvbmFsLmV2ZW50cy5JTW9kZWxBYm91dFRvQmVDaGFuZ2VkTGlzdGVuZXI7CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc3NlLmNvcmUuaW50ZXJuYWwucHJvdmlzaW9uYWwuZXZlbnRzLklTdHJ1Y3R1cmVkRG9jdW1lbnRMaXN0ZW5lcjsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zc2UuY29yZS5pbnRlcm5hbC5wcm92aXNpb25hbC5ldmVudHMuTm9DaGFuZ2VFdmVudDsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zc2UuY29yZS5pbnRlcm5hbC5wcm92aXNpb25hbC5ldmVudHMuUmVnaW9uQ2hhbmdlZEV2ZW50OwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNzZS5jb3JlLmludGVybmFsLnByb3Zpc2lvbmFsLmV2ZW50cy5SZWdpb25zUmVwbGFjZWRFdmVudDsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zc2UuY29yZS5pbnRlcm5hbC5wcm92aXNpb25hbC5ldmVudHMuU3RydWN0dXJlZERvY3VtZW50RXZlbnQ7CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc3NlLmNvcmUuaW50ZXJuYWwucHJvdmlzaW9uYWwuZXZlbnRzLlN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbnNSZXBsYWNlZEV2ZW50OwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNzZS5jb3JlLmludGVybmFsLnByb3Zpc2lvbmFsLnRleHQuSVN0cnVjdHVyZWREb2N1bWVudDsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zc2UuY29yZS5pbnRlcm5hbC5wcm92aXNpb25hbC50ZXh0LklTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb247CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc3NlLmNvcmUuaW50ZXJuYWwucHJvdmlzaW9uYWwudGV4dC5JU3RydWN0dXJlZERvY3VtZW50UmVnaW9uTGlzdDsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zc2UuY29yZS5pbnRlcm5hbC5wcm92aXNpb25hbC50ZXh0LklTdHJ1Y3R1cmVkUGFydGl0aW9uaW5nOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNzZS5jb3JlLmludGVybmFsLnByb3Zpc2lvbmFsLnRleHQuSVN0cnVjdHVyZWRUZXh0UmVQYXJzZXI7CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc3NlLmNvcmUuaW50ZXJuYWwudGV4dC5ydWxlcy5TdHJ1Y3R1cmVkVGV4dFBhcnRpdGlvbmVyOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNzZS5jb3JlLmludGVybmFsLnVuZG8uSVN0cnVjdHVyZWRUZXh0VW5kb01hbmFnZXI7CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc3NlLmNvcmUuaW50ZXJuYWwudW5kby5TdHJ1Y3R1cmVkVGV4dFVuZG9NYW5hZ2VyOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNzZS5jb3JlLmludGVybmFsLnV0aWwuQXNzZXJ0OwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNzZS5jb3JlLmludGVybmFsLnV0aWwuRGVidWc7CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc3NlLmNvcmUuaW50ZXJuYWwudXRpbC5VdGlsaXRpZXM7CgoKLyoqCiAqIFRoZSBzdGFuZGFyZCBpbXBsZW1lbnRhdGlvbiBvZiBzdHJ1Y3R1cmVkIGRvY3VtZW50LgogKi8KcHVibGljIGNsYXNzIEJhc2ljU3RydWN0dXJlZERvY3VtZW50IGltcGxlbWVudHMgSVN0cnVjdHVyZWREb2N1bWVudCwgSURvY3VtZW50RXh0ZW5zaW9uLCBJRG9jdW1lbnRFeHRlbnNpb24zLCBJRG9jdW1lbnRFeHRlbnNpb240LCBDaGFyU2VxdWVuY2UsIElSZWdpb25Db21wYXJpYmxlIHsKCgkvKioKCSAqIFRoaXMgVGhyZWFkTG9jYWwgY29uc3RydWN0IGlzIHVzZWQgc28gZWFjaCB0aHJlYWQgY2FuIG1haW50YWluIGl0cyBvbmx5CgkgKiBwb2ludGVyIHRvIHRoZSBkb3VibGUgbGlua2VkIGxpc3QgdGhhdCBtYW5hZ2VzIHRoZSBkb2N1bWVudHMgcmVnaW9ucy4KCSAqIFRoZSBvbmx5IHRoaW5nIHdlICJnYXVyZCIgZm9yIGlzIHRoYXQgYSBwcmV2aW91c2x5IGNhY2hlZCByZWdpb24gaGFzCgkgKiBiZWVuIGRlbGV0ZWQuCgkgKiAKCSAqIFRoZSBvYmplY3QgdGhhdCBpcyBrZXB0IGluIHRoZSB0aHJlYWQgbG9jYWwncyBtYXAsIGlzIGp1c3QgYSBwb2ludGVyIHRvCgkgKiBhbiBhcnJheSBwb3NpdGlvbi4gVGhhdCdzIGJlY2F1c2UgdGhlIG9iamVjdCB0aGVyZSBuZWVkcyB0byBiZSAiZnJlZSIKCSAqIGZyb20gcmVmZXJlbmNlcyB0byBvdGhlciBvYmplY3RzLCBvciBpdCB3aWxsIG5vdCBiZSBnYXJiYWdlIGNvbGxlY3RlZC4KCSAqLwoJcHJpdmF0ZSBjbGFzcyBDdXJyZW50RG9jdW1lbnRSZWdpb25DYWNoZSB7CgkJLy8gSSdtIGFzc3VtaW5nIGZvciBub3cgdGhlcmUgd291bGQgbmV2ZXIgYmUgc28gbWFueSB0aHJlYWRzIHRoYXQKCQkvLyB0aGlzIGFycmF5TGlzdCBuZWVkcyB0byBiZSBib3VuZGVkLCBvciAnY2xlYW5lZCB1cCcuCgkJLy8gdGhpcyBhc3N1bXB0aW9uIHNob3VsZCBiZSB0ZXN0ZWQgaW4gcHJhY3RpY2UgYW5kIGxvbmcgcnVubmluZwoJCS8vIGpvYnMgLS0gZm91bmQgbm90IHRvIGJlIGEgZ29vZCBhc3N1bXB0aW9uLiBTZWUgYmVsb3cuCgkJcHJpdmF0ZSBMaXN0IGNhY2hlZFJlZ2lvblBvc2l0aW9uQXJyYXkgPSBDb2xsZWN0aW9ucy5zeW5jaHJvbml6ZWRMaXN0KG5ldyBBcnJheUxpc3QoKSk7CgkJcHJpdmF0ZSBmaW5hbCBib29sZWFuIERFQlVHID0gZmFsc2U7CgkJcHJpdmF0ZSBmaW5hbCBpbnQgTUFYX1NJWkUgPSA1MDsKCgoJCXByaXZhdGUgVGhyZWFkTG9jYWwgdGhyZWFkTG9jYWxDYWNoZVBvc2l0aW9uID0gbmV3IFRocmVhZExvY2FsKCk7CgoJCUlTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb24gZ2V0KCkgewoJCQlJU3RydWN0dXJlZERvY3VtZW50UmVnaW9uIHJlZ2lvbiA9IG51bGw7CgkJCWludCBwb3MgPSBnZXRUaHJlYWRMb2NhbFBvc2l0aW9uKCk7CgkJCXRyeSB7CgkJCQlyZWdpb24gPSAoSVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbikgY2FjaGVkUmVnaW9uUG9zaXRpb25BcnJheS5nZXQocG9zKTsKCQkJfQoJCQljYXRjaCAoSW5kZXhPdXRPZkJvdW5kc0V4Y2VwdGlvbiBlKSB7CgkJCQkvLyBldmVuIHRob3VnaCB0aGUgY2FjaGVkUmVnaW9uUG9zaXRpb24gaXMgc3luY2hyb25pemVkLAoJCQkJLy8gdGhhdCBqdXN0IG1lYW5zIGVhY2ggYWNjZXNzIGlzIHN5bmNyb25pemVkLCBpdHMKCQkJCS8vIHN0aWxsIHBvc3NpYmxlIGZvciBhbm90aGVyIHRocmVhZCB0byBjYXVzZSBpdCB0bwoJCQkJLy8gYmUgY2xlYXJlZCwgYWZ0ZXIgdGhpcyB0aHJlYWQgZ2V0cyBpdCBwb3NpdGlvbi4KCQkJCS8vIFNvLCBpZiB0aGF0IGhhcHBlbnMsIGFsbCB3ZSBjYW4gZG8gaXMgcmVzZXQgdG8gYmVnaW5uaW5nLgoJCQkJLy8gVGhpcyBzaG91bGQgYmUgZXh0cmVtZWx5IHJhcmUgKGluIG90aGVyIHdvcmRzLCBwcm9iYWJseQoJCQkJLy8gbm90IHdvcnRoIHVzaW5nIHN5bmNocm9uaXplZCBibG9ja3MKCQkJCS8vIHRvIGFjY2VzcyBjYWNoZWRSZWdpb25Qb3NpdGlvbkFycmF5LgoJCQkJcmVpbml0VGhyZWFkTG9jYWxQb3NpdGlvbigpOwoJCQkJcmVzZXRUb0luaXRpYWxTdGF0ZSgpOwoJCQl9CgkJCWlmIChyZWdpb24gPT0gbnVsbCkgewoJCQkJcmVnaW9uID0gcmVzZXRUb0luaXRpYWxTdGF0ZSgpOwoJCQl9CgkJCWVsc2UKCQkJLy8gcmVnaW9uIG5vdCBudWxsCgkJCWlmIChyZWdpb24uaXNEZWxldGVkKCkpIHsKCQkJCXJlZ2lvbiA9IHJlc2V0VG9Jbml0aWFsU3RhdGUoKTsKCQkJfQoJCQlyZXR1cm4gcmVnaW9uOwoJCX0KCgkJcHJpdmF0ZSBpbnQgZ2V0VGhyZWFkTG9jYWxQb3NpdGlvbigpIHsKCQkJT2JqZWN0IHRocmVhZExvY2FsT2JqZWN0ID0gdGhyZWFkTG9jYWxDYWNoZVBvc2l0aW9uLmdldCgpOwoJCQlpbnQgcG9zID0gLTE7CgkJCWlmICh0aHJlYWRMb2NhbE9iamVjdCA9PSBudWxsKSB7CgoJCQkJcG9zID0gcmVpbml0VGhyZWFkTG9jYWxQb3NpdGlvbigpOwoJCQl9CgkJCWVsc2UgewoJCQkJcG9zID0gKChJbnRlZ2VyKSB0aHJlYWRMb2NhbE9iamVjdCkuaW50VmFsdWUoKTsKCQkJfQoJCQlyZXR1cm4gcG9zOwoJCX0KCgkJLyoqCgkJICogQHJldHVybgoJCSAqLwoJCXByaXZhdGUgaW50IHJlaW5pdFRocmVhZExvY2FsUG9zaXRpb24oKSB7CgkJCUludGVnZXIgcG9zaXRpb247CgkJCWludCBwb3M7CgkJCS8vIFRPRE9fZnV0dXJlOiB0aGluayBvZiBhIGJldHRlciBzb2x1dGlvbiB0aGF0IGRvZXNuJ3QKCQkJLy8gcmVxdWlyZSB0aGlzIGtsdWRnZS4gVGhpcyBpcyBlc3BlY2lhbGx5IHJlcXVpcmVkIGJlY2F1c2UKCQkJLy8gc29tZSBpbmZyYXN0dXJlLCBzdWNoIGFzIHJlY29uY2lsZXIsIGFjdHVhbGx5IG51bGwgb3V0CgkJCS8vIHRoZWlyIHRocmVhZCBvYmplY3QgYW5kIHJlY3JlYXRlIGl0LCA1MDAgbXNlY3MgbGF0ZXIKCQkJLy8gKGFwcHJveGltYXRlbHkpLgoJCQkvLyBOb3RlOiB0aGUgbGlrZWx5IHNvbHV0aW9uIGluIGZ1dHVyZSBpcyB0byBjbGVhciBhZnRlciBldmVyeQoJCQkvLyBoZWF2eSB1c2Ugb2YgZ2V0Q2FjaGVkUmVnaW9uLCBzdWNoIGFzIGluIGNyZWF0aW5nIG5vZGUKCQkJLy8gbGlzdHMsIG9yIHJlcGFyc2luZyBvciBwYXJ0aW9uaW5nLgoJCQlpZiAoY2FjaGVkUmVnaW9uUG9zaXRpb25BcnJheS5zaXplKCkgPiBNQVhfU0laRSkgewoJCQkJY2FjaGVkUmVnaW9uUG9zaXRpb25BcnJheS5jbGVhcigpOwoJCQkJaWYgKERFQlVHKSB7CgkJCQkJU3lzdGVtLm91dC5wcmludGxuKCJjYWNoZWRSZWdpb25Qb3NpdGlvbkFycmF5IGNsZWFyZWQgYXQgc2l6ZSAiICsgTUFYX1NJWkUpOyAvLyROT04tTkxTLTEkCgkJCQl9CgkJCX0KCQkJcG9zaXRpb24gPSBuZXcgSW50ZWdlcihjYWNoZWRSZWdpb25Qb3NpdGlvbkFycmF5LnNpemUoKSk7CgkJCXRocmVhZExvY2FsQ2FjaGVQb3NpdGlvbi5zZXQocG9zaXRpb24pOwoJCQljYWNoZWRSZWdpb25Qb3NpdGlvbkFycmF5LmFkZChwb3NpdGlvbi5pbnRWYWx1ZSgpLCBudWxsKTsKCQkJcG9zID0gcG9zaXRpb24uaW50VmFsdWUoKTsKCQkJcmV0dXJuIHBvczsKCQl9CgoJCXByaXZhdGUgSVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbiByZXNldFRvSW5pdGlhbFN0YXRlKCkgewoJCQlJU3RydWN0dXJlZERvY3VtZW50UmVnaW9uIHJlZ2lvbjsKCQkJcmVnaW9uID0gZ2V0Rmlyc3RTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb24oKTsKCQkJc2V0KHJlZ2lvbik7CgkJCXJldHVybiByZWdpb247CgkJfQoKCQkvLyBUT0RPOiBtYWtlIHByaXZpdGUgaWYgdXNlZCwgZWxzZSBkZWxldGUKCQl2b2lkIHNldChpbnQgcG9zLCBJU3RydWN0dXJlZERvY3VtZW50UmVnaW9uIHJlZ2lvbikgewoJCQljYWNoZWRSZWdpb25Qb3NpdGlvbkFycmF5LnNldChwb3MsIHJlZ2lvbik7CgkJfQoKCQl2b2lkIHNldChJU3RydWN0dXJlZERvY3VtZW50UmVnaW9uIHJlZ2lvbikgewoJCQl0cnkgewoJCQkJaW50IHBvcyA9IGdldFRocmVhZExvY2FsUG9zaXRpb24oKTsKCQkJCWNhY2hlZFJlZ2lvblBvc2l0aW9uQXJyYXkuc2V0KHBvcywgcmVnaW9uKTsKCQkJfQoJCQljYXRjaCAoSW5kZXhPdXRPZkJvdW5kc0V4Y2VwdGlvbiBlKSB7CgkJCQkvLyBldmVuIHRob3VnaCB0aGUgY2FjaGVkUmVnaW9uUG9zaXRpb24gaXMgc3luY2hyb25pemVkLAoJCQkJLy8gdGhhdCBqdXN0IG1lYW5zIGVhY2ggYWNjZXNzIGlzIHN5bmNyb25pemVkLCBpdHMKCQkJCS8vIHN0aWxsIHBvc3NpYmxlIGZvciBhbm90aGVyIHRocmVhZCB0byBjYXVzZSBpdCB0bwoJCQkJLy8gYmUgY2xlYXJlZCwgYWZ0ZXIgdGhpcyB0aHJlYWQgZ2V0cyBpdCBwb3NpdGlvbi4KCQkJCS8vIFNvLCBpZiB0aGF0IGhhcHBlbnMsIGFsbCB3ZSBjYW4gZG8gaXMgcmVzZXQgdG8gYmVnaW5uaW5nLgoJCQkJLy8gVGhpcyBzaG91bGQgYmUgZXh0cmVtZWx5IHJhcmUgKGluIG90aGVyIHdvcmRzLCBwcm9iYWJseQoJCQkJLy8gbm90IHdvcnRoIHVzaW5nIHN5bmNocm9uaXplZCBibG9ja3MKCQkJCS8vIHRvIGFjY2VzcyBjYWNoZWRSZWdpb25Qb3NpdGlvbkFycmF5LgoJCQkJcmVpbml0VGhyZWFkTG9jYWxQb3NpdGlvbigpOwoJCQkJcmVzZXRUb0luaXRpYWxTdGF0ZSgpOwoJCQl9CgkJfQoJfQoKCS8qKgoJICogVGhpcyBOdWxsRG9jdW1lbnRFdmVudCBpcyB1c2VkIHRvIGNvbXBsZXRlIHRoZSAiYWJvdXRUb0NoYW5nZSIgYW5kCgkgKiAiY2hhbmdlZCIgY3ljbGUsIHdoZW4gaW4gZmFjdCB0aGUgb3JpZ2luYWwgY2hhbmdlIGlzIG5vIGxvbmdlciB2YWxpZC4KCSAqIFRoZSBvbmx5IGtub3duICh2YWxpZCkgY2FzZSBvZiB0aGlzIGlzIHdoZW4gYSBtb2RlbCByZS1pbml0aWFsaXplIHRha2VzCgkgKiBwbGFjZSwgd2hpY2ggY2F1c2VzIHNldFRleHQgdG8gYmUgY2FsbGVkIGluIHRoZSBtaWRkbGUgb2Ygc29tZSBwcmV2aW91cwoJICogY2hhbmdlLiBbVGhpcyBhcmNoaXRlY3R1cmUgd2lsbCBiZSBpbXByb3ZlZCBpbiBmdXR1cmVdLgoJICovCglwdWJsaWMgY2xhc3MgTnVsbERvY3VtZW50RXZlbnQgZXh0ZW5kcyBEb2N1bWVudEV2ZW50IHsKCQlwdWJsaWMgTnVsbERvY3VtZW50RXZlbnQoKSB7CgkJCXRoaXMoQmFzaWNTdHJ1Y3R1cmVkRG9jdW1lbnQudGhpcywgMCwgMCwgIiIpOyAvLyROT04tTkxTLTEkCgkJfQoKCQlwcml2YXRlIE51bGxEb2N1bWVudEV2ZW50KElEb2N1bWVudCBkb2MsIGludCBvZmZzZXQsIGludCBsZW5ndGgsIFN0cmluZyB0ZXh0KSB7CgkJCXN1cGVyKGRvYywgb2Zmc2V0LCBsZW5ndGgsIHRleHQpOwoJCX0KCX0KCgljbGFzcyBSZWdpc3RlcmVkUmVwbGFjZSB7CgkJLyoqIFRoZSBvd25lciBvZiB0aGlzIHJlcGxhY2Ugb3BlcmF0aW9uLiAqLwoJCUlEb2N1bWVudExpc3RlbmVyIGZPd25lcjsKCQkvKiogVGhlIHJlcGxhY2Ugb3BlcmF0aW9uICovCgkJSURvY3VtZW50RXh0ZW5zaW9uLklSZXBsYWNlIGZSZXBsYWNlOwoKCQkvKioKCQkgKiBDcmVhdGVzIGEgbmV3IGJ1bmRsZSBvYmplY3QuCgkJICogCgkJICogQHBhcmFtIG93bmVyCgkJICogICAgICAgICAgICB0aGUgZG9jdW1lbnQgbGlzdGVuZXIgb3duaW5nIHRoZSByZXBsYWNlIG9wZXJhdGlvbgoJCSAqIEBwYXJhbSByZXBsYWNlCgkJICogICAgICAgICAgICB0aGUgcmVwbGFjZSBvcGVyYXRpb24KCQkgKi8KCQlSZWdpc3RlcmVkUmVwbGFjZShJRG9jdW1lbnRMaXN0ZW5lciBvd25lciwgSURvY3VtZW50RXh0ZW5zaW9uLklSZXBsYWNlIHJlcGxhY2UpIHsKCQkJZk93bmVyID0gb3duZXI7CgkJCWZSZXBsYWNlID0gcmVwbGFjZTsKCQl9Cgl9CgoJLyoqCgkgKiB0aGVzZSBjb250cm9sIHZhcmlhYmxlIGlzbid0IG1hcmsgYXMgJ2ZpbmFsJyBzaW5jZSB0aGVyZSdzIHNvbWUgdW5pdAoJICogdGVzdHMgdGhhdCBtYW5pcHVsYXRlIGl0LiBGb3IgZmluYWwgcHJvZHVjdCwgaXQgc2hvdWxkIGJlLgoJICovCgoJcHJpdmF0ZSBzdGF0aWMgYm9vbGVhbiBVU0VfTE9DQUxfVEhSRUFEID0gdHJ1ZTsKCgkvKioKCSAqIHB1cmVseSBmb3IgZGVidWdnaW5nL3BlcmZvcm1hbmNlIG1lYXN1cmVtZW50cyBJbiBwcmFjdGljZSwgd291bGQgYWx3YXlzCgkgKiBiZSAndHJ1ZScuIChhbmQgc2hvdWxkIG5ldmVyIGJlIGNhbGxlZCBieSBjYWxsZWQgYnkgY2xpZW50cykuIEl0cyBub3QKCSAqICdmaW5hbCcgb3IgcHJpdmF0ZSBqdXN0IHNvIGl0IGNhbiBiZSB2YXJpZWQgZHVyaW5nCgkgKiBkZWJ1Z2dpbmcvcGVyZm9ybWFuY2UgbWVhc3VyZW1lbnQgcnVucy4KCSAqIAoJICogQHBhcmFtIHVzZV9sb2NhbF90aHJlYWQKCSAqLwoJcHVibGljIHN0YXRpYyB2b2lkIHNldFVTRV9MT0NBTF9USFJFQUQoZmluYWwgYm9vbGVhbiB1c2VfbG9jYWxfdGhyZWFkKSB7CgkJVVNFX0xPQ0FMX1RIUkVBRCA9IHVzZV9sb2NhbF90aHJlYWQ7Cgl9CgoJcHJpdmF0ZSBJU3RydWN0dXJlZERvY3VtZW50UmVnaW9uIGNhY2hlZERvY3VtZW50UmVnaW9uOwoJcHJpdmF0ZSBFbmNvZGluZ01lbWVudG8gZW5jb2RpbmdNZW1lbnRvOwoJcHJpdmF0ZSBib29sZWFuIGZBY2NlcHRQb3N0Tm90aWZpY2F0aW9uUmVwbGFjZXMgPSB0cnVlOwoJcHJpdmF0ZSBDdXJyZW50RG9jdW1lbnRSZWdpb25DYWNoZSBmQ3VycmVudERvY3VtbmV0UmVnaW9uQ2FjaGU7Cglwcml2YXRlIERvY3VtZW50RXZlbnQgZkRvY3VtZW50RXZlbnQ7Cglwcml2YXRlIElEb2N1bWVudExpc3RlbmVyW10gZkRvY3VtZW50TGlzdGVuZXJzOwoKCS8qKgoJICogVGhlIHJlZ2lzdGVyZWQgZG9jdW1lbnQgcGFydGl0aW9uZXJzLgoJICovCglwcml2YXRlIE1hcCBmRG9jdW1lbnRQYXJ0aXRpb25lcnM7CgkvKiogVGhlIHJlZ2lzdGVyZWQgZG9jdW1lbnQgcGFydGl0aW9uaW5nIGxpc3RlbmVycyAqLwoJcHJpdmF0ZSBMaXN0IGZEb2N1bWVudFBhcnRpdGlvbmluZ0xpc3RlbmVyczsKCXByaXZhdGUgSVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbiBmaXJzdERvY3VtZW50UmVnaW9uOwoJcHJpdmF0ZSBSZWdpb25QYXJzZXIgZlBhcnNlcjsKCXByaXZhdGUgR2VuZXJpY1Bvc2l0aW9uTWFuYWdlciBmUG9zaXRpb25NYW5hZ2VyOwoJcHJpdmF0ZSBMaXN0IGZQb3N0Tm90aWZpY2F0aW9uQ2hhbmdlczsKCXByaXZhdGUgSURvY3VtZW50TGlzdGVuZXJbXSBmUHJlbm90aWZpZWREb2N1bWVudExpc3RlbmVyczsKCXByaXZhdGUgaW50IGZSZWVudHJhbmNlQ291bnQgPSAwOwoJcHJpdmF0ZSBJU3RydWN0dXJlZFRleHRSZVBhcnNlciBmUmVQYXJzZXI7Cglwcml2YXRlIGludCBmU3RvcHBlZENvdW50ID0gMDsKCglwcml2YXRlIElUZXh0U3RvcmUgZlN0b3JlOwoJcHJpdmF0ZSBPYmplY3RbXSBmU3RydWN0dXJlZERvY3VtZW50QWJvdXRUb0NoYW5nZUxpc3RlbmVyczsKCXByaXZhdGUgT2JqZWN0W10gZlN0cnVjdHVyZWREb2N1bWVudENoYW5nZWRMaXN0ZW5lcnM7Cglwcml2YXRlIE9iamVjdFtdIGZTdHJ1Y3R1cmVkRG9jdW1lbnRDaGFuZ2luZ0xpc3RlbmVyczsKCglwcml2YXRlIExpc3QgZkRvY3VtZW50UmV3cml0ZVNlc3Npb25MaXN0ZW5lcnM7CgoJcHJpdmF0ZSBJTGluZVRyYWNrZXIgZlRyYWNrZXI7Cglwcml2YXRlIElTdHJ1Y3R1cmVkVGV4dFVuZG9NYW5hZ2VyIGZVbmRvTWFuYWdlcjsKCXByaXZhdGUgSVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbiBsYXN0RG9jdW1lbnRSZWdpb247CgoJcHJpdmF0ZSBieXRlW10gbGlzdGVuZXJMb2NrID0gbmV3IGJ5dGVbMF07Cglwcml2YXRlIE51bGxEb2N1bWVudEV2ZW50IE5VTExfRE9DVU1FTlRfRVZFTlQ7CgoJLy8KCS8qKgoJICogaW4gY2FzZSBwcmVmZXJyZWQgZGVsaW1pdGVyIGlzIG5vdCBzZXQsIHdlJ2xsIGFzc3VtZSB0aGUgcGxhdGZvcm0KCSAqIGRlZmF1bHQgTm90ZTogaXQgaXMgbm90IGZpbmFsIHN0YXRpYyB0byBtYWtlIHN1cmUgaXQgd29uJ3QgYmUgaW5saW5lZAoJICogYnkgY29tcGlsZXIuCgkgKi8KCXByaXZhdGUgZmluYWwgU3RyaW5nIFBsYXRmb3JtTGluZURlbGltaXRlciA9IFN5c3RlbS5nZXRQcm9wZXJ0eSgibGluZS5zZXBhcmF0b3IiKTsgLy8kTk9OLU5MUy0xJAoJLyoqCgkgKiB0aGVvcmV0aWNhbGx5LCBhIGRvY3VtZW50IGNhbiBjb250YWluIG1peGVkIGxpbmUgZGVsaW1pdGVycwoJICovCglwcml2YXRlIFN0cmluZyBwcmVmZXJlZERlbGltaXRlcjsKCXByaXZhdGUgZmluYWwgU3RyaW5nIFJFQURfT05MWV9SRUdJT05TX0NBVEVHT1JZID0gIl9SRUFEX09OTFlfUkVHSU9OU19DQVRFR09SWV8iOyAvLyROT04tTkxTLTEkCgkvKioKCSAqIEN1cnJlbnQgcmV3cml0ZSBzZXNzaW9uLCBvciBub25lIGlmIG5vdCBwcmVzZW50bHkgcmV3cml0aW5nLgoJICovCglwcml2YXRlIERvY3VtZW50UmV3cml0ZVNlc3Npb24gZkFjdGl2ZVJld3JpdGVTZXNzaW9uOwoJLyoqCgkgKiBMYXN0IG1vZGlmaWNhdGlvbiBzdGFtcCwgYXV0b21hdGljYWxseSB1cGRhdGVkIG9uIGNoYW5nZS4KCSAqLwoJcHJpdmF0ZSBsb25nIGZNb2RpZmljYXRpb25TdGFtcDsKCS8qKgoJICogZGVidWcgdmFyaWFibGUgb25seQoJICogCgkgKiBAcGFyYW0gcGFyc2VyCgkgKi8KCXByaXZhdGUgbG9uZyBzdGFydFN0cmVhbVRpbWU7CgkvKioKCSAqIGRlYnVnIHZhcmlhYmxlIG9ubHkKCSAqIAoJICogQHBhcmFtIHBhcnNlcgoJICovCglwcml2YXRlIGxvbmcgc3RhcnRUaW1lOwoKCXB1YmxpYyBCYXNpY1N0cnVjdHVyZWREb2N1bWVudCgpIHsKCQlzdXBlcigpOwoJCWZDdXJyZW50RG9jdW1uZXRSZWdpb25DYWNoZSA9IG5ldyBDdXJyZW50RG9jdW1lbnRSZWdpb25DYWNoZSgpOwoJCWZTdG9yZSA9IG5ldyBTdHJ1Y3R1cmVkRG9jdW1lbnRUZXh0U3RvcmUoNTAsIDMwMCk7CgkJc2V0TGluZVRyYWNrZXIobmV3IERlZmF1bHRMaW5lVHJhY2tlcigpKTsKCQlOVUxMX0RPQ1VNRU5UX0VWRU5UID0gbmV3IE51bGxEb2N1bWVudEV2ZW50KCk7CgoJCWludGVybmFsX2FkZFBvc2l0aW9uQ2F0ZWdvcnkoUkVBRF9PTkxZX1JFR0lPTlNfQ0FURUdPUlkpOwoJCWludGVybmFsX2FkZFBvc2l0aW9uVXBkYXRlcihuZXcgRGVsZXRlRXF1YWxQb3NpdGlvblVwZGF0ZXIoUkVBRF9PTkxZX1JFR0lPTlNfQ0FURUdPUlkpKTsKCgl9CgoJLyoqCgkgKiBUaGlzIGlzIHRoZSBwcmltYXJ5IHdheSB0byBnZXQgYSBuZXcgc3RydWN0dXJlZERvY3VtZW50LiBJdHMgYmVzdCB0bwoJICogdXNlIHRoZSBmYWN0b3J5IG1ldGhvZHMgaW4gTW9kZWxNYW5nZXIgdG8gY3JlYXRlIGEgbmV3CgkgKiBJU3RydWN0dXJlZERvY3VtZW50LCBzaW5jZSBpdCB3aWxsIGdldCBhbmQgaW5pdGlhbGl6ZSB0aGUgcGFyc2VyCgkgKiBhY2NvcmRpbmcgdG8gdGhlIGRlc2lyZWQgY29udGVudCB0eXBlLgoJICovCglwdWJsaWMgQmFzaWNTdHJ1Y3R1cmVkRG9jdW1lbnQoUmVnaW9uUGFyc2VyIHBhcnNlcikgewoJCXRoaXMoKTsKCQlBc3NlcnQuaXNOb3ROdWxsKHBhcnNlciwgIlByb2dyYW0gRXJyb3I6IElTdHJ1Y3R1cmVkRG9jdW1lbnQgY2FuIG5vdCBiZSBjcmVhdGVkIHdpdGggbnVsbCBwYXJzZXIiKTsgLy8kTk9OLU5MUy0xJAoJCS8vIGdvIHRocm91Z2ggc2V0dGVyIGluIGNhc2UgdGhlcmUgaXMgc2lkZSBlZmZlY3RzCgkJaW50ZXJuYWxfc2V0UGFyc2VyKHBhcnNlcik7Cgl9CgoJcHJpdmF0ZSB2b2lkIF9jbGVhckRvY3VtZW50RXZlbnQoKSB7CgkJLy8gbm8gaGFyZCBhbmQgZmFzdCByZXF1aXJlbWVudCB0byBudWxsIG91dCAuLi4ganVzdCBzZWVtcyBsaWtlCgkJLy8gYSBnb29kIGlkZWEsIHNpbmNlIHdlIGFyZSBkb25lIHdpdGggaXQuCgkJZkRvY3VtZW50RXZlbnQgPSBudWxsOwoJfQoKCXByaXZhdGUgdm9pZCBfZmlyZURvY3VtZW50QWJvdXRUb0NoYW5nZShPYmplY3RbXSBsaXN0ZW5lcnMpIHsKCQkvLyBtb3N0IERvY3VtZW50QWJvdXRUb0JlQ2hhbmdlZCBsaXN0ZW5lcnMgZG8gbm90IGFudGljaXBhdGUKCQkvLyBEb2N1bWVudEV2ZW50ID09IG51bGwuIFNvIG1ha2Ugc3VyZSBkb2N1bWVudEV2ZW50IGlzIG5vdAoJCS8vIG51bGwuICh0aGlzIHNob3VsZCBuZXZlciBoYXBwZW4sIHlldCBpdCBkb2VzIHNvbWV0aW1lcykKCQlpZiAoZkRvY3VtZW50RXZlbnQgPT0gbnVsbCkgewoJCQlmRG9jdW1lbnRFdmVudCA9IG5ldyBOdWxsRG9jdW1lbnRFdmVudCgpOwoJCX0KCQkvLyB3ZSBtdXN0IGFzc2lnbiBsaXN0ZW5lcnMgdG8gbG9jYWwgdmFyaWFibGUsIHNpbmNlIHRoZSBhZGQgYW5kCgkJLy8gcmVtb3ZlCgkJLy8gbGlzdG5lcgoJCS8vIG1ldGhvZHMgY2FuIGNoYW5nZSB0aGUgYWN0dWFsIGluc3RhbmNlIG9mIHRoZSBsaXN0ZW5lciBhcnJheSBmcm9tCgkJLy8gYW5vdGhlciB0aHJlYWQKCQlpZiAobGlzdGVuZXJzICE9IG51bGwpIHsKCQkJT2JqZWN0W10gaG9sZExpc3RlbmVycyA9IGxpc3RlbmVyczsKCQkJLy8gTm90ZTogdGhlIGRvY0V2ZW50IGlzIGNyZWF0ZWQgaW4gcmVwbGFjZVRleHQgQVBJCgkJCS8vIGZpcmUKCQkJZm9yIChpbnQgaSA9IDA7IGkgPCBob2xkTGlzdGVuZXJzLmxlbmd0aDsgaSsrKSB7CgkJCQlpZiAoRGVidWcucGVyZlRlc3QgfHwgRGVidWcucGVyZlRlc3RTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudE9ubHkpIHsKCQkJCQlzdGFydFRpbWUgPSBTeXN0ZW0uY3VycmVudFRpbWVNaWxsaXMoKTsKCQkJCX0KCQkJCS8vIHNhZmVndWFyZCBmcm9tIGxpc3RlbmVycyB0aGF0IHRocm93IGV4Y2VwdGlvbnMKCQkJCXRyeSB7CgkJCQkJLy8gdGhpcyBpcyBhIHNhZmUgY2FzdCwgc2luY2UgYWRkTGlzdG5lcnMgcmVxdWlyZXMgYQoJCQkJCS8vIElTdHJ1Y3R1cmVkRG9jdW1lbnRMaXN0ZW5lcgoJCQkJCSgoSURvY3VtZW50TGlzdGVuZXIpIGhvbGRMaXN0ZW5lcnNbaV0pLmRvY3VtZW50QWJvdXRUb0JlQ2hhbmdlZChmRG9jdW1lbnRFdmVudCk7CgkJCQl9CgkJCQljYXRjaCAoRXhjZXB0aW9uIGV4Y2VwdGlvbikgewoJCQkJCUxvZ2dlci5sb2dFeGNlcHRpb24oZXhjZXB0aW9uKTsKCQkJCX0KCQkJCWlmIChEZWJ1Zy5wZXJmVGVzdCB8fCBEZWJ1Zy5wZXJmVGVzdFN0cnVjdHVyZWREb2N1bWVudEV2ZW50T25seSkgewoJCQkJCWxvbmcgc3RvcFRpbWUgPSBTeXN0ZW0uY3VycmVudFRpbWVNaWxsaXMoKTsKCQkJCQlTeXN0ZW0ub3V0LnByaW50bG4oIlxuXHRcdFx0XHQgSVN0cnVjdHVyZWREb2N1bWVudDo6ZmlyZVN0cnVjdHVyZWREb2N1bWVudEV2ZW50LiBUaW1lIHdhcyAiICsgKHN0b3BUaW1lIC0gc3RhcnRUaW1lKSArICIgbXNlY3MgdG8gZmlyZSBOZXdNb2RlbEV2ZW50IHRvIGluc3RhbmNlIG9mICIgKyBob2xkTGlzdGVuZXJzW2ldLmdldENsYXNzKCkpOyAvLyROT04tTkxTLTIkLy8kTk9OLU5MUy0xJAoJCQkJfQoJCQl9CgkJfQoJfQoKCXByaXZhdGUgdm9pZCBub3RpZnlEb2N1bWVudFBhcnRpdGlvbmVyc0Fib3V0VG9DaGFuZ2UoRG9jdW1lbnRFdmVudCBkb2N1bWVudEV2ZW50KSB7CgkJaWYgKGZEb2N1bWVudFBhcnRpdGlvbmVycyAhPSBudWxsKSB7CgkJCUl0ZXJhdG9yIGUgPSBmRG9jdW1lbnRQYXJ0aXRpb25lcnMudmFsdWVzKCkuaXRlcmF0b3IoKTsKCQkJd2hpbGUgKGUuaGFzTmV4dCgpKSB7CgkJCQlJRG9jdW1lbnRQYXJ0aXRpb25lciBwID0gKElEb2N1bWVudFBhcnRpdGlvbmVyKSBlLm5leHQoKTsKCQkJCS8vIHNhZmVndWFyZCBmcm9tIGxpc3RlbmVycyB0aGF0IHRocm93IGV4Y2VwdGlvbnMKCQkJCXRyeSB7CgkJCQkJcC5kb2N1bWVudEFib3V0VG9CZUNoYW5nZWQoZG9jdW1lbnRFdmVudCk7CgkJCQl9CgkJCQljYXRjaCAoRXhjZXB0aW9uIGV4Y2VwdGlvbikgewoJCQkJCUxvZ2dlci5sb2dFeGNlcHRpb24oZXhjZXB0aW9uKTsKCQkJCX0KCQkJfQoJCX0KCX0KCglwcml2YXRlIHZvaWQgX2ZpcmVEb2N1bWVudENoYW5nZWQoT2JqZWN0W10gbGlzdGVuZXJzLCBTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudCBldmVudCkgewoKCQkvLyB3ZSBtdXN0IGFzc2lnbiBsaXN0ZW5lcnMgdG8gbG9jYWwgdmFyaWFibGUsIHNpbmNlIHRoZSBhZGQgYW5kCgkJLy8gcmVtb3ZlCgkJLy8gbGlzdG5lcgoJCS8vIG1ldGhvZHMgY2FuIGNoYW5nZSB0aGUgYWN0dWFsIGluc3RhbmNlIG9mIHRoZSBsaXN0ZW5lciBhcnJheSBmcm9tCgkJLy8gYW5vdGhlciB0aHJlYWQKCQlpZiAobGlzdGVuZXJzICE9IG51bGwpIHsKCQkJT2JqZWN0W10gaG9sZExpc3RlbmVycyA9IGxpc3RlbmVyczsKCQkJLy8gTk9URTogZG9jdW1lbnQgZXZlbnQgaXMgY3JlYXRlZCBpbiByZXBsYWNlIFRleHQgQVBJIGFuZCBzZXRUZXh0CgkJCS8vIEFQSQoJCQkvLyBub3cgZmlyZQoJCQlmb3IgKGludCBpID0gMDsgaSA8IGhvbGRMaXN0ZW5lcnMubGVuZ3RoOyBpKyspIHsKCQkJCWlmIChEZWJ1Zy5wZXJmVGVzdCB8fCBEZWJ1Zy5wZXJmVGVzdFN0cnVjdHVyZWREb2N1bWVudEV2ZW50T25seSkgewoJCQkJCXN0YXJ0VGltZSA9IFN5c3RlbS5jdXJyZW50VGltZU1pbGxpcygpOwoJCQkJfQoKCQkJCS8vIHNhZmVndWFyZCBmcm9tIGxpc3RlbmVycyB0aGF0IHRocm93IGV4Y2VwdGlvbnMKCQkJCXRyeSB7CgkJCQkJLy8gdGhpcyBpcyBhIHNhZmUgY2FzdCwgc2luY2UgYWRkTGlzdG5lcnMgcmVxdWlyZXMgYQoJCQkJCS8vIElTdHJ1Y3R1cmVkRG9jdW1lbnRMaXN0ZW5lcgoJCQkJCS8vIE5vdGVzOiBmRG9jdW1lbnRFdmVudCBjYW4gYmUgInN1ZGRlbmx5IiBudWxsLCBpZiBvbmUgb2YKCQkJCQkvLyB0aGUKCQkJCQkvLyBwcmV2aW91cyBjaGFuZ2VzCgkJCQkJLy8gY2F1c2VkIGEgInNldFRleHQiIHRvIGJlIGNhbGxlZC4gVGhlIG9ubHkga25vd24gY2FzZSBvZgoJCQkJCS8vIHRoaXMKCQkJCQkvLyBpcyBhIG1vZGVsIHJlc2V0CgkJCQkJLy8gZHVlIHRvIHBhZ2UgZGlyZWN0aXZlIGNoYW5naW5nLiBFdmVudHVhbGx5IHdlIHNob3VsZAoJCQkJCS8vIGNoYW5nZQoJCQkJCS8vIGFyY2hldGVjdHVyZSB0byBoYXZlCgkJCQkJLy8gZXZlbnQgcXVlIGFuZCBiZSBhYmxlIHRvICJjYW5jZWwiIHBlbmRpbmcgZXZlbnRzLCBidXQKCQkJCQkvLyBmb3IKCQkJCQkvLyBub3csIHdlJ2xsIGp1c3QgcGFzcyBhCgkJCQkJLy8gTnVsbERvY3VtZW50RXZlbnQuIEJ5IHRoZSB3YXksIGl0IGlzIGltcG9ydGFudCB0byBzZW5kCgkJCQkJLy8gc29tZXRoaW5nLCBzaW5jZSBjbGllbnRzIG1pZ2h0CgkJCQkJLy8gaGF2ZSBpbmRldGVybWluYW50IHN0YXRlIGR1ZSB0byAiYWJvdXRUb0NoYW5nZSIgYmVpbmcKCQkJCQkvLyBzZW50CgkJCQkJLy8gZWFybGllci4KCQkJCQlpZiAoZkRvY3VtZW50RXZlbnQgPT0gbnVsbCkgewoJCQkJCQkoKElEb2N1bWVudExpc3RlbmVyKSBob2xkTGlzdGVuZXJzW2ldKS5kb2N1bWVudENoYW5nZWQoTlVMTF9ET0NVTUVOVF9FVkVOVCk7CgkJCQkJfQoJCQkJCWVsc2UgewoJCQkJCQlmRG9jdW1lbnRFdmVudC5mTW9kaWZpY2F0aW9uU3RhbXAgPSBnZXRNb2RpZmljYXRpb25TdGFtcCgpOwoJCQkJCQkoKElEb2N1bWVudExpc3RlbmVyKSBob2xkTGlzdGVuZXJzW2ldKS5kb2N1bWVudENoYW5nZWQoZkRvY3VtZW50RXZlbnQpOwoJCQkJCX0KCQkJCX0KCQkJCWNhdGNoIChFeGNlcHRpb24gZXhjZXB0aW9uKSB7CgkJCQkJTG9nZ2VyLmxvZ0V4Y2VwdGlvbihleGNlcHRpb24pOwoJCQkJfQoJCQkJaWYgKERlYnVnLnBlcmZUZXN0IHx8IERlYnVnLnBlcmZUZXN0U3RydWN0dXJlZERvY3VtZW50RXZlbnRPbmx5KSB7CgkJCQkJbG9uZyBzdG9wVGltZSA9IFN5c3RlbS5jdXJyZW50VGltZU1pbGxpcygpOwoJCQkJCVN5c3RlbS5vdXQucHJpbnRsbigiXG5cdFx0XHRcdCBJU3RydWN0dXJlZERvY3VtZW50OjpmaXJlU3RydWN0dXJlZERvY3VtZW50RXZlbnQuIFRpbWUgd2FzICIgKyAoc3RvcFRpbWUgLSBzdGFydFRpbWUpICsgIiBtc2VjcyB0byBmaXJlIE5ld01vZGVsRXZlbnQgdG8gaW5zdGFuY2Ugb2YgIiArIGhvbGRMaXN0ZW5lcnNbaV0uZ2V0Q2xhc3MoKSk7IC8vJE5PTi1OTFMtMiQvLyROT04tTkxTLTEkCgkJCQl9CgkJCX0KCQl9Cgl9CgoJcHJpdmF0ZSB2b2lkIG5vdGlmeURvY3VtZW50UGFydGl0aW9uZXJzRG9jdW1lbnRDaGFuZ2VkKERvY3VtZW50RXZlbnQgZG9jdW1lbnRFdmVudCkgewoJCWlmIChmRG9jdW1lbnRQYXJ0aXRpb25lcnMgIT0gbnVsbCkgewoJCQlJdGVyYXRvciBlID0gZkRvY3VtZW50UGFydGl0aW9uZXJzLnZhbHVlcygpLml0ZXJhdG9yKCk7CgkJCXdoaWxlIChlLmhhc05leHQoKSkgewoJCQkJSURvY3VtZW50UGFydGl0aW9uZXIgcCA9IChJRG9jdW1lbnRQYXJ0aXRpb25lcikgZS5uZXh0KCk7CgkJCQkvLyBzYWZlZ3VhcmQgZnJvbSBsaXN0ZW5lcnMgdGhhdCB0aHJvdyBleGNlcHRpb25zCgkJCQl0cnkgewoJCQkJCWlmIChwIGluc3RhbmNlb2YgSURvY3VtZW50UGFydGl0aW9uZXJFeHRlbnNpb24pIHsKCQkJCQkJLy8gSVJlZ2lvbiBjaGFuZ2VkUGFydGlvbiA9CgkJCQkJCSgoSURvY3VtZW50UGFydGl0aW9uZXJFeHRlbnNpb24pIHApLmRvY3VtZW50Q2hhbmdlZDIoZG9jdW1lbnRFdmVudCk7CgkJCQkJfQoJCQkJCWVsc2UgewoJCQkJCQlwLmRvY3VtZW50Q2hhbmdlZChkb2N1bWVudEV2ZW50KTsKCQkJCQl9CgkJCQl9CgkJCQljYXRjaCAoRXhjZXB0aW9uIGV4Y2VwdGlvbikgewoJCQkJCUxvZ2dlci5sb2dFeGNlcHRpb24oZXhjZXB0aW9uKTsKCQkJCX0KCQkJfQoJCX0KCX0KCgoJcHJpdmF0ZSB2b2lkIF9maXJlRXZlbnQoT2JqZWN0W10gbGlzdGVuZXJzLCBOb0NoYW5nZUV2ZW50IGV2ZW50KSB7CgkJLy8gd2UgbXVzdCBhc3NpZ24gbGlzdGVuZXJzIHRvIGxvY2FsIHZhcmlhYmxlLCBzaW5jZSB0aGUgYWRkIGFuZAoJCS8vIHJlbW92ZQoJCS8vIGxpc3RuZXIKCQkvLyBtZXRob2RzIGNhbiBjaGFuZ2UgdGhlIGFjdHVhbCBpbnN0YW5jZSBvZiB0aGUgbGlzdGVuZXIgYXJyYXkgZnJvbQoJCS8vIGFub3RoZXIgdGhyZWFkCgkJaWYgKGxpc3RlbmVycyAhPSBudWxsKSB7CgkJCU9iamVjdFtdIGhvbGRMaXN0ZW5lcnMgPSBsaXN0ZW5lcnM7CgkJCWZvciAoaW50IGkgPSAwOyBpIDwgaG9sZExpc3RlbmVycy5sZW5ndGg7IGkrKykgewoJCQkJaWYgKERlYnVnLnBlcmZUZXN0IHx8IERlYnVnLnBlcmZUZXN0U3RydWN0dXJlZERvY3VtZW50RXZlbnRPbmx5KSB7CgkJCQkJc3RhcnRUaW1lID0gU3lzdGVtLmN1cnJlbnRUaW1lTWlsbGlzKCk7CgkJCQl9CgkJCQkvLyBzYWZlZ3VhcmQgZnJvbSBsaXN0ZW5lcnMgdGhhdCB0aHJvdyBleGNlcHRpb25zCgkJCQl0cnkgewoJCQkJCS8vIHRoaXMgaXMgYSBzYWZlIGNhc3QsIHNpbmNlIGFkZExpc3RuZXJzIHJlcXVpcmVzIGEKCQkJCQkvLyBJU3RydWN0dXJlZERvY3VtZW50TGlzdGVuZXIKCQkJCQkoKElTdHJ1Y3R1cmVkRG9jdW1lbnRMaXN0ZW5lcikgaG9sZExpc3RlbmVyc1tpXSkubm9DaGFuZ2UoZXZlbnQpOwoJCQkJfQoJCQkJY2F0Y2ggKEV4Y2VwdGlvbiBleGNlcHRpb24pIHsKCQkJCQlMb2dnZXIubG9nRXhjZXB0aW9uKGV4Y2VwdGlvbik7CgkJCQl9CgkJCQlpZiAoRGVidWcucGVyZlRlc3QgfHwgRGVidWcucGVyZlRlc3RTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudE9ubHkpIHsKCQkJCQlsb25nIHN0b3BUaW1lID0gU3lzdGVtLmN1cnJlbnRUaW1lTWlsbGlzKCk7CgkJCQkJU3lzdGVtLm91dC5wcmludGxuKCJcblx0XHRcdFx0IElTdHJ1Y3R1cmVkRG9jdW1lbnQ6OmZpcmVTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudC4gVGltZSB3YXMgIiArIChzdG9wVGltZSAtIHN0YXJ0VGltZSkgKyAiIG1zZWNzIHRvIGZpcmUgTmV3TW9kZWxFdmVudCB0byBpbnN0YW5jZSBvZiAiICsgaG9sZExpc3RlbmVyc1tpXS5nZXRDbGFzcygpKTsgLy8kTk9OLU5MUy0yJC8vJE5PTi1OTFMtMSQKCQkJCX0KCQkJfQoJCX0KCX0KCglwcml2YXRlIHZvaWQgX2ZpcmVFdmVudChPYmplY3RbXSBsaXN0ZW5lcnMsIFJlZ2lvbkNoYW5nZWRFdmVudCBldmVudCkgewoJCS8vIHdlIG11c3QgYXNzaWduIGxpc3RlbmVycyB0byBsb2NhbCB2YXJpYWJsZSwgc2luY2UgdGhlIGFkZCBhbmQKCQkvLyByZW1vdmUKCQkvLyBsaXN0bmVyCgkJLy8gbWV0aG9kcyBjYW4gY2hhbmdlIHRoZSBhY3R1YWwgaW5zdGFuY2Ugb2YgdGhlIGxpc3RlbmVyIGFycmF5IGZyb20KCQkvLyBhbm90aGVyIHRocmVhZAoJCWlmIChsaXN0ZW5lcnMgIT0gbnVsbCkgewoJCQlPYmplY3RbXSBob2xkTGlzdGVuZXJzID0gbGlzdGVuZXJzOwoJCQlmb3IgKGludCBpID0gMDsgaSA8IGhvbGRMaXN0ZW5lcnMubGVuZ3RoOyBpKyspIHsKCQkJCWlmIChEZWJ1Zy5wZXJmVGVzdCB8fCBEZWJ1Zy5wZXJmVGVzdFN0cnVjdHVyZWREb2N1bWVudEV2ZW50T25seSkgewoJCQkJCXN0YXJ0VGltZSA9IFN5c3RlbS5jdXJyZW50VGltZU1pbGxpcygpOwoJCQkJfQoJCQkJLy8gc2FmZWd1YXJkIGZyb20gbGlzdGVuZXJzIHRoYXQgdGhyb3cgZXhjZXB0aW9ucwoJCQkJdHJ5IHsKCQkJCQkvLyB0aGlzIGlzIGEgc2FmZSBjYXN0LCBzaW5jZSBhZGRMaXN0bmVycyByZXF1aXJlcyBhCgkJCQkJLy8gSVN0cnVjdHVyZWREb2N1bWVudExpc3RlbmVyCgkJCQkJKChJU3RydWN0dXJlZERvY3VtZW50TGlzdGVuZXIpIGhvbGRMaXN0ZW5lcnNbaV0pLnJlZ2lvbkNoYW5nZWQoZXZlbnQpOwoJCQkJfQoJCQkJY2F0Y2ggKEV4Y2VwdGlvbiBleGNlcHRpb24pIHsKCQkJCQlMb2dnZXIubG9nRXhjZXB0aW9uKGV4Y2VwdGlvbik7CgkJCQl9CgkJCQlpZiAoRGVidWcucGVyZlRlc3QgfHwgRGVidWcucGVyZlRlc3RTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudE9ubHkpIHsKCQkJCQlsb25nIHN0b3BUaW1lID0gU3lzdGVtLmN1cnJlbnRUaW1lTWlsbGlzKCk7CgkJCQkJU3lzdGVtLm91dC5wcmludGxuKCJcblx0XHRcdFx0IElTdHJ1Y3R1cmVkRG9jdW1lbnQ6OmZpcmVTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudC4gVGltZSB3YXMgIiArIChzdG9wVGltZSAtIHN0YXJ0VGltZSkgKyAiIG1zZWNzIHRvIGZpcmUgTmV3TW9kZWxFdmVudCB0byBpbnN0YW5jZSBvZiAiICsgaG9sZExpc3RlbmVyc1tpXS5nZXRDbGFzcygpKTsgLy8kTk9OLU5MUy0yJC8vJE5PTi1OTFMtMSQKCQkJCX0KCQkJfQoJCX0KCX0KCglwcml2YXRlIHZvaWQgX2ZpcmVFdmVudChPYmplY3RbXSBsaXN0ZW5lcnMsIFJlZ2lvbnNSZXBsYWNlZEV2ZW50IGV2ZW50KSB7CgkJLy8gd2UgbXVzdCBhc3NpZ24gbGlzdGVuZXJzIHRvIGxvY2FsIHZhcmlhYmxlLCBzaW5jZSB0aGUgYWRkIGFuZAoJCS8vIHJlbW92ZQoJCS8vIGxpc3RuZXIKCQkvLyBtZXRob2RzIGNhbiBjaGFuZ2UgdGhlIGFjdHVhbCBpbnN0YW5jZSBvZiB0aGUgbGlzdGVuZXIgYXJyYXkgZnJvbQoJCS8vIGFub3RoZXIgdGhyZWFkCgkJaWYgKGxpc3RlbmVycyAhPSBudWxsKSB7CgkJCU9iamVjdFtdIGhvbGRMaXN0ZW5lcnMgPSBsaXN0ZW5lcnM7CgkJCWZvciAoaW50IGkgPSAwOyBpIDwgaG9sZExpc3RlbmVycy5sZW5ndGg7IGkrKykgewoJCQkJaWYgKERlYnVnLnBlcmZUZXN0IHx8IERlYnVnLnBlcmZUZXN0U3RydWN0dXJlZERvY3VtZW50RXZlbnRPbmx5KSB7CgkJCQkJc3RhcnRUaW1lID0gU3lzdGVtLmN1cnJlbnRUaW1lTWlsbGlzKCk7CgkJCQl9CgkJCQkvLyBzYWZlZ3VhcmQgZnJvbSBsaXN0ZW5lcnMgdGhhdCB0aHJvdyBleGNlcHRpb25zCgkJCQl0cnkgewoJCQkJCS8vIHRoaXMgaXMgYSBzYWZlIGNhc3QsIHNpbmNlIGFkZExpc3RuZXJzIHJlcXVpcmVzIGEKCQkJCQkvLyBJU3RydWN0dXJlZERvY3VtZW50TGlzdGVuZXIKCQkJCQkoKElTdHJ1Y3R1cmVkRG9jdW1lbnRMaXN0ZW5lcikgaG9sZExpc3RlbmVyc1tpXSkucmVnaW9uc1JlcGxhY2VkKGV2ZW50KTsKCQkJCX0KCQkJCWNhdGNoIChFeGNlcHRpb24gZXhjZXB0aW9uKSB7CgkJCQkJTG9nZ2VyLmxvZ0V4Y2VwdGlvbihleGNlcHRpb24pOwoJCQkJfQoJCQkJaWYgKERlYnVnLnBlcmZUZXN0IHx8IERlYnVnLnBlcmZUZXN0U3RydWN0dXJlZERvY3VtZW50RXZlbnRPbmx5KSB7CgkJCQkJbG9uZyBzdG9wVGltZSA9IFN5c3RlbS5jdXJyZW50VGltZU1pbGxpcygpOwoJCQkJCVN5c3RlbS5vdXQucHJpbnRsbigiXG5cdFx0XHRcdCBJU3RydWN0dXJlZERvY3VtZW50OjpmaXJlU3RydWN0dXJlZERvY3VtZW50RXZlbnQuIFRpbWUgd2FzICIgKyAoc3RvcFRpbWUgLSBzdGFydFRpbWUpICsgIiBtc2VjcyB0byBmaXJlIE5ld01vZGVsRXZlbnQgdG8gaW5zdGFuY2Ugb2YgIiArIGhvbGRMaXN0ZW5lcnNbaV0uZ2V0Q2xhc3MoKSk7IC8vJE5PTi1OTFMtMiQvLyROT04tTkxTLTEkCgkJCQl9CgkJCX0KCQl9Cgl9CgoJcHJpdmF0ZSB2b2lkIF9maXJlRXZlbnQoT2JqZWN0W10gbGlzdGVuZXJzLCBTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb25zUmVwbGFjZWRFdmVudCBldmVudCkgewoJCS8vIHdlIG11c3QgYXNzaWduIGxpc3RlbmVycyB0byBsb2NhbCB2YXJpYWJsZSwgc2luY2UgdGhlIGFkZCBhbmQKCQkvLyByZW1vdmUKCQkvLyBsaXN0bmVyCgkJLy8gbWV0aG9kcyBjYW4gY2hhbmdlIHRoZSBhY3R1YWwgaW5zdGFuY2Ugb2YgdGhlIGxpc3RlbmVyIGFycmF5IGZyb20KCQkvLyBhbm90aGVyIHRocmVhZAoJCWlmIChsaXN0ZW5lcnMgIT0gbnVsbCkgewoJCQlPYmplY3RbXSBob2xkTGlzdGVuZXJzID0gbGlzdGVuZXJzOwoJCQlmb3IgKGludCBpID0gMDsgaSA8IGhvbGRMaXN0ZW5lcnMubGVuZ3RoOyBpKyspIHsKCQkJCWlmIChEZWJ1Zy5wZXJmVGVzdCB8fCBEZWJ1Zy5wZXJmVGVzdFN0cnVjdHVyZWREb2N1bWVudEV2ZW50T25seSkgewoJCQkJCXN0YXJ0VGltZSA9IFN5c3RlbS5jdXJyZW50VGltZU1pbGxpcygpOwoJCQkJfQoJCQkJLy8gc2FmZWd1YXJkIGZyb20gbGlzdGVuZXJzIHRoYXQgdGhyb3cgZXhjZXB0aW9ucwoJCQkJdHJ5IHsKCQkJCQkvLyB0aGlzIGlzIGEgc2FmZSBjYXN0LCBzaW5jZSBhZGRMaXN0bmVycyByZXF1aXJlcyBhCgkJCQkJLy8gSVN0cnVjdHVyZWREb2N1bWVudExpc3RlbmVyCgkJCQkJKChJU3RydWN0dXJlZERvY3VtZW50TGlzdGVuZXIpIGhvbGRMaXN0ZW5lcnNbaV0pLm5vZGVzUmVwbGFjZWQoZXZlbnQpOwoJCQkJfQoJCQkJY2F0Y2ggKEV4Y2VwdGlvbiBleGNlcHRpb24pIHsKCQkJCQlMb2dnZXIubG9nRXhjZXB0aW9uKGV4Y2VwdGlvbik7CgkJCQl9CgkJCQlpZiAoRGVidWcucGVyZlRlc3QgfHwgRGVidWcucGVyZlRlc3RTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudE9ubHkpIHsKCQkJCQlsb25nIHN0b3BUaW1lID0gU3lzdGVtLmN1cnJlbnRUaW1lTWlsbGlzKCk7CgkJCQkJU3lzdGVtLm91dC5wcmludGxuKCJcblx0XHRcdFx0IElTdHJ1Y3R1cmVkRG9jdW1lbnQ6OmZpcmVTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudC4gVGltZSB3YXMgIiArIChzdG9wVGltZSAtIHN0YXJ0VGltZSkgKyAiIG1zZWNzIHRvIGZpcmUgTmV3TW9kZWxFdmVudCB0byBpbnN0YW5jZSBvZiAiICsgaG9sZExpc3RlbmVyc1tpXS5nZXRDbGFzcygpKTsgLy8kTk9OLU5MUy0yJC8vJE5PTi1OTFMtMSQKCQkJCX0KCQkJfQoJCX0KCX0KCglwcml2YXRlIHZvaWQgX2ZpcmVTdHJ1Y3R1cmVkRG9jdW1lbnRBYm91dFRvQ2hhbmdlKE9iamVjdFtdIGxpc3RlbmVycykgewoJCS8vIHdlIG11c3QgYXNzaWduIGxpc3RlbmVycyB0byBsb2NhbCB2YXJpYWJsZSwgc2luY2UgdGhlIGFkZCBhbmQKCQkvLyByZW1vdmUKCQkvLyBsaXN0bmVyCgkJLy8gbWV0aG9kcyBjYW4gY2hhbmdlIHRoZSBhY3R1YWwgaW5zdGFuY2Ugb2YgdGhlIGxpc3RlbmVyIGFycmF5IGZyb20KCQkvLyBhbm90aGVyIHRocmVhZAoJCWlmIChsaXN0ZW5lcnMgIT0gbnVsbCkgewoJCQlPYmplY3RbXSBob2xkTGlzdGVuZXJzID0gbGlzdGVuZXJzOwoJCQkvLyBOb3RlOiB0aGUgZG9jRXZlbnQgaXMgY3JlYXRlZCBpbiByZXBsYWNlVGV4dCBBUEkKCQkJLy8gZmlyZQoJCQlmb3IgKGludCBpID0gMDsgaSA8IGhvbGRMaXN0ZW5lcnMubGVuZ3RoOyBpKyspIHsKCQkJCWlmIChEZWJ1Zy5wZXJmVGVzdCB8fCBEZWJ1Zy5wZXJmVGVzdFN0cnVjdHVyZWREb2N1bWVudEV2ZW50T25seSkgewoJCQkJCXN0YXJ0VGltZSA9IFN5c3RlbS5jdXJyZW50VGltZU1pbGxpcygpOwoJCQkJfQoJCQkJLy8gc2FmZWd1YXJkIGZyb20gbGlzdGVuZXJzIHRoYXQgdGhyb3cgZXhjZXB0aW9ucwoJCQkJdHJ5IHsKCQkJCQkvLyBub3RpY2UgdGhlIEFib3V0VG9CZUNoYW5nZWRFdmVudCBpcyBjcmVhdGVkIGZyb20gdGhlCgkJCQkJLy8gRG9jdW1lbnRFdmVudCwgc2luY2UgaXQgaXMgKG5lYXJseSkKCQkJCQkvLyB0aGUgc2FtZSBpbmZvcm1hdGlvbi4gP1doYXQgdG8gZG8gYWJvdXQKCQkJCQkvLyBvcmlnaW5hbFJlcXVlc3Rlcj8KCQkJCQlpZiAoZkRvY3VtZW50RXZlbnQgPT0gbnVsbCkgewoJCQkJCQlmRG9jdW1lbnRFdmVudCA9IG5ldyBOdWxsRG9jdW1lbnRFdmVudCgpOwoJCQkJCX0KCQkJCQlBYm91dFRvQmVDaGFuZ2VkRXZlbnQgYWJvdXRUb0JlQ2hhbmdlZEV2ZW50ID0gbmV3IEFib3V0VG9CZUNoYW5nZWRFdmVudCh0aGlzLCBudWxsLCBmRG9jdW1lbnRFdmVudC5nZXRUZXh0KCksIGZEb2N1bWVudEV2ZW50LmdldE9mZnNldCgpLCBmRG9jdW1lbnRFdmVudC5nZXRMZW5ndGgoKSk7CgkJCQkJLy8gdGhpcyBpcyBhIHNhZmUgY2FzdCwgc2luY2UgYWRkTGlzdG5lcnMgcmVxdWlyZXMgYQoJCQkJCS8vIElTdHJ1Y3R1cmVkRG9jdW1lbnRMaXN0ZW5lcgoJCQkJCSgoSU1vZGVsQWJvdXRUb0JlQ2hhbmdlZExpc3RlbmVyKSBob2xkTGlzdGVuZXJzW2ldKS5tb2RlbEFib3V0VG9CZUNoYW5nZWQoYWJvdXRUb0JlQ2hhbmdlZEV2ZW50KTsKCQkJCX0KCQkJCWNhdGNoIChFeGNlcHRpb24gZXhjZXB0aW9uKSB7CgkJCQkJTG9nZ2VyLmxvZ0V4Y2VwdGlvbihleGNlcHRpb24pOwoJCQkJfQoJCQkJaWYgKERlYnVnLnBlcmZUZXN0IHx8IERlYnVnLnBlcmZUZXN0U3RydWN0dXJlZERvY3VtZW50RXZlbnRPbmx5KSB7CgkJCQkJbG9uZyBzdG9wVGltZSA9IFN5c3RlbS5jdXJyZW50VGltZU1pbGxpcygpOwoJCQkJCVN5c3RlbS5vdXQucHJpbnRsbigiXG5cdFx0XHRcdCBJU3RydWN0dXJlZERvY3VtZW50OjpmaXJlU3RydWN0dXJlZERvY3VtZW50RXZlbnQuIFRpbWUgd2FzICIgKyAoc3RvcFRpbWUgLSBzdGFydFRpbWUpICsgIiBtc2VjcyB0byBmaXJlIE5ld01vZGVsRXZlbnQgdG8gaW5zdGFuY2Ugb2YgIiArIGhvbGRMaXN0ZW5lcnNbaV0uZ2V0Q2xhc3MoKSk7IC8vJE5PTi1OTFMtMiQvLyROT04tTkxTLTEkCgkJCQl9CgkJCX0KCQl9Cgl9CgoJcHJvdGVjdGVkIHZvaWQgYWNxdWlyZUxvY2soKSB7CgkJLy8gZG8gbm90aGluZyBoZXJlIGluIHN1cGVyIGNsYXNzCgl9CgoJLyoqCgkgKiBhZGRNb2RlbEFib3V0VG9CZUNoYW5nZWRMaXN0ZW5lciBtZXRob2QgY29tbWVudC4KCSAqLwoJcHVibGljIHZvaWQgYWRkRG9jdW1lbnRBYm91dFRvQ2hhbmdlTGlzdGVuZXIoSU1vZGVsQWJvdXRUb0JlQ2hhbmdlZExpc3RlbmVyIGxpc3RlbmVyKSB7CgkJc3luY2hyb25pemVkIChsaXN0ZW5lckxvY2spIHsKCgkJCS8vIG1ha2Ugc3VyZSBsaXN0ZW5lciBpcyBub3QgYWxyZWFkeSBpbiBsaXN0ZW5pbmcKCQkJLy8gKGFuZCBpZiBpdCBpcywgcHJpbnQgYSB3YXJuaW5nIHRvIGFpZCBkZWJ1Z2dpbmcsIGlmIG5lZWRlZCkKCQkJaWYgKCFVdGlsaXRpZXMuY29udGFpbnMoZlN0cnVjdHVyZWREb2N1bWVudEFib3V0VG9DaGFuZ2VMaXN0ZW5lcnMsIGxpc3RlbmVyKSkgewoJCQkJaW50IG9sZFNpemUgPSAwOwoJCQkJaWYgKGZTdHJ1Y3R1cmVkRG9jdW1lbnRBYm91dFRvQ2hhbmdlTGlzdGVuZXJzICE9IG51bGwpIHsKCQkJCQkvLyBub3JtYWxseSB3b24ndCBiZSBudWxsLCBidXQgd2UgbmVlZCB0byBiZSBzdXJlLCBmb3IKCQkJCQkvLyBmaXJzdAoJCQkJCS8vIHRpbWUgdGhyb3VnaAoJCQkJCW9sZFNpemUgPSBmU3RydWN0dXJlZERvY3VtZW50QWJvdXRUb0NoYW5nZUxpc3RlbmVycy5sZW5ndGg7CgkJCQl9CgkJCQlpbnQgbmV3U2l6ZSA9IG9sZFNpemUgKyAxOwoJCQkJT2JqZWN0W10gbmV3TGlzdGVuZXJzID0gbmV3IE9iamVjdFtuZXdTaXplXTsKCQkJCWlmIChmU3RydWN0dXJlZERvY3VtZW50QWJvdXRUb0NoYW5nZUxpc3RlbmVycyAhPSBudWxsKSB7CgkJCQkJU3lzdGVtLmFycmF5Y29weShmU3RydWN0dXJlZERvY3VtZW50QWJvdXRUb0NoYW5nZUxpc3RlbmVycywgMCwgbmV3TGlzdGVuZXJzLCAwLCBvbGRTaXplKTsKCQkJCX0KCQkJCS8vIGFkZCBsaXN0ZW5lciB0byBsYXN0IHBvc2l0aW9uCgkJCQluZXdMaXN0ZW5lcnNbbmV3U2l6ZSAtIDFdID0gbGlzdGVuZXI7CgkJCQkvLwoJCQkJLy8gbm93IHN3aXRjaCBuZXcgZm9yIG9sZAoJCQkJZlN0cnVjdHVyZWREb2N1bWVudEFib3V0VG9DaGFuZ2VMaXN0ZW5lcnMgPSBuZXdMaXN0ZW5lcnM7CgkJCQkvLwoJCQl9CgkJfQoJfQoKCS8qKgoJICogVGhlIFN0cnVjdHVyZWREb2N1bWVudExpc3RuZXJzIGFuZCBNb2RlbENoYWduZWRMaXN0ZW5lcnMgYXJlIHZlcnkKCSAqIHNpbWlsYXIuIFRoZXkgYm90aCByZWNlaXZlIGlkZW50aWNhbCBldmVudHMuIFRoZSBkaWZmZXJlbmNlIGlzIHRoZQoJICogdGltaW5nLiBUaGUgInB1cmUiIFN0cnVjdHVyZWREb2N1bWVudExpc3RuZXJzIGFyZSBub3RpZmllZCBhZnRlciB0aGUKCSAqIHN0cnVjdHVyZWREb2N1bWVudCBoYXMgYmVlbiBjaGFuZ2VkLCBidXQgYmVmb3JlIG90aGVyLCByZWxhdGVkIG1vZGVscwoJICogbWF5IGhhdmUgYmVlbiBjaGFuZ2VkIHN1Y2ggYXMgdGhlIFN0cnVjdHVyYWwgTW9kZWwuIFRoZSBTdHJ1Y3R1cmFsCgkgKiBtb2RlbCBpcyBpbiBmYWN0IGl0c2VsZiBhICJwdXJlIiBTdHJ1Y3R1cmVkRG9jdW1lbnRMaXN0bmVyLiBUaGUKCSAqIE1vZGVsQ2hhbmdlZExpc3RlbmVycyBjYW4gcmVzdCBhc3N1cmVkIHRoYXQgYWxsIG1vZGVscyBhbmQgZGF0YSBoYXZlCgkgKiBiZWVuIHVwZGF0ZWQgZnJvbSB0aGUgY2hhbmdlIGJ5IHRoZSB0aWVtIHRoZXkgYXJlIG5vdGlmaWVkLiBUaGlzIGlzCgkgKiBlc3BlY2lhbGx5IGltcG9ydGFudCBmb3IgdGhlIHRleHQgd2lkZ2V0LCBmb3IgZXhhbXBsZSwgd2hpY2ggbWF5IHJlbHkKCSAqIG9uIGJvdGggc3RydWN0dXJlZERvY3VtZW50IGFuZCBzdHJ1Y3R1cmFsIG1vZGVsIGluZm9ybWF0aW9uLgoJICovCglwdWJsaWMgdm9pZCBhZGREb2N1bWVudENoYW5nZWRMaXN0ZW5lcihJU3RydWN0dXJlZERvY3VtZW50TGlzdGVuZXIgbGlzdGVuZXIpIHsKCQlzeW5jaHJvbml6ZWQgKGxpc3RlbmVyTG9jaykgewoKCQkJaWYgKERlYnVnLmRlYnVnU3RydWN0dXJlZERvY3VtZW50KSB7CgkJCQlTeXN0ZW0ub3V0LnByaW50bG4oIklTdHJ1Y3R1cmVkRG9jdW1lbnQ6OmFkZE1vZGVsQ2hhbmdlZExpc3RlbmVyLiBSZXF1ZXN0IHRvIGFkZCBhbiBpbnN0YW5jZSBvZiAiICsgbGlzdGVuZXIuZ2V0Q2xhc3MoKSArICIgYXMgYSBsaXN0ZW5lciBvbiBzdHJ1Y3R1cmVkRG9jdW1lbnQuIik7IC8vJE5PTi1OTFMtMiQvLyROT04tTkxTLTEkCgkJCX0KCQkJLy8gbWFrZSBzdXJlIGxpc3RlbmVyIGlzIG5vdCBhbHJlYWR5IGluIGxpc3RlbmluZwoJCQkvLyAoYW5kIGlmIGl0IGlzLCBwcmludCBhIHdhcm5pbmcgdG8gYWlkIGRlYnVnZ2luZywgaWYgbmVlZGVkKQoJCQlpZiAoVXRpbGl0aWVzLmNvbnRhaW5zKGZTdHJ1Y3R1cmVkRG9jdW1lbnRDaGFuZ2VkTGlzdGVuZXJzLCBsaXN0ZW5lcikpIHsKCQkJCWlmIChEZWJ1Zy5kaXNwbGF5V2FybmluZ3MpIHsKCQkJCQlTeXN0ZW0ub3V0LnByaW50bG4oIklTdHJ1Y3R1cmVkRG9jdW1lbnQ6OmFkZE1vZGVsQ2hhbmdlZExpc3RlbmVyLiBsaXN0ZW5lciAiICsgbGlzdGVuZXIgKyAiIHdhcyBhZGRlZGVkIG1vcmUgdGhhbiBvbmNlLiAiKTsgLy8kTk9OLU5MUy0yJC8vJE5PTi1OTFMtMSQKCQkJCX0KCQkJfQoJCQllbHNlIHsKCQkJCWlmIChEZWJ1Zy5kZWJ1Z1N0cnVjdHVyZWREb2N1bWVudCkgewoJCQkJCVN5c3RlbS5vdXQucHJpbnRsbigiSVN0cnVjdHVyZWREb2N1bWVudDo6YWRkTW9kZWxDaGFuZ2VkTGlzdGVuZXIuIEFkZGluZyBhbiBpbnN0YW5jZSBvZiAiICsgbGlzdGVuZXIuZ2V0Q2xhc3MoKSArICIgYXMgYSBsaXN0ZW5lciBvbiBzdHJ1Y3R1cmVkRG9jdW1lbnQuIik7IC8vJE5PTi1OTFMtMiQvLyROT04tTkxTLTEkCgkJCQl9CgkJCQlpbnQgb2xkU2l6ZSA9IDA7CgkJCQlpZiAoZlN0cnVjdHVyZWREb2N1bWVudENoYW5nZWRMaXN0ZW5lcnMgIT0gbnVsbCkgewoJCQkJCS8vIG5vcm1hbGx5IHdvbid0IGJlIG51bGwsIGJ1dCB3ZSBuZWVkIHRvIGJlIHN1cmUsIGZvcgoJCQkJCS8vIGZpcnN0CgkJCQkJLy8gdGltZSB0aHJvdWdoCgkJCQkJb2xkU2l6ZSA9IGZTdHJ1Y3R1cmVkRG9jdW1lbnRDaGFuZ2VkTGlzdGVuZXJzLmxlbmd0aDsKCQkJCX0KCQkJCWludCBuZXdTaXplID0gb2xkU2l6ZSArIDE7CgkJCQlPYmplY3RbXSBuZXdMaXN0ZW5lcnMgPSBuZXcgT2JqZWN0W25ld1NpemVdOwoJCQkJaWYgKGZTdHJ1Y3R1cmVkRG9jdW1lbnRDaGFuZ2VkTGlzdGVuZXJzICE9IG51bGwpIHsKCQkJCQlTeXN0ZW0uYXJyYXljb3B5KGZTdHJ1Y3R1cmVkRG9jdW1lbnRDaGFuZ2VkTGlzdGVuZXJzLCAwLCBuZXdMaXN0ZW5lcnMsIDAsIG9sZFNpemUpOwoJCQkJfQoJCQkJLy8gYWRkIGxpc3RlbmVyIHRvIGxhc3QgcG9zaXRpb24KCQkJCW5ld0xpc3RlbmVyc1tuZXdTaXplIC0gMV0gPSBsaXN0ZW5lcjsKCQkJCS8vCgkJCQkvLyBub3cgc3dpdGNoIG5ldyBmb3Igb2xkCgkJCQlmU3RydWN0dXJlZERvY3VtZW50Q2hhbmdlZExpc3RlbmVycyA9IG5ld0xpc3RlbmVyczsKCQkJCS8vCgkJCQkvLyB3aGVuIGEgbGlzdGVuZXIgaXMgYWRkZWQsCgkJCQkvLyBzZW5kIHRoZSBuZXcgbW9kZWwgZXZlbnQgdG8gdGhhdCBvbmUgcGFydGljdWxhciBsaXN0ZW5lciwKCQkJCS8vIHNvIGl0CgkJCQkvLyBjYW4gaW5pdGlhbGl6ZSBpdHNlbGYgd2l0aCB0aGUgY3VycmVudCBzdGF0ZSBvZiB0aGUgbW9kZWwKCQkJCS8vIGxpc3RlbmVyLm5ld01vZGVsKG5ldyBOZXdNb2RlbEV2ZW50KHRoaXMsIGxpc3RlbmVyKSk7CgkJCX0KCQl9Cgl9CgoJcHVibGljIHZvaWQgYWRkRG9jdW1lbnRDaGFuZ2luZ0xpc3RlbmVyKElTdHJ1Y3R1cmVkRG9jdW1lbnRMaXN0ZW5lciBsaXN0ZW5lcikgewoJCXN5bmNocm9uaXplZCAobGlzdGVuZXJMb2NrKSB7CgoJCQlpZiAoRGVidWcuZGVidWdTdHJ1Y3R1cmVkRG9jdW1lbnQpIHsKCQkJCVN5c3RlbS5vdXQucHJpbnRsbigiSVN0cnVjdHVyZWREb2N1bWVudDo6YWRkU3RydWN0dXJlZERvY3VtZW50TGlzdGVuZXIuIFJlcXVlc3QgdG8gYWRkIGFuIGluc3RhbmNlIG9mICIgKyBsaXN0ZW5lci5nZXRDbGFzcygpICsgIiBhcyBhIGxpc3RlbmVyIG9uIHN0cnVjdHVyZWREb2N1bWVudC4iKTsgLy8kTk9OLU5MUy0yJC8vJE5PTi1OTFMtMSQKCQkJfQoJCQkvLyBtYWtlIHN1cmUgbGlzdGVuZXIgaXMgbm90IGFscmVhZHkgaW4gbGlzdGVuaW5nCgkJCS8vIChhbmQgaWYgaXQgaXMsIHByaW50IGEgd2FybmluZyB0byBhaWQgZGVidWdnaW5nLCBpZiBuZWVkZWQpCgkJCWlmIChVdGlsaXRpZXMuY29udGFpbnMoZlN0cnVjdHVyZWREb2N1bWVudENoYW5naW5nTGlzdGVuZXJzLCBsaXN0ZW5lcikpIHsKCQkJCWlmIChEZWJ1Zy5kaXNwbGF5V2FybmluZ3MpIHsKCQkJCQlTeXN0ZW0ub3V0LnByaW50bG4oIklTdHJ1Y3R1cmVkRG9jdW1lbnQ6OmFkZFN0cnVjdHVyZWREb2N1bWVudExpc3RlbmVyLiBsaXN0ZW5lciAiICsgbGlzdGVuZXIgKyAiIHdhcyBhZGRlZGVkIG1vcmUgdGhhbiBvbmNlLiAiKTsgLy8kTk9OLU5MUy0yJC8vJE5PTi1OTFMtMSQKCQkJCX0KCQkJfQoJCQllbHNlIHsKCQkJCWlmIChEZWJ1Zy5kZWJ1Z1N0cnVjdHVyZWREb2N1bWVudCkgewoJCQkJCVN5c3RlbS5vdXQucHJpbnRsbigiSVN0cnVjdHVyZWREb2N1bWVudDo6YWRkU3RydWN0dXJlZERvY3VtZW50TGlzdGVuZXIuIEFkZGluZyBhbiBpbnN0YW5jZSBvZiAiICsgbGlzdGVuZXIuZ2V0Q2xhc3MoKSArICIgYXMgYSBsaXN0ZW5lciBvbiBzdHJ1Y3R1cmVkRG9jdW1lbnQuIik7IC8vJE5PTi1OTFMtMiQvLyROT04tTkxTLTEkCgkJCQl9CgkJCQlpbnQgb2xkU2l6ZSA9IDA7CgkJCQlpZiAoZlN0cnVjdHVyZWREb2N1bWVudENoYW5naW5nTGlzdGVuZXJzICE9IG51bGwpIHsKCQkJCQkvLyBub3JtYWxseSB3b24ndCBiZSBudWxsLCBidXQgd2UgbmVlZCB0byBiZSBzdXJlLCBmb3IKCQkJCQkvLyBmaXJzdAoJCQkJCS8vIHRpbWUgdGhyb3VnaAoJCQkJCW9sZFNpemUgPSBmU3RydWN0dXJlZERvY3VtZW50Q2hhbmdpbmdMaXN0ZW5lcnMubGVuZ3RoOwoJCQkJfQoJCQkJaW50IG5ld1NpemUgPSBvbGRTaXplICsgMTsKCQkJCU9iamVjdFtdIG5ld0xpc3RlbmVycyA9IG5ldyBPYmplY3RbbmV3U2l6ZV07CgkJCQlpZiAoZlN0cnVjdHVyZWREb2N1bWVudENoYW5naW5nTGlzdGVuZXJzICE9IG51bGwpIHsKCQkJCQlTeXN0ZW0uYXJyYXljb3B5KGZTdHJ1Y3R1cmVkRG9jdW1lbnRDaGFuZ2luZ0xpc3RlbmVycywgMCwgbmV3TGlzdGVuZXJzLCAwLCBvbGRTaXplKTsKCQkJCX0KCQkJCS8vIGFkZCBsaXN0ZW5lciB0byBsYXN0IHBvc2l0aW9uCgkJCQluZXdMaXN0ZW5lcnNbbmV3U2l6ZSAtIDFdID0gbGlzdGVuZXI7CgkJCQkvLwoJCQkJLy8gbm93IHN3aXRjaCBuZXcgZm9yIG9sZAoJCQkJZlN0cnVjdHVyZWREb2N1bWVudENoYW5naW5nTGlzdGVuZXJzID0gbmV3TGlzdGVuZXJzOwoJCQkJLy8KCQkJCS8vIHdoZW4gYSBsaXN0ZW5lciBpcyBhZGRlZCwKCQkJCS8vIHNlbmQgdGhlIG5ldyBtb2RlbCBldmVudCB0byB0aGF0IG9uZSBwYXJ0aWN1bGFyIGxpc3RlbmVyLAoJCQkJLy8gc28gaXQKCQkJCS8vIGNhbiBpbml0aWFsaXplIGl0c2VsZiB3aXRoIHRoZSBjdXJyZW50IHN0YXRlIG9mIHRoZSBtb2RlbAoJCQkJLy8gbGlzdGVuZXIubmV3TW9kZWwobmV3IE5ld01vZGVsRXZlbnQodGhpcywgbGlzdGVuZXIpKTsKCQkJfQoJCX0KCX0KCgkvKioKCSAqIFdlIG1hbmFnZSBvdXIgb3duIGRvY3VtZW50IGxpc3RuZXJzLCBpbnN0ZWFkIG9mIGRlbGVnYXRpbmcgdG8gb3VyCgkgKiBwYXJlbnREb2N1bWVudCwgc28gd2UgY2FuIGZpcmUgYXQgdmVyeSBlbmQgKGFuZCBub3Qgd2hlbiB0aGUKCSAqIHBhcmVudERvY3VtZW50IGNoYW5nZXMpLgoJICogCgkgKi8KCXB1YmxpYyB2b2lkIGFkZERvY3VtZW50TGlzdGVuZXIoSURvY3VtZW50TGlzdGVuZXIgbGlzdGVuZXIpIHsKCQlzeW5jaHJvbml6ZWQgKGxpc3RlbmVyTG9jaykgewoKCQkJLy8gbWFrZSBzdXJlIGxpc3RlbmVyIGlzIG5vdCBhbHJlYWR5IGluIGxpc3RlbmluZwoJCQkvLyAoYW5kIGlmIGl0IGlzLCBwcmludCBhIHdhcm5pbmcgdG8gYWlkIGRlYnVnZ2luZywgaWYgbmVlZGVkKQoJCQlpZiAoIVV0aWxpdGllcy5jb250YWlucyhmRG9jdW1lbnRMaXN0ZW5lcnMsIGxpc3RlbmVyKSkgewoJCQkJaW50IG9sZFNpemUgPSAwOwoJCQkJaWYgKGZEb2N1bWVudExpc3RlbmVycyAhPSBudWxsKSB7CgkJCQkJLy8gbm9ybWFsbHkgd29uJ3QgYmUgbnVsbCwgYnV0IHdlIG5lZWQgdG8gYmUgc3VyZSwgZm9yCgkJCQkJLy8gZmlyc3QKCQkJCQkvLyB0aW1lIHRocm91Z2gKCQkJCQlvbGRTaXplID0gZkRvY3VtZW50TGlzdGVuZXJzLmxlbmd0aDsKCQkJCX0KCQkJCWludCBuZXdTaXplID0gb2xkU2l6ZSArIDE7CgkJCQlJRG9jdW1lbnRMaXN0ZW5lcltdIG5ld0xpc3RlbmVycyA9IG51bGw7CgkJCQluZXdMaXN0ZW5lcnMgPSBuZXcgSURvY3VtZW50TGlzdGVuZXJbbmV3U2l6ZV07CgkJCQlpZiAoZkRvY3VtZW50TGlzdGVuZXJzICE9IG51bGwpIHsKCQkJCQlTeXN0ZW0uYXJyYXljb3B5KGZEb2N1bWVudExpc3RlbmVycywgMCwgbmV3TGlzdGVuZXJzLCAwLCBvbGRTaXplKTsKCQkJCX0KCQkJCS8vIGFkZCBsaXN0ZW5lciB0byBsYXN0IHBvc2l0aW9uCgkJCQluZXdMaXN0ZW5lcnNbbmV3U2l6ZSAtIDFdID0gbGlzdGVuZXI7CgkJCQkvLyBub3cgc3dpdGNoIG5ldyBmb3Igb2xkCgkJCQlmRG9jdW1lbnRMaXN0ZW5lcnMgPSBuZXdMaXN0ZW5lcnM7CgkJCX0KCQl9Cgl9CgoJLyoKCSAqIEBzZWUgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5JRG9jdW1lbnQjYWRkRG9jdW1lbnRQYXJ0aXRpb25pbmdMaXN0ZW5lcihvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklEb2N1bWVudFBhcnRpdGlvbmluZ0xpc3RlbmVyKQoJICogCgkgKiBSZWdpc3RlcnMgdGhlIGRvY3VtZW50IHBhcnRpdGlvbmluZyBsaXN0ZW5lciB3aXRoIHRoZSBkb2N1bWVudC4gQWZ0ZXIKCSAqIHJlZ2lzdHJhdGlvbiB0aGUgSURvY3VtZW50UGFydGl0aW9uaW5nTGlzdGVuZXIgaXMgaW5mb3JtZWQgYWJvdXQgZWFjaAoJICogcGFydGl0aW9uIGNoYW5nZSBjYXVzZSBieSBhIGRvY3VtZW50IG1hbmlwdWxhdGlvbi4gSWYgYSBkb2N1bWVudAoJICogcGFydGl0aW9uaW5nIGxpc3RlbmVyIGlzIGFsc28gYSBkb2N1bWVudCBsaXN0ZW5lciwgdGhlIGZvbGxvd2luZwoJICogbm90aWZpY2F0aW9uIHNlcXVlbmNlIGlzIGd1YXJhbnRlZWQgaWYgYSBkb2N1bWVudCBtYW5pcHVsYXRpb24gY2hhbmdlcwoJICogdGhlIGRvY3VtZW50IHBhcnRpdGlvbmluZzogMSkKCSAqIGxpc3RlbmVyLmRvY3VtZW50QWJvdXRUb0JlQ2hhbmdlZChEb2N1bWVudEV2ZW50KTsgMikKCSAqIGxpc3RlbmVyLmRvY3VtZW50UGFydGl0aW9uaW5nQ2hhbmdlZCgpOyAzKQoJICogbGlzdGVuZXIuZG9jdW1lbnRDaGFuZ2VkKERvY3VtZW50RXZlbnQpOyBJZiB0aGUgbGlzdGVuZXIgaXMgYWxyZWFkeQoJICogcmVnaXN0ZXJlZCBub3RoaW5nIGhhcHBlbnMuCgkgKiAKCSAqIEBzZWUgSURvY3VtZW50UGFydGl0aW9uaW5nTGlzdGVuZXIKCSAqLwoKCXB1YmxpYyB2b2lkIGFkZERvY3VtZW50UGFydGl0aW9uaW5nTGlzdGVuZXIoSURvY3VtZW50UGFydGl0aW9uaW5nTGlzdGVuZXIgbGlzdGVuZXIpIHsKCQlzeW5jaHJvbml6ZWQgKGxpc3RlbmVyTG9jaykgewoKCQkJQXNzZXJ0LmlzTm90TnVsbChsaXN0ZW5lcik7CgkJCWlmIChmRG9jdW1lbnRQYXJ0aXRpb25pbmdMaXN0ZW5lcnMgPT0gbnVsbCkgewoJCQkJZkRvY3VtZW50UGFydGl0aW9uaW5nTGlzdGVuZXJzID0gbmV3IEFycmF5TGlzdCgxKTsKCQkJfQoJCQlpZiAoIWZEb2N1bWVudFBhcnRpdGlvbmluZ0xpc3RlbmVycy5jb250YWlucyhsaXN0ZW5lcikpCgkJCQlmRG9jdW1lbnRQYXJ0aXRpb25pbmdMaXN0ZW5lcnMuYWRkKGxpc3RlbmVyKTsKCQl9Cgl9CgoJLyoqCgkgKiBBZGRzIHRoZSBwb3NpdGlvbiB0byB0aGUgZG9jdW1lbnQncyBkZWZhdWx0IHBvc2l0aW9uIGNhdGVnb3J5LiBUaGUKCSAqIGRlZmF1bHQgY2F0ZWdvcnkgbXVzdCBiZSBzcGVjaWZpZWQgYnkgdGhlIGltcGxlbWVudGVyLiBBIHBvc2l0aW9uIHRoYXQKCSAqIGhhcyBiZWVuIGFkZGVkIHRvIGEgcG9zaXRpb24gY2F0ZWdvcnkgaXMgdXBkYXRlZCBhdCBlYWNoIGNoYW5nZSBhcHBsaWVkCgkgKiB0byB0aGUgZG9jdW1lbnQuCgkgKiAKCSAqIEBleGNlcHRpb24gQmFkTG9jYXRpb25FeGNlcHRpb24KCSAqICAgICAgICAgICAgICAgIElmIHBvc2l0aW9uIGlzIG5vdCBhIHZhbGlkIHJhbmdlIGluIHRoZSBkb2N1bWVudAoJICovCglwdWJsaWMgdm9pZCBhZGRQb3NpdGlvbihQb3NpdGlvbiBwb3NpdGlvbikgdGhyb3dzIEJhZExvY2F0aW9uRXhjZXB0aW9uIHsKCQlnZXRQb3NpdGlvbk1hbmFnZXIoKS5hZGRQb3NpdGlvbihwb3NpdGlvbik7Cgl9CgoJLyoqCgkgKiBAc2VlIElEb2N1bWVudCNhZGRQb3NpdGlvbgoJICogQGV4Y2VwdGlvbiBCYWRMb2NhdGlvbkV4Y2VwdGlvbgoJICogICAgICAgICAgICAgICAgSWYgcG9zaXRpb24gaXMgbm90IGEgdmFsaWQgcmFuZ2UgaW4gdGhlIGRvY3VtZW50CgkgKiBAZXhjZXB0aW9uIEJhZFBvc2l0aW9uQ2F0ZWdvcnlFeGNlcHRpb24KCSAqICAgICAgICAgICAgICAgIElmIHRoZSBjYXRlZ29yeSBpcyBub3QgZGVmaW5lZCBmb3IgdGhlIGRvY3VtZW50CgkgKi8KCXB1YmxpYyB2b2lkIGFkZFBvc2l0aW9uKFN0cmluZyBjYXRlZ29yeSwgUG9zaXRpb24gcG9zaXRpb24pIHRocm93cyBCYWRMb2NhdGlvbkV4Y2VwdGlvbiwgQmFkUG9zaXRpb25DYXRlZ29yeUV4Y2VwdGlvbiB7CgkJZ2V0UG9zaXRpb25NYW5hZ2VyKCkuYWRkUG9zaXRpb24oY2F0ZWdvcnksIHBvc2l0aW9uKTsKCX0KCgkvKioKCSAqIEBzZWUgSURvY3VtZW50I2FkZFBvc2l0aW9uQ2F0ZWdvcnkKCSAqLwoJcHVibGljIHZvaWQgYWRkUG9zaXRpb25DYXRlZ29yeShTdHJpbmcgY2F0ZWdvcnkpIHsKCQlpbnRlcm5hbF9hZGRQb3NpdGlvbkNhdGVnb3J5KGNhdGVnb3J5KTsKCX0KCgkvKioKCSAqIEBzZWUgSURvY3VtZW50I2FkZFBvc2l0aW9uVXBkYXRlcgoJICovCglwdWJsaWMgdm9pZCBhZGRQb3NpdGlvblVwZGF0ZXIoSVBvc2l0aW9uVXBkYXRlciB1cGRhdGVyKSB7CgkJaW50ZXJuYWxfYWRkUG9zaXRpb25VcGRhdGVyKHVwZGF0ZXIpOwoJfQoKCS8qKgoJICogQWRkcyB0aGUgZ2l2ZW4gZG9jdW1lbnQgbGlzdGVuZXIgYXMgb25lIHdoaWNoIGlzIG5vdGlmaWVkIGJlZm9yZSB0aG9zZQoJICogZG9jdW1lbnQgbGlzdGVuZXJzIGFkZGVkIHdpdGggPGNvZGU+YWRkRG9jdW1lbnRMaXN0ZW5lcjwvY29kZT4gYXJlCgkgKiBub3RpZmllZC4gSWYgdGhlIGdpdmVuIGxpc3RlbmVyIGlzIGFsc28gcmVnaXN0ZXJlZCB1c2luZwoJICogPGNvZGU+YWRkRG9jdW1lbnRMaXN0ZW5lcjwvY29kZT4gaXQgd2lsbCBiZSBub3RpZmllZCB0d2ljZS4gSWYgdGhlCgkgKiBsaXN0ZW5lciBpcyBhbHJlYWR5IHJlZ2lzdGVyZWQgbm90aGluZyBoYXBwZW5zLgoJICogPHA+CgkgKiAKCSAqIFRoaXMgbWV0aG9kIGlzIG5vdCBmb3IgcHVibGljIHVzZSwgaXQgbWF5IG9ubHkgYmUgY2FsbGVkIGJ5CgkgKiBpbXBsZW1lbnRlcnMgb2YgPGNvZGU+SURvY3VtZW50QWRhcHRlcjwvY29kZT4gYW5kIG9ubHkgaWYgdGhvc2UKCSAqIGltcGxlbWVudGVycyBuZWVkIHRvIGltcGxlbWVudCA8Y29kZT5JRG9jdW1lbnRMaXN0ZW5lcjwvY29kZT4uCgkgKiAKCSAqIEBwYXJhbSBkb2N1bWVudEFkYXB0ZXIKCSAqICAgICAgICAgICAgdGhlIGxpc3RlbmVyIHRvIGJlIGFkZGVkIGFzIHByZW5vdGlmaWVkIGRvY3VtZW50IGxpc3RlbmVyCgkgKi8KCXB1YmxpYyB2b2lkIGFkZFByZW5vdGlmaWVkRG9jdW1lbnRMaXN0ZW5lcihJRG9jdW1lbnRMaXN0ZW5lciBkb2N1bWVudEFkYXB0ZXIpIHsKCQlzeW5jaHJvbml6ZWQgKGxpc3RlbmVyTG9jaykgewoKCQkJaWYgKGZQcmVub3RpZmllZERvY3VtZW50TGlzdGVuZXJzICE9IG51bGwpIHsKCQkJCWludCBwcmV2aW91c1NpemUgPSBmUHJlbm90aWZpZWREb2N1bWVudExpc3RlbmVycy5sZW5ndGg7CgkJCQlJRG9jdW1lbnRMaXN0ZW5lcltdIGxpc3RlbmVycyA9IG5ldyBJRG9jdW1lbnRMaXN0ZW5lcltwcmV2aW91c1NpemUgKyAxXTsKCQkJCVN5c3RlbS5hcnJheWNvcHkoZlByZW5vdGlmaWVkRG9jdW1lbnRMaXN0ZW5lcnMsIDAsIGxpc3RlbmVycywgMCwgcHJldmlvdXNTaXplKTsKCQkJCWxpc3RlbmVyc1twcmV2aW91c1NpemVdID0gZG9jdW1lbnRBZGFwdGVyOwoJCQkJZlByZW5vdGlmaWVkRG9jdW1lbnRMaXN0ZW5lcnMgPSBsaXN0ZW5lcnM7CgkJCX0KCQkJZWxzZSB7CgkJCQlmUHJlbm90aWZpZWREb2N1bWVudExpc3RlbmVycyA9IG5ldyBJRG9jdW1lbnRMaXN0ZW5lclsxXTsKCQkJCWZQcmVub3RpZmllZERvY3VtZW50TGlzdGVuZXJzWzBdID0gZG9jdW1lbnRBZGFwdGVyOwoJCQl9CgkJfQoJfQoKCS8qCgkgKiAobm9uLUphdmFkb2MpCgkgKiAKCSAqIEBzZWUgamF2YS5sYW5nLkNoYXJTZXF1ZW5jZSNjaGFyQXQoaW50KQoJICovCglwdWJsaWMgY2hhciBjaGFyQXQoaW50IGFyZzApIHsKCQl0cnkgewoJCQlyZXR1cm4gZ2V0Q2hhcigwKTsKCQl9CgkJY2F0Y2ggKEJhZExvY2F0aW9uRXhjZXB0aW9uIGUpIHsKCQkJdGhyb3cgbmV3IEluZGV4T3V0T2ZCb3VuZHNFeGNlcHRpb24oKTsKCQl9Cgl9CgoJLyoqCgkgKiBUaGlzIGZvcm0gb2YgdGhlIEFQSSByZW1vdmVzIGFsbCByZWFkIG9ubHkgcG9zaXRpb25zLCBhcyBzaG91bGQgYmUgZG9uZQoJICogd2UgJ3NldFRleHQnIGlzIGNhbGxlZC4gTm90ZTogYW4gYWx0ZXJuYXRpdmUgYWxnb3JpdGhtIG1heSBzaW1wbHkKCSAqIHJlbW92ZSB0aGUgY2F0ZWdvcnkgKGFuZCBpdCB3b3VsZCBnZXQgYWRkZWQgYmFjayBpbiBsYXRlciwgaWYvd2hlbgoJICogcmVhZG9ubHkgcmVnaW9ucyBhZGRlZC4KCSAqLwoJcHJpdmF0ZSB2b2lkIGNsZWFyUmVhZE9ubHkoKSB7CgkJUG9zaXRpb25bXSBwb3NpdGlvbnMgPSBudWxsOwoJCXRyeSB7CgkJCXBvc2l0aW9ucyA9IGdldFBvc2l0aW9ucyhSRUFEX09OTFlfUkVHSU9OU19DQVRFR09SWSk7CgkJfQoJCWNhdGNoIChCYWRQb3NpdGlvbkNhdGVnb3J5RXhjZXB0aW9uIGUpIHsKCQkJTG9nZ2VyLmxvZ0V4Y2VwdGlvbigicHJvZ3JhbSBlcnJvcjogc2hvdWxkIG5ldmVyIG9jY3VyIiwgZSk7IC8vJE5PTi1OTFMtMSQKCQl9CgkJZm9yIChpbnQgaSA9IDA7IGkgPCBwb3NpdGlvbnMubGVuZ3RoOyBpKyspIHsKCQkJUG9zaXRpb24gcG9zaXRpb24gPSBwb3NpdGlvbnNbaV07CgkJCS8vIG5vdGUgd2UgZG9uJ3QgZmlyZSB0aGUgImFib3V0IHRvIGNoYW5nZSIgb3IgImNoYW5nZWQiIGV2ZW50cywKCQkJLy8gc2luY2UgcHJlc3VtYWJseSwgdGV4dCBpcyBhbGwgZ29pbmcgYXdheSBhbmQgYmVpbmcgcmVwbGFjZWQKCQkJLy8gYW55d2F5LgoJCQlwb3NpdGlvbi5kZWxldGUoKTsKCQl9Cgl9CgoKCXB1YmxpYyB2b2lkIGNsZWFyUmVhZE9ubHkoaW50IHN0YXJ0T2Zmc2V0LCBpbnQgbGVuZ3RoKSB7CgkJLy8gVE9ETyBEVyBJIHN0aWxsIG5lZWQgdG8gaW1wbGVtZW50IHNtYXJ0ZXIgYWxnb3JpdGhtIHRoYXQKCQkvLyBhZHVzdCBleGlzdGluZyBSTyByZWdpb25zLCBpZiBuZWVkZWQuIEZvciBub3csIEknbGwganVzdAoJCS8vIHJlbW92ZSBhbnkgdGhhdCBvdmVybGFwLgoJCXRyeSB7CgkJCVBvc2l0aW9uW10gcG9zaXRpb25zID0gZ2V0UG9zaXRpb25zKFJFQURfT05MWV9SRUdJT05TX0NBVEVHT1JZKTsKCQkJZm9yIChpbnQgaSA9IDA7IGkgPCBwb3NpdGlvbnMubGVuZ3RoOyBpKyspIHsKCQkJCVBvc2l0aW9uIHBvc2l0aW9uID0gcG9zaXRpb25zW2ldOwoJCQkJaWYgKHBvc2l0aW9uLm92ZXJsYXBzV2l0aChzdGFydE9mZnNldCwgbGVuZ3RoKSkgewoJCQkJCVN0cmluZyBlZmZlY3RlZFRleHQgPSB0aGlzLmdldChzdGFydE9mZnNldCwgbGVuZ3RoKTsKCQkJCQkvLyBmRG9jdW1lbnRFdmVudCA9IG5ldyBEb2N1bWVudEV2ZW50KHRoaXMsIHN0YXJ0T2Zmc2V0LAoJCQkJCS8vIGxlbmd0aCwgZWZmZWN0ZWRUZXh0KTsKCQkJCQlmaXJlUmVhZE9ubHlBYm91dFRvQmVDaGFuZ2VkKCk7CgkJCQkJcG9zaXRpb24uZGVsZXRlKCk7CgkJCQkJTm9DaGFuZ2VFdmVudCBub0NoYW5nZUV2ZW50ID0gbmV3IE5vQ2hhbmdlRXZlbnQodGhpcywgbnVsbCwgZWZmZWN0ZWRUZXh0LCBzdGFydE9mZnNldCwgbGVuZ3RoKTsKCQkJCQlub0NoYW5nZUV2ZW50LnJlYXNvbiA9IE5vQ2hhbmdlRXZlbnQuUkVBRF9PTkxZX1NUQVRFX0NIQU5HRTsKCQkJCQlmaXJlUmVhZE9ubHlTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudChub0NoYW5nZUV2ZW50KTsKCQkJCX0KCQkJfQoJCX0KCQljYXRjaCAoQmFkUG9zaXRpb25DYXRlZ29yeUV4Y2VwdGlvbiBlKSB7CgkJCS8vIGp1c3QgbWVhbnMgbm8gcmVhZG9ubHkgcmVnaW9ucyBiZWVuIGRlZmluZWQgeWV0CgkJCS8vIHNvIG5vdGhpbmcgdG8gZG8uCgkJfQoJfQoKCS8qKgoJICogQ29tcHV0ZXMgdGhlIGluZGV4IGF0IHdoaWNoIGEgPGNvZGU+UG9zaXRpb248L2NvZGU+IHdpdGggdGhlCgkgKiBzcGVjaWZpZWQgb2Zmc2V0IHdvdWxkIGJlIGluc2VydGVkIGludG8gdGhlIGdpdmVuIGNhdGVnb3J5LiBBcyB0aGUKCSAqIG9yZGVyaW5nIGluc2lkZSBhIGNhdGVnb3J5IG9ubHkgZGVwZW5kcyBvbiB0aGUgb2Zmc2V0LCB0aGUgaW5kZXggbXVzdAoJICogYmUgY2hvb3NlbiB0byBiZSB0aGUgZmlyc3Qgb2YgYWxsIHBvc2l0aW9ucyB3aXRoIHRoZSBzYW1lIG9mZnNldC4KCSAqIAoJICogQHBhcmFtIGNhdGVnb3J5CgkgKiAgICAgICAgICAgIHRoZSBjYXRlZ29yeSBpbiB3aGljaCB3b3VsZCBiZSBhZGRlZAoJICogQHBhcmFtIG9mZnNldAoJICogICAgICAgICAgICB0aGUgcG9zaXRpb24gb2Zmc2V0IHRvIGJlIGNvbnNpZGVyZWQKCSAqIEByZXR1cm4gdGhlIGluZGV4IGludG8gdGhlIGNhdGVnb3J5CgkgKiBAZXhjZXB0aW9uIEJhZExvY2F0aW9uRXhjZXB0aW9uCgkgKiAgICAgICAgICAgICAgICBpZiBvZmZzZXQgaXMgaW52YWxpZCBpbiB0aGlzIGRvY3VtZW50CgkgKiBAZXhjZXB0aW9uIEJhZFBvc2l0aW9uQ2F0ZWdvcnlFeGNlcHRpb24KCSAqICAgICAgICAgICAgICAgIGlmIGNhdGVnb3J5IGlzIHVuZGVmaW5lZCBpbiB0aGlzIGRvY3VtZW50CgkgKi8KCXB1YmxpYyBpbnQgY29tcHV0ZUluZGV4SW5DYXRlZ29yeShTdHJpbmcgY2F0ZWdvcnksIGludCBvZmZzZXQpIHRocm93cyBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LkJhZFBvc2l0aW9uQ2F0ZWdvcnlFeGNlcHRpb24sIG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuQmFkTG9jYXRpb25FeGNlcHRpb24gewoJCXJldHVybiBnZXRQb3NpdGlvbk1hbmFnZXIoKS5jb21wdXRlSW5kZXhJbkNhdGVnb3J5KGNhdGVnb3J5LCBvZmZzZXQpOwoJfQoKCS8qKgoJICogQ29tcHV0ZXMgdGhlIG51bWJlciBvZiBsaW5lcyBpbiB0aGUgZ2l2ZW4gdGV4dC4gRm9yIGEgZ2l2ZW4gaW1wbGVtZW50ZXIKCSAqIG9mIHRoaXMgaW50ZXJmYWNlIHRoaXMgbWV0aG9kIHJldHVybnMgdGhlIHNhbWUgcmVzdWx0IGFzCgkgKiA8Y29kZT5zZXQodGV4dCk7IGdldE51bWJlck9mTGluZXMoKTwvY29kZT4uCgkgKiAKCSAqIEBwYXJhbSB0ZXh0CgkgKiAgICAgICAgICAgIHRoZSB0ZXh0IHdob3NlIG51bWJlciBvZiBsaW5lcyBzaG91bGQgYmUgY29tcHV0ZWQKCSAqIEByZXR1cm4gdGhlIG51bWJlciBvZiBsaW5lcyBpbiB0aGUgZ2l2ZW4gdGV4dAoJICovCglwdWJsaWMgaW50IGNvbXB1dGVOdW1iZXJPZkxpbmVzKFN0cmluZyB0ZXh0KSB7CgkJcmV0dXJuIGdldFRyYWNrZXIoKS5jb21wdXRlTnVtYmVyT2ZMaW5lcyh0ZXh0KTsKCX0KCgkvKioKCSAqIENvbXB1dGVzIHRoZSBwYXJ0aXRpb25pbmcgb2YgdGhlIGdpdmVuIGRvY3VtZW50IHJhbmdlIHVzaW5nIHRoZQoJICogZG9jdW1lbnQncyBwYXJ0aXRpb25lci4KCSAqIAoJICogQHBhcmFtIG9mZnNldAoJICogICAgICAgICAgICB0aGUgZG9jdW1lbnQgb2Zmc2V0IGF0IHdoaWNoIHRoZSByYW5nZSBzdGFydHMKCSAqIEBwYXJhbSBsZW5ndGgKCSAqICAgICAgICAgICAgdGhlIGxlbmd0aCBvZiB0aGUgZG9jdW1lbnQgcmFuZ2UKCSAqIEByZXR1cm4gYSBzcGVjaWZpY2F0aW9uIG9mIHRoZSByYW5nZSdzIHBhcnRpdGlvbmluZwoJICogQHRocm93cyBCYWRMb2NhdGlvbkV4Y2VwdGlvbgoJICogQHRocm93cyBCYWRQYXJ0aXRpb25pbmdFeGNlcHRpb24KCSAqLwoJcHVibGljIElUeXBlZFJlZ2lvbltdIGNvbXB1dGVQYXJ0aXRpb25pbmcoaW50IG9mZnNldCwgaW50IGxlbmd0aCkgdGhyb3dzIEJhZExvY2F0aW9uRXhjZXB0aW9uIHsKCQlJVHlwZWRSZWdpb25bXSB0eXBlZFJlZ2lvbnMgPSBudWxsOwoJCXRyeSB7CgkJCXR5cGVkUmVnaW9ucyA9IGNvbXB1dGVQYXJ0aXRpb25pbmcoSVN0cnVjdHVyZWRQYXJ0aXRpb25pbmcuREVGQVVMVF9TVFJVQ1RVUkVEX1BBUlRJVElPTklORywgb2Zmc2V0LCBsZW5ndGgsIGZhbHNlKTsKCQl9CgkJY2F0Y2ggKEJhZFBhcnRpdGlvbmluZ0V4Y2VwdGlvbiBlKSB7CgkJCS8vIGltcG9zc2libGUgaW4gdGhpcyBjb250ZXh0CgkJCXRocm93IG5ldyBFcnJvcihlKTsKCQl9CgkJaWYgKHR5cGVkUmVnaW9ucyA9PSBudWxsKSB7CgkJCXR5cGVkUmVnaW9ucyA9IG5ldyBJVHlwZWRSZWdpb25bMF07CgkJfQoJCXJldHVybiB0eXBlZFJlZ2lvbnM7Cgl9CgoKCXB1YmxpYyBJVHlwZWRSZWdpb25bXSBjb21wdXRlUGFydGl0aW9uaW5nKFN0cmluZyBwYXJ0aXRpb25pbmcsIGludCBvZmZzZXQsIGludCBsZW5ndGgsIGJvb2xlYW4gaW5jbHVkZVplcm9MZW5ndGhQYXJ0aXRpb25zKSB0aHJvd3MgQmFkTG9jYXRpb25FeGNlcHRpb24sIEJhZFBhcnRpdGlvbmluZ0V4Y2VwdGlvbiB7CgkJaWYgKCgwID4gb2Zmc2V0KSB8fCAoMCA+IGxlbmd0aCkgfHwgKG9mZnNldCArIGxlbmd0aCA+IGdldExlbmd0aCgpKSkKCQkJdGhyb3cgbmV3IEJhZExvY2F0aW9uRXhjZXB0aW9uKCk7CgoJCUlEb2N1bWVudFBhcnRpdGlvbmVyIHBhcnRpdGlvbmVyID0gZ2V0RG9jdW1lbnRQYXJ0aXRpb25lcihwYXJ0aXRpb25pbmcpOwoKCQlpZiAocGFydGl0aW9uZXIgaW5zdGFuY2VvZiBJRG9jdW1lbnRQYXJ0aXRpb25lckV4dGVuc2lvbjIpCgkJCXJldHVybiAoKElEb2N1bWVudFBhcnRpdGlvbmVyRXh0ZW5zaW9uMikgcGFydGl0aW9uZXIpLmNvbXB1dGVQYXJ0aXRpb25pbmcob2Zmc2V0LCBsZW5ndGgsIGluY2x1ZGVaZXJvTGVuZ3RoUGFydGl0aW9ucyk7CgkJZWxzZSBpZiAocGFydGl0aW9uZXIgIT0gbnVsbCkKCQkJcmV0dXJuIHBhcnRpdGlvbmVyLmNvbXB1dGVQYXJ0aXRpb25pbmcob2Zmc2V0LCBsZW5ndGgpOwoJCWVsc2UgaWYgKElTdHJ1Y3R1cmVkUGFydGl0aW9uaW5nLkRFRkFVTFRfU1RSVUNUVVJFRF9QQVJUSVRJT05JTkcuZXF1YWxzKHBhcnRpdGlvbmluZykpCgkJCXJldHVybiBuZXcgVHlwZWRSZWdpb25bXXtuZXcgVHlwZWRSZWdpb24ob2Zmc2V0LCBsZW5ndGgsIERFRkFVTFRfQ09OVEVOVF9UWVBFKX07CgkJZWxzZQoJCQl0aHJvdyBuZXcgQmFkUGFydGl0aW9uaW5nRXhjZXB0aW9uKCk7Cgl9CgoJLyoqCgkgKiBAc2VlIElEb2N1bWVudCNjb250YWluc1Bvc2l0aW9uCgkgKi8KCXB1YmxpYyBib29sZWFuIGNvbnRhaW5zUG9zaXRpb24oU3RyaW5nIGNhdGVnb3J5LCBpbnQgb2Zmc2V0LCBpbnQgbGVuZ3RoKSB7CgkJcmV0dXJuIGdldFBvc2l0aW9uTWFuYWdlcigpLmNvbnRhaW5zUG9zaXRpb24oY2F0ZWdvcnksIG9mZnNldCwgbGVuZ3RoKTsKCX0KCgkvKioKCSAqIEBzZWUgSURvY3VtZW50I2NvbnRhaW5zUG9zaXRpb25DYXRlZ29yeQoJICovCglwdWJsaWMgYm9vbGVhbiBjb250YWluc1Bvc2l0aW9uQ2F0ZWdvcnkoU3RyaW5nIGNhdGVnb3J5KSB7CgkJcmV0dXJuIGdldFBvc2l0aW9uTWFuYWdlcigpLmNvbnRhaW5zUG9zaXRpb25DYXRlZ29yeShjYXRlZ29yeSk7Cgl9CgoJcHVibGljIGJvb2xlYW4gY29udGFpbnNSZWFkT25seShpbnQgc3RhcnRPZmZzZXQsIGludCBsZW5ndGgpIHsKCQlib29sZWFuIHJlc3VsdCA9IGZhbHNlOwoJCXRyeSB7CgkJCVBvc2l0aW9uW10gcG9zaXRpb25zID0gZ2V0UG9zaXRpb25zKFJFQURfT05MWV9SRUdJT05TX0NBVEVHT1JZKTsKCQkJZm9yIChpbnQgaSA9IDA7IGkgPCBwb3NpdGlvbnMubGVuZ3RoOyBpKyspIHsKCQkJCVBvc2l0aW9uIHBvc2l0aW9uID0gcG9zaXRpb25zW2ldOwoJCQkJaWYgKHBvc2l0aW9uLm92ZXJsYXBzV2l0aChzdGFydE9mZnNldCwgbGVuZ3RoKSkgewoJCQkJCXJlc3VsdCA9IHRydWU7CgkJCQkJYnJlYWs7CgkJCQl9CgkJCX0KCQl9CgkJY2F0Y2ggKEJhZFBvc2l0aW9uQ2F0ZWdvcnlFeGNlcHRpb24gZSkgewoJCQkvLyBqdXN0IG1lYW5zIG5vIHJlYWRvbmx5IHJlZ2lvbnMgYmVlbiBkZWZpbmVkIHlldAoJCQkvLyBzbyBvYnZpb3VzbHkgZmFsc2UKCQkJcmVzdWx0ID0gZmFsc2U7CgkJfQoJCXJldHVybiByZXN1bHQ7Cgl9CgoJcHJpdmF0ZSB2b2lkIGV4ZWN1dGVQb3N0Tm90aWZpY2F0aW9uQ2hhbmdlcygpIHsKCQlpZiAoZlN0b3BwZWRDb3VudCA+IDApCgkJCXJldHVybjsKCQl3aGlsZSAoZlBvc3ROb3RpZmljYXRpb25DaGFuZ2VzICE9IG51bGwpIHsKCQkJTGlzdCBjaGFuZ2VzID0gZlBvc3ROb3RpZmljYXRpb25DaGFuZ2VzOwoJCQlmUG9zdE5vdGlmaWNhdGlvbkNoYW5nZXMgPSBudWxsOwoJCQlJdGVyYXRvciBlID0gY2hhbmdlcy5pdGVyYXRvcigpOwoJCQl3aGlsZSAoZS5oYXNOZXh0KCkpIHsKCQkJCVJlZ2lzdGVyZWRSZXBsYWNlIHJlcGxhY2UgPSAoUmVnaXN0ZXJlZFJlcGxhY2UpIGUubmV4dCgpOwoJCQkJcmVwbGFjZS5mUmVwbGFjZS5wZXJmb3JtKHRoaXMsIHJlcGxhY2UuZk93bmVyKTsKCQkJfQoJCX0KCX0KCglwcml2YXRlIHZvaWQgZmlyZURvY3VtZW50QWJvdXRUb0NoYW5nZWQoKSB7CgkJLy8gbW9zdCBEb2N1bWVudEFib3V0VG9CZUNoYW5nZWQgbGlzdGVuZXJzIGRvIG5vdCBhbnRpY2lwYXRlCgkJLy8gRG9jdW1lbnRFdmVudCA9PSBudWxsLiBTbyBtYWtlIHN1cmUgZG9jdW1lbnRFdmVudCBpcyBub3QKCQkvLyBudWxsLiAodGhpcyBzaG91bGQgbmV2ZXIgaGFwcGVuLCB5ZXQgaXQgZG9lcyBzb21ldGltZXMpCgkJaWYgKGZEb2N1bWVudEV2ZW50ID09IG51bGwpIHsKCQkJZkRvY3VtZW50RXZlbnQgPSBuZXcgTnVsbERvY3VtZW50RXZlbnQoKTsKCQl9CgoJCV9maXJlU3RydWN0dXJlZERvY3VtZW50QWJvdXRUb0NoYW5nZShmU3RydWN0dXJlZERvY3VtZW50QWJvdXRUb0NoYW5nZUxpc3RlbmVycyk7CgkJLy8gTm90ZTogdGhlIGRvY0V2ZW50IGlzIGNyZWF0ZWQgaW4gcmVwbGFjZVRleHQgQVBJISAob3Igc2V0IFRleHQpCgkJX2ZpcmVEb2N1bWVudEFib3V0VG9DaGFuZ2UoZlByZW5vdGlmaWVkRG9jdW1lbnRMaXN0ZW5lcnMpOwoJCW5vdGlmeURvY3VtZW50UGFydGl0aW9uZXJzQWJvdXRUb0NoYW5nZShmRG9jdW1lbnRFdmVudCk7CgkJX2ZpcmVEb2N1bWVudEFib3V0VG9DaGFuZ2UoZkRvY3VtZW50TGlzdGVuZXJzKTsKCX0KCgkvKioKCSAqIEZpcmVzIHRoZSBkb2N1bWVudCBwYXJ0aXRpb25pbmcgY2hhbmdlZCBub3RpZmljYXRpb24gdG8gYWxsIHJlZ2lzdGVyZWQKCSAqIGRvY3VtZW50IHBhcnRpdGlvbmluZyBsaXN0ZW5lcnMuIFVzZXMgYSByb2J1c3QgaXRlcmF0b3IuCgkgKiAKCSAqIEBwYXJhbSBldmVudAoJICogICAgICAgICAgICB0aGUgZG9jdW1lbnQgcGFydGl0aW9uaW5nIGNoYW5nZWQgZXZlbnQKCSAqIAoJICogQHNlZSBJRG9jdW1lbnRQYXJ0aXRpb25pbmdMaXN0ZW5lckV4dGVuc2lvbjIKCSAqLwoJcHJvdGVjdGVkIHZvaWQgZmlyZURvY3VtZW50UGFydGl0aW9uaW5nQ2hhbmdlZChEb2N1bWVudFBhcnRpdGlvbmluZ0NoYW5nZWRFdmVudCBldmVudCkgewoJCWlmIChmRG9jdW1lbnRQYXJ0aXRpb25pbmdMaXN0ZW5lcnMgPT0gbnVsbCB8fCBmRG9jdW1lbnRQYXJ0aXRpb25pbmdMaXN0ZW5lcnMuc2l6ZSgpID09IDApCgkJCXJldHVybjsKCgkJTGlzdCBsaXN0ID0gbmV3IEFycmF5TGlzdChmRG9jdW1lbnRQYXJ0aXRpb25pbmdMaXN0ZW5lcnMpOwoJCUl0ZXJhdG9yIGUgPSBsaXN0Lml0ZXJhdG9yKCk7CgkJd2hpbGUgKGUuaGFzTmV4dCgpKSB7CgkJCUlEb2N1bWVudFBhcnRpdGlvbmluZ0xpc3RlbmVyIGwgPSAoSURvY3VtZW50UGFydGl0aW9uaW5nTGlzdGVuZXIpIGUubmV4dCgpOwoJCQlpZiAobCBpbnN0YW5jZW9mIElEb2N1bWVudFBhcnRpdGlvbmluZ0xpc3RlbmVyRXh0ZW5zaW9uMikgewoJCQkJSURvY3VtZW50UGFydGl0aW9uaW5nTGlzdGVuZXJFeHRlbnNpb24yIGV4dGVuc2lvbjIgPSAoSURvY3VtZW50UGFydGl0aW9uaW5nTGlzdGVuZXJFeHRlbnNpb24yKSBsOwoJCQkJZXh0ZW5zaW9uMi5kb2N1bWVudFBhcnRpdGlvbmluZ0NoYW5nZWQoZXZlbnQpOwoJCQl9CgkJCWVsc2UgaWYgKGwgaW5zdGFuY2VvZiBJRG9jdW1lbnRQYXJ0aXRpb25pbmdMaXN0ZW5lckV4dGVuc2lvbikgewoJCQkJSURvY3VtZW50UGFydGl0aW9uaW5nTGlzdGVuZXJFeHRlbnNpb24gZXh0ZW5zaW9uID0gKElEb2N1bWVudFBhcnRpdGlvbmluZ0xpc3RlbmVyRXh0ZW5zaW9uKSBsOwoJCQkJZXh0ZW5zaW9uLmRvY3VtZW50UGFydGl0aW9uaW5nQ2hhbmdlZCh0aGlzLCBldmVudC5nZXRDb3ZlcmFnZSgpKTsKCQkJfQoJCQllbHNlIHsKCQkJCWwuZG9jdW1lbnRQYXJ0aXRpb25pbmdDaGFuZ2VkKHRoaXMpOwoJCQl9CgkJfQoKCX0KCglwcml2YXRlIHZvaWQgZmlyZVJlYWRPbmx5QWJvdXRUb0JlQ2hhbmdlZCgpIHsKCQlfZmlyZVN0cnVjdHVyZWREb2N1bWVudEFib3V0VG9DaGFuZ2UoZlN0cnVjdHVyZWREb2N1bWVudEFib3V0VG9DaGFuZ2VMaXN0ZW5lcnMpOwoJCS8vIE5vdGU6IHRoZSBkb2NFdmVudCBpcyBjcmVhdGVkIGluIHJlcGxhY2VUZXh0IEFQSSEgKG9yIHNldCBUZXh0KQoJCS8vIF9maXJlRG9jdW1lbnRBYm91dFRvQ2hhbmdlKGZQcmVub3RpZmllZERvY3VtZW50TGlzdGVuZXJzKTsKCQkvLyBfZmlyZURvY3VtZW50QWJvdXRUb0NoYW5nZShmRG9jdW1lbnRMaXN0ZW5lcnMpOwoJfQoKCXByaXZhdGUgdm9pZCBmaXJlUmVhZE9ubHlTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudChOb0NoYW5nZUV2ZW50IGV2ZW50KSB7CgkJX2ZpcmVFdmVudChmU3RydWN0dXJlZERvY3VtZW50Q2hhbmdpbmdMaXN0ZW5lcnMsIGV2ZW50KTsKCQlfZmlyZUV2ZW50KGZTdHJ1Y3R1cmVkRG9jdW1lbnRDaGFuZ2VkTGlzdGVuZXJzLCBldmVudCk7CgkJLy8gX2ZpcmVEb2N1bWVudENoYW5nZWQoZlByZW5vdGlmaWVkRG9jdW1lbnRMaXN0ZW5lcnMsIGV2ZW50KTsKCQkvLyBfZmlyZURvY3VtZW50Q2hhbmdlZChmRG9jdW1lbnRMaXN0ZW5lcnMsIGV2ZW50KTsKCQkvLyBfY2xlYXJEb2N1bWVudEV2ZW50KCk7Cgl9CgoJcHJpdmF0ZSB2b2lkIGZpcmVTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudChOb0NoYW5nZUV2ZW50IGV2ZW50KSB7CgkJX2ZpcmVFdmVudChmU3RydWN0dXJlZERvY3VtZW50Q2hhbmdpbmdMaXN0ZW5lcnMsIGV2ZW50KTsKCQlfZmlyZUV2ZW50KGZTdHJ1Y3R1cmVkRG9jdW1lbnRDaGFuZ2VkTGlzdGVuZXJzLCBldmVudCk7CgkJX2ZpcmVEb2N1bWVudENoYW5nZWQoZlByZW5vdGlmaWVkRG9jdW1lbnRMaXN0ZW5lcnMsIGV2ZW50KTsKCQlub3RpZnlEb2N1bWVudFBhcnRpdGlvbmVyc0RvY3VtZW50Q2hhbmdlZChldmVudCk7CgkJX2ZpcmVEb2N1bWVudENoYW5nZWQoZkRvY3VtZW50TGlzdGVuZXJzLCBldmVudCk7CgkJX2NsZWFyRG9jdW1lbnRFdmVudCgpOwoJfQoKCXByaXZhdGUgdm9pZCBmaXJlU3RydWN0dXJlZERvY3VtZW50RXZlbnQoUmVnaW9uQ2hhbmdlZEV2ZW50IGV2ZW50KSB7CgkJX2ZpcmVFdmVudChmU3RydWN0dXJlZERvY3VtZW50Q2hhbmdpbmdMaXN0ZW5lcnMsIGV2ZW50KTsKCQlfZmlyZUV2ZW50KGZTdHJ1Y3R1cmVkRG9jdW1lbnRDaGFuZ2VkTGlzdGVuZXJzLCBldmVudCk7CgkJX2ZpcmVEb2N1bWVudENoYW5nZWQoZlByZW5vdGlmaWVkRG9jdW1lbnRMaXN0ZW5lcnMsIGV2ZW50KTsKCQlub3RpZnlEb2N1bWVudFBhcnRpdGlvbmVyc0RvY3VtZW50Q2hhbmdlZChldmVudCk7CgkJX2ZpcmVEb2N1bWVudENoYW5nZWQoZkRvY3VtZW50TGlzdGVuZXJzLCBldmVudCk7CgkJX2NsZWFyRG9jdW1lbnRFdmVudCgpOwoJfQoKCXByaXZhdGUgdm9pZCBmaXJlU3RydWN0dXJlZERvY3VtZW50RXZlbnQoUmVnaW9uc1JlcGxhY2VkRXZlbnQgZXZlbnQpIHsKCQlfZmlyZUV2ZW50KGZTdHJ1Y3R1cmVkRG9jdW1lbnRDaGFuZ2luZ0xpc3RlbmVycywgZXZlbnQpOwoJCV9maXJlRXZlbnQoZlN0cnVjdHVyZWREb2N1bWVudENoYW5nZWRMaXN0ZW5lcnMsIGV2ZW50KTsKCQlfZmlyZURvY3VtZW50Q2hhbmdlZChmUHJlbm90aWZpZWREb2N1bWVudExpc3RlbmVycywgZXZlbnQpOwoJCW5vdGlmeURvY3VtZW50UGFydGl0aW9uZXJzRG9jdW1lbnRDaGFuZ2VkKGV2ZW50KTsKCQlfZmlyZURvY3VtZW50Q2hhbmdlZChmRG9jdW1lbnRMaXN0ZW5lcnMsIGV2ZW50KTsKCQlfY2xlYXJEb2N1bWVudEV2ZW50KCk7Cgl9CgoJcHJpdmF0ZSB2b2lkIGZpcmVTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudChTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb25zUmVwbGFjZWRFdmVudCBldmVudCkgewoJCV9maXJlRXZlbnQoZlN0cnVjdHVyZWREb2N1bWVudENoYW5naW5nTGlzdGVuZXJzLCBldmVudCk7CgkJX2ZpcmVFdmVudChmU3RydWN0dXJlZERvY3VtZW50Q2hhbmdlZExpc3RlbmVycywgZXZlbnQpOwoJCV9maXJlRG9jdW1lbnRDaGFuZ2VkKGZQcmVub3RpZmllZERvY3VtZW50TGlzdGVuZXJzLCBldmVudCk7CgkJbm90aWZ5RG9jdW1lbnRQYXJ0aXRpb25lcnNEb2N1bWVudENoYW5nZWQoZXZlbnQpOwoJCV9maXJlRG9jdW1lbnRDaGFuZ2VkKGZEb2N1bWVudExpc3RlbmVycywgZXZlbnQpOwoJCV9jbGVhckRvY3VtZW50RXZlbnQoKTsKCX0KCgkvKioKCSAqIFJldHVybnMgdGhlIGRvY3VtZW50J3MgY29tcGxldGUgdGV4dC4KCSAqLwoJcHVibGljIFN0cmluZyBnZXQoKSB7CgkJcmV0dXJuIGdldFN0b3JlKCkuZ2V0KDAsIGdldExlbmd0aCgpKTsKCX0KCgkvKioKCSAqIFJldHVybnMgbGVuZ3RoIGNoYXJhY3RlcnMgZnJvbSB0aGUgZG9jdW1lbnQncyB0ZXh0IHN0YXJ0aW5nIGZyb20gdGhlCgkgKiBzcGVjaWZpZWQgcG9zaXRpb24uCgkgKiAKCSAqIEB0aHJvd3MgQmFkTG9jYXRpb25FeGNlcHRpb24KCSAqIAoJICogQGV4Y2VwdGlvbiBCYWRMb2NhdGlvbkV4Y2VwdGlvbgoJICogICAgICAgICAgICAgICAgSWYgdGhlIHJhbmdlIGlzIG5vdCB2YWxpZCBpbiB0aGUgZG9jdW1lbnQKCSAqLwoJcHVibGljIFN0cmluZyBnZXQoaW50IG9mZnNldCwgaW50IGxlbmd0aCkgewoJCVN0cmluZyByZXN1bHQgPSBudWxsOwoJCWludCBteUxlbmd0aCA9IGdldExlbmd0aCgpOwoJCWlmICgwID4gb2Zmc2V0KQoJCQlvZmZzZXQgPSAwOwoJCWlmICgwID4gbGVuZ3RoKQoJCQlsZW5ndGggPSAwOwoJCWlmIChvZmZzZXQgKyBsZW5ndGggPiBteUxlbmd0aCkgewoJCQkvLyBmaXJzdCB0cnkgYWRqdXN0aW5nIGxlbmd0aCB0byBmaXQKCQkJaW50IGxlc3NMZW5ndGggPSBteUxlbmd0aCAtIG9mZnNldDsKCQkJaWYgKChsZXNzTGVuZ3RoID49IDApICYmIChvZmZzZXQgKyBsZXNzTGVuZ3RoID09IG15TGVuZ3RoKSkgewoJCQkJbGVuZ3RoID0gbGVzc0xlbmd0aDsKCQkJfQoJCQllbHNlIHsKCQkJCS8vIHNlY29uZCwgdHJ5IG9mZnNldAoJCQkJaW50IG1vcmVPZmZzZXQgPSBteUxlbmd0aCAtIGxlbmd0aDsKCQkJCWlmICgobW9yZU9mZnNldCA+PSAwKSAmJiAobW9yZU9mZnNldCArIGxlbmd0aCA9PSBteUxlbmd0aCkpIHsKCQkJCQlvZmZzZXQgPSBtb3JlT2Zmc2V0OwoJCQkJfQoJCQkJZWxzZSB7CgkJCQkJLy8gY2FuIGhhcHBlbiBpZiBteUxlbmd0aCBpcyAwLgoJCQkJCS8vIG5vIGFkanVzdG1lbnQgcG9zc2libGUuCgkJCQkJcmVzdWx0ID0gbmV3IFN0cmluZygpOwoJCQkJfQoJCQl9CgoJCX0KCQlpZiAocmVzdWx0ID09IG51bGwpIHsKCQkJcmVzdWx0ID0gZ2V0U3RvcmUoKS5nZXQob2Zmc2V0LCBsZW5ndGgpOwoJCX0KCQlyZXR1cm4gcmVzdWx0OwoJfQoKCXB1YmxpYyBPYmplY3QgZ2V0QWRhcHRlcihDbGFzcyBhZGFwdGVyKSB7CgkJcmV0dXJuIFBsYXRmb3JtLmdldEFkYXB0ZXJNYW5hZ2VyKCkuZ2V0QWRhcHRlcih0aGlzLCBhZGFwdGVyKTsKCX0KCglJU3RydWN0dXJlZERvY3VtZW50UmVnaW9uIGdldENhY2hlZERvY3VtZW50UmVnaW9uKCkgewoJCUlTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb24gcmVzdWx0ID0gbnVsbDsKCQlpZiAoVVNFX0xPQ0FMX1RIUkVBRCkgewoJCQlyZXN1bHQgPSBmQ3VycmVudERvY3VtbmV0UmVnaW9uQ2FjaGUuZ2V0KCk7CgkJfQoJCWVsc2UgewoJCQlyZXN1bHQgPSBjYWNoZWREb2N1bWVudFJlZ2lvbjsKCQl9CgkJcmV0dXJuIHJlc3VsdDsKCX0KCgkvKioKCSAqIEBzZWUgSURvY3VtZW50I2dldENoYXIKCSAqIEBleGNlcHRpb24gQmFkTG9jYXRpb25FeGNlcHRpb24KCSAqICAgICAgICAgICAgICAgIElmIHBvc2l0aW9uIGlzIG5vdCBhIHZhbGlkIHJhbmdlIGluIHRoZSBkb2N1bWVudAoJICovCglwdWJsaWMgY2hhciBnZXRDaGFyKGludCBwb3MpIHRocm93cyBCYWRMb2NhdGlvbkV4Y2VwdGlvbiB7CgkJY2hhciByZXN1bHQgPSAweDAwOwoJCXRyeSB7CgkJCXJlc3VsdCA9IGdldFN0b3JlKCkuZ2V0KHBvcyk7CgkJfQoJCWNhdGNoIChJbmRleE91dE9mQm91bmRzRXhjZXB0aW9uIGUpIHsKCQkJdGhyb3cgbmV3IEJhZExvY2F0aW9uRXhjZXB0aW9uKGUuZ2V0TG9jYWxpemVkTWVzc2FnZSgpKTsKCQl9CgkJcmV0dXJuIHJlc3VsdDsKCX0KCgkvKioKCSAqIFJldHVybnMgdGhlIHR5cGUgb2YgdGhlIGRvY3VtZW50IHBhcnRpdGlvbiBjb250YWluaW5nIHRoZSBnaXZlbgoJICogY2hhcmFjdGVyIHBvc2l0aW9uLgoJICovCglwdWJsaWMgU3RyaW5nIGdldENvbnRlbnRUeXBlKGludCBvZmZzZXQpIHRocm93cyBCYWRMb2NhdGlvbkV4Y2VwdGlvbiB7CgkJcmV0dXJuIGdldERvY3VtZW50UGFydGl0aW9uZXIoKS5nZXRDb250ZW50VHlwZShvZmZzZXQpOwoJfQoKCglwdWJsaWMgU3RyaW5nIGdldENvbnRlbnRUeXBlKFN0cmluZyBwYXJ0aXRpb25pbmcsIGludCBvZmZzZXQsIGJvb2xlYW4gcHJlZmVyT3BlblBhcnRpdGlvbnMpIHRocm93cyBCYWRMb2NhdGlvbkV4Y2VwdGlvbiwgQmFkUGFydGl0aW9uaW5nRXhjZXB0aW9uIHsKCQlpZiAoKDAgPiBvZmZzZXQpIHx8IChvZmZzZXQgPiBnZXRMZW5ndGgoKSkpCgkJCXRocm93IG5ldyBCYWRMb2NhdGlvbkV4Y2VwdGlvbigpOwoKCQlJRG9jdW1lbnRQYXJ0aXRpb25lciBwYXJ0aXRpb25lciA9IGdldERvY3VtZW50UGFydGl0aW9uZXIocGFydGl0aW9uaW5nKTsKCgkJaWYgKHBhcnRpdGlvbmVyIGluc3RhbmNlb2YgSURvY3VtZW50UGFydGl0aW9uZXJFeHRlbnNpb24yKQoJCQlyZXR1cm4gKChJRG9jdW1lbnRQYXJ0aXRpb25lckV4dGVuc2lvbjIpIHBhcnRpdGlvbmVyKS5nZXRDb250ZW50VHlwZShvZmZzZXQsIHByZWZlck9wZW5QYXJ0aXRpb25zKTsKCQllbHNlIGlmIChwYXJ0aXRpb25lciAhPSBudWxsKQoJCQlyZXR1cm4gcGFydGl0aW9uZXIuZ2V0Q29udGVudFR5cGUob2Zmc2V0KTsKCQllbHNlIGlmIChJU3RydWN0dXJlZFBhcnRpdGlvbmluZy5ERUZBVUxUX1NUUlVDVFVSRURfUEFSVElUSU9OSU5HLmVxdWFscyhwYXJ0aXRpb25pbmcpKQoJCQlyZXR1cm4gREVGQVVMVF9DT05URU5UX1RZUEU7CgkJZWxzZQoJCQl0aHJvdyBuZXcgQmFkUGFydGl0aW9uaW5nRXhjZXB0aW9uKCk7Cgl9CgoJLyoKCSAqIChub24tSmF2YWRvYykKCSAqIAoJICogQHNlZSBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklEb2N1bWVudEV4dGVuc2lvbjQjZ2V0RGVmYXVsdExpbmVEZWxpbWl0ZXIoKQoJICovCglwdWJsaWMgU3RyaW5nIGdldERlZmF1bHRMaW5lRGVsaW1pdGVyKCkgewoJCS8vIHNwZWNpZmljIHByZWZlcnJlZCBsaW5lIGRlbGltaXRlcgoJCWlmIChwcmVmZXJlZERlbGltaXRlciAhPSBudWxsKQoJCQlyZXR1cm4gcHJlZmVyZWREZWxpbWl0ZXI7CgoKCQkvLyBubyBsaW5lIGRlbGltaXRlciBoYXMgYmVlbiB1c2VkIHNvIGp1c3QgdXNlIHBsYXRmb3JtJ3MgZGVmYXVsdAoJCVN0cmluZyBsaW5lRGVsaW1pdGVyID0gbnVsbDsKCQlTdHJpbmcgc3lzTGluZURlbGltaXRlciA9IFBsYXRmb3JtTGluZURlbGltaXRlcjsKCQlTdHJpbmdbXSBkZWxpbWl0ZXJzID0gZ2V0TGVnYWxMaW5lRGVsaW1pdGVycygpOwoJCUFzc2VydC5pc1RydWUoZGVsaW1pdGVycy5sZW5ndGggPiAwKTsKCQlmb3IgKGludCBpID0gMDsgaSA8IGRlbGltaXRlcnMubGVuZ3RoOyBpKyspIHsKCQkJaWYgKGRlbGltaXRlcnNbaV0uZXF1YWxzKHN5c0xpbmVEZWxpbWl0ZXIpKSB7CgkJCQlsaW5lRGVsaW1pdGVyID0gc3lzTGluZURlbGltaXRlcjsKCQkJCWJyZWFrOwoJCQl9CgkJfQoKCQkvLyBubyBwbGF0Zm9ybSBkZWZhdWx0IHNvIGp1c3QgdXNlIGZpcnN0IGxlZ2FsIGRlbGltaXRlcgoJCWlmIChsaW5lRGVsaW1pdGVyID09IG51bGwpCgkJCWxpbmVEZWxpbWl0ZXIgPSBkZWxpbWl0ZXJzWzBdOwoKCQlyZXR1cm4gbGluZURlbGltaXRlcjsKCX0KCgkvKioKCSAqIFJldHVybnMgdGhlIGRvY3VtZW50J3MgcGFydGl0aW9uZXIuCgkgKiAKCSAqIEBzZWUgSURvY3VtZW50UGFydGl0aW9uZXIKCSAqLwoJcHVibGljIElEb2N1bWVudFBhcnRpdGlvbmVyIGdldERvY3VtZW50UGFydGl0aW9uZXIoKSB7CgkJcmV0dXJuIGdldERvY3VtZW50UGFydGl0aW9uZXIoSURvY3VtZW50RXh0ZW5zaW9uMy5ERUZBVUxUX1BBUlRJVElPTklORyk7Cgl9CgoKCXB1YmxpYyBJRG9jdW1lbnRQYXJ0aXRpb25lciBnZXREb2N1bWVudFBhcnRpdGlvbmVyKFN0cmluZyBwYXJ0aXRpb25pbmcpIHsKCgkJSURvY3VtZW50UGFydGl0aW9uZXIgZG9jdW1lbnRQYXJ0aXRpb25lciA9IG51bGw7CgkJaWYgKGZEb2N1bWVudFBhcnRpdGlvbmVycyAhPSBudWxsKSB7CgkJCWRvY3VtZW50UGFydGl0aW9uZXIgPSAoSURvY3VtZW50UGFydGl0aW9uZXIpIGZEb2N1bWVudFBhcnRpdGlvbmVycy5nZXQocGFydGl0aW9uaW5nKTsKCQl9CgkJcmV0dXJuIGRvY3VtZW50UGFydGl0aW9uZXI7Cgl9CgoJcHVibGljIEVuY29kaW5nTWVtZW50byBnZXRFbmNvZGluZ01lbWVudG8oKSB7CgkJcmV0dXJuIGVuY29kaW5nTWVtZW50bzsKCX0KCglwdWJsaWMgSVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbiBnZXRGaXJzdFN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbigpIHsKCQkvLyBzaG91bGQgd2UgdXBkYXRlIGNhY2hlZE5vZGU/CgkJLy8gV2Ugc2hvdWxkIHRvIGtlZXAgY29uc2lzdGVudCBwaGlsb3NvcGh5IG9mIHJlbWVtYmVyaW5nIGxhc3QKCQkvLyByZXF1ZXN0ZWQgcG9zaXRpb24sCgkJLy8gZm9yIGVmZmljaWVuY3kuCgkJc2V0Q2FjaGVkRG9jdW1lbnRSZWdpb24oZmlyc3REb2N1bWVudFJlZ2lvbik7CgkJcmV0dXJuIGZpcnN0RG9jdW1lbnRSZWdpb247Cgl9CgoJcHVibGljIElTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb24gZ2V0TGFzdFN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbigpIHsKCQkvLyBzaG91bGQgd2UgdXBkYXRlIGNhY2hlZE5vZGU/CgkJLy8gV2Ugc2hvdWxkIHRvIGtlZXAgY29uc2lzdGVudCBwaGlsb3NvcGh5IG9mIHJlbWVtYmVyaW5nIGxhc3QKCQkvLyByZXF1ZXN0ZWQgcG9zaXRpb24sCgkJLy8gZm9yIGVmZmljaWVuY3kuCgkJc2V0Q2FjaGVkRG9jdW1lbnRSZWdpb24obGFzdERvY3VtZW50UmVnaW9uKTsKCQlyZXR1cm4gbGFzdERvY3VtZW50UmVnaW9uOwoJfQoKCS8qCgkgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBwYXJ0aXRpb25zCgkgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgkgKi8KCXB1YmxpYyBTdHJpbmdbXSBnZXRMZWdhbENvbnRlbnRUeXBlcygpIHsKCQlTdHJpbmdbXSByZXN1bHQgPSBudWxsOwoJCXRyeSB7CgkJCXJlc3VsdCA9IGdldExlZ2FsQ29udGVudFR5cGVzKElTdHJ1Y3R1cmVkUGFydGl0aW9uaW5nLkRFRkFVTFRfU1RSVUNUVVJFRF9QQVJUSVRJT05JTkcpOwoJCX0KCQljYXRjaCAoQmFkUGFydGl0aW9uaW5nRXhjZXB0aW9uIGUpIHsKCQkJLy8gaW1wb3NzaWJsZSBpbiB0aGlzIGNvbnRleHQKCQkJdGhyb3cgbmV3IEVycm9yKGUpOwoJCX0KCQlyZXR1cm4gcmVzdWx0OwoJfQoKCXB1YmxpYyBTdHJpbmdbXSBnZXRMZWdhbENvbnRlbnRUeXBlcyhTdHJpbmcgcGFydGl0aW9uaW5nKSB0aHJvd3MgQmFkUGFydGl0aW9uaW5nRXhjZXB0aW9uIHsKCQlJRG9jdW1lbnRQYXJ0aXRpb25lciBwYXJ0aXRpb25lciA9IGdldERvY3VtZW50UGFydGl0aW9uZXIocGFydGl0aW9uaW5nKTsKCQlpZiAocGFydGl0aW9uZXIgIT0gbnVsbCkKCQkJcmV0dXJuIHBhcnRpdGlvbmVyLmdldExlZ2FsQ29udGVudFR5cGVzKCk7CgkJaWYgKElTdHJ1Y3R1cmVkUGFydGl0aW9uaW5nLkRFRkFVTFRfU1RSVUNUVVJFRF9QQVJUSVRJT05JTkcuZXF1YWxzKHBhcnRpdGlvbmluZykpCgkJCXJldHVybiBuZXcgU3RyaW5nW117REVGQVVMVF9DT05URU5UX1RZUEV9OwoJCXRocm93IG5ldyBCYWRQYXJ0aXRpb25pbmdFeGNlcHRpb24oKTsKCX0KCgkvKgoJICogLS0tLS0tLS0tLS0tLS0tLS0tIGxpbmUgZGVsaW1pdGVyIGNvbnZlcnNpb24KCSAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoJICovCglwdWJsaWMgU3RyaW5nW10gZ2V0TGVnYWxMaW5lRGVsaW1pdGVycygpIHsKCQlyZXR1cm4gZ2V0VHJhY2tlcigpLmdldExlZ2FsTGluZURlbGltaXRlcnMoKTsKCX0KCgkvKioKCSAqIEBzZWUgSURvY3VtZW50I2dldExlbmd0aAoJICovCglwdWJsaWMgaW50IGdldExlbmd0aCgpIHsKCQlyZXR1cm4gZ2V0U3RvcmUoKS5nZXRMZW5ndGgoKTsKCX0KCgkvKgoJICogKG5vbi1KYXZhZG9jKQoJICogCgkgKiBAc2VlIG9yZy5lY2xpcHNlLndzdC5zc2UuY29yZS5pbnRlcm5hbC5wcm92aXNpb25hbC50ZXh0LklTdHJ1Y3R1cmVkRG9jdW1lbnQjZ2V0TGluZURlbGltaXRlcigpCgkgKi8KCXB1YmxpYyBTdHJpbmcgZ2V0TGluZURlbGltaXRlcigpIHsKCQlyZXR1cm4gZ2V0RGVmYXVsdExpbmVEZWxpbWl0ZXIoKTsKCX0KCgkvKioKCSAqIFJldHVybnMgdGhlIGxpbmUgZGVsaW1pdGVyIG9mIHRoYXQgbGluZQoJICogCgkgKiBAZXhjZXB0aW9uIEJhZExvY2F0aW9uRXhjZXB0aW9uCgkgKiAgICAgICAgICAgICAgICBJZiB0aGUgbGluZSBudW1iZXIgaXMgaW52YWxpZCBpbiB0aGUgZG9jdW1lbnQKCSAqLwoJcHVibGljIFN0cmluZyBnZXRMaW5lRGVsaW1pdGVyKGludCBsaW5lKSB0aHJvd3Mgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5CYWRMb2NhdGlvbkV4Y2VwdGlvbiB7CgkJcmV0dXJuIGdldFRyYWNrZXIoKS5nZXRMaW5lRGVsaW1pdGVyKGxpbmUpOwoJfQoKCS8qKgoJICogUmV0dXJucyBhIGRlc2NyaXB0aW9uIG9mIHRoZSBzcGVjaWZpZWQgbGluZS4gVGhlIGxpbmUgaXMgZGVzY3JpYmVkIGJ5CgkgKiBpdHMgb2Zmc2V0IGFuZCBpdHMgbGVuZ3RoIGV4Y2x1ZGluZyB0aGUgbGluZSdzIGRlbGltaXRlci4KCSAqIAoJICogQHBhcmFtIGxpbmUKCSAqICAgICAgICAgICAgdGhlIGxpbmUgb2YgaW50ZXJlc3QKCSAqIEByZXR1cm4gYSBsaW5lIGRlc2NyaXB0aW9uCgkgKiBAZXhjZXB0aW9uIEJhZExvY2F0aW9uRXhjZXB0aW9uCgkgKiAgICAgICAgICAgICAgICBpZiB0aGUgbGluZSBudW1iZXIgaXMgaW52YWxpZCBpbiB0aGlzIGRvY3VtZW50CgkgKi8KCXB1YmxpYyBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklSZWdpb24gZ2V0TGluZUluZm9ybWF0aW9uKGludCBsaW5lKSB0aHJvd3Mgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5CYWRMb2NhdGlvbkV4Y2VwdGlvbiB7CgkJcmV0dXJuIGdldFRyYWNrZXIoKS5nZXRMaW5lSW5mb3JtYXRpb24obGluZSk7Cgl9CgoJLyoqCgkgKiBSZXR1cm5zIGEgZGVzY3JpcHRpb24gb2YgdGhlIGxpbmUgYXQgdGhlIGdpdmVuIG9mZnNldC4gVGhlIGRlc2NyaXB0aW9uCgkgKiBjb250YWlucyB0aGUgb2Zmc2V0IGFuZCB0aGUgbGVuZ3RoIG9mIHRoZSBsaW5lIGV4Y2x1ZGluZyB0aGUgbGluZSdzCgkgKiBkZWxpbWl0ZXIuCgkgKiAKCSAqIEBwYXJhbSBvZmZzZXQKCSAqICAgICAgICAgICAgdGhlIG9mZnNldCB3aG9zZSBsaW5lIHNob3VsZCBiZSBkZXNjcmliZWQKCSAqIEByZXR1cm4gYSByZWdpb24gZGVzY3JpYmluZyB0aGUgbGluZQoJICogQGV4Y2VwdGlvbiBCYWRMb2NhdGlvbkV4Y2VwdGlvbgoJICogICAgICAgICAgICAgICAgaWYgb2Zmc2V0IGlzIGludmFsaWQgaW4gdGhpcyBkb2N1bWVudAoJICovCglwdWJsaWMgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5JUmVnaW9uIGdldExpbmVJbmZvcm1hdGlvbk9mT2Zmc2V0KGludCBvZmZzZXQpIHRocm93cyBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LkJhZExvY2F0aW9uRXhjZXB0aW9uIHsKCQlyZXR1cm4gZ2V0VHJhY2tlcigpLmdldExpbmVJbmZvcm1hdGlvbk9mT2Zmc2V0KG9mZnNldCk7Cgl9CgoJLyoKCSAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gbGluZSBpbmZvcm1hdGlvbgoJICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCSAqLwoJcHVibGljIGludCBnZXRMaW5lTGVuZ3RoKGludCBsaW5lKSB0aHJvd3Mgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5CYWRMb2NhdGlvbkV4Y2VwdGlvbiB7CgkJcmV0dXJuIGdldFRyYWNrZXIoKS5nZXRMaW5lTGVuZ3RoKGxpbmUpOwoJfQoKCS8qKgoJICogRGV0ZXJtaW5lcyB0aGUgb2Zmc2V0IG9mIHRoZSBmaXJzdCBjaGFyYWN0ZXIgb2YgdGhlIGdpdmVuIGxpbmUuCgkgKiAKCSAqIEBwYXJhbSBsaW5lCgkgKiAgICAgICAgICAgIHRoZSBsaW5lIG9mIGludGVyZXN0CgkgKiBAcmV0dXJuIHRoZSBkb2N1bWVudCBvZmZzZXQKCSAqIEBleGNlcHRpb24gQmFkTG9jYXRpb25FeGNlcHRpb24KCSAqICAgICAgICAgICAgICAgIGlmIHRoZSBsaW5lIG51bWJlciBpcyBpbnZhbGlkIGluIHRoaXMgZG9jdW1lbnQKCSAqLwoJcHVibGljIGludCBnZXRMaW5lT2Zmc2V0KGludCBsaW5lKSB0aHJvd3Mgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5CYWRMb2NhdGlvbkV4Y2VwdGlvbiB7CgkJcmV0dXJuIGdldFRyYWNrZXIoKS5nZXRMaW5lT2Zmc2V0KGxpbmUpOwoJfQoKCXB1YmxpYyBpbnQgZ2V0TGluZU9mT2Zmc2V0KGludCBvZmZzZXQpIHsKCQlpbnQgcmVzdWx0ID0gLTE7CgkJdHJ5IHsKCQkJcmVzdWx0ID0gZ2V0VHJhY2tlcigpLmdldExpbmVOdW1iZXJPZk9mZnNldChvZmZzZXQpOwoJCX0KCQljYXRjaCAoQmFkTG9jYXRpb25FeGNlcHRpb24gZSkgewoJCQlpZiAoTG9nZ2VyLkRFQlVHX0RPQ1VNRU5UKQoJCQkJTG9nZ2VyLmxvZyhMb2dnZXIuSU5GTywgIkRldi4gUHJvZ3JhbSBJbmZvIE9ubHk6IElTdHJ1Y3R1cmVkRG9jdW1lbnQ6OmdldExpbmVPZk9mZnNldDogb2Zmc2V0IG91dCBvZiByYW5nZSwgemVybyBhc3N1bWVkLiBvZmZzZXQgPSAiICsgb2Zmc2V0LCBlKTsgLy8kTk9OLU5MUy0xJCAvLyROT04tTkxTLTIkCgkJCXJlc3VsdCA9IDA7CgkJfQoJCXJldHVybiByZXN1bHQ7Cgl9CgoJLyoqCgkgKiBSZXR1cm5zIHRoZSBudW1iZXIgb2YgbGluZXMgaW4gdGhpcyBkb2N1bWVudAoJICogCgkgKiBAcmV0dXJuIHRoZSBudW1iZXIgb2YgbGluZXMgaW4gdGhpcyBkb2N1bWVudAoJICovCglwdWJsaWMgaW50IGdldE51bWJlck9mTGluZXMoKSB7CgkJcmV0dXJuIGdldFRyYWNrZXIoKS5nZXROdW1iZXJPZkxpbmVzKCk7Cgl9CgoJLyoqCgkgKiBSZXR1cm5zIHRoZSBudW1iZXIgb2YgbGluZXMgd2hpY2ggYXJlIG9jY3VwaWVkIGJ5IGEgZ2l2ZW4gdGV4dCByYW5nZS4KCSAqIAoJICogQHBhcmFtIG9mZnNldAoJICogICAgICAgICAgICB0aGUgb2Zmc2V0IG9mIHRoZSBzcGVjaWZpZWQgdGV4dCByYW5nZQoJICogQHBhcmFtIGxlbmd0aAoJICogICAgICAgICAgICB0aGUgbGVuZ3RoIG9mIHRoZSBzcGVjaWZpZWQgdGV4dCByYW5nZQoJICogQHJldHVybiB0aGUgbnVtYmVyIG9mIGxpbmVzIG9jY3VwaWVkIGJ5IHRoZSBzcGVjaWZpZWQgcmFuZ2UKCSAqIEBleGNlcHRpb24gQmFkTG9jYXRpb25FeGNlcHRpb24KCSAqICAgICAgICAgICAgICAgIGlmIHNwZWNpZmllZCByYW5nZSBpcyBpbnZhbGlkIGluIHRoaXMgdHJhY2tlcgoJICovCglwdWJsaWMgaW50IGdldE51bWJlck9mTGluZXMoaW50IG9mZnNldCwgaW50IGxlbmd0aCkgdGhyb3dzIG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuQmFkTG9jYXRpb25FeGNlcHRpb24gewoJCXJldHVybiBnZXRUcmFja2VyKCkuZ2V0TnVtYmVyT2ZMaW5lcyhvZmZzZXQsIGxlbmd0aCk7Cgl9CgoJLyoqCgkgKiBUaGlzIGlzIHB1YmxpYywgdGVtcG9yYXJpbHksIGZvciB1c2UgYnkgdGFnIGxpYiBjbGFzc2VzLgoJICovCglwdWJsaWMgUmVnaW9uUGFyc2VyIGdldFBhcnNlcigpIHsKCQlpZiAoZlBhcnNlciA9PSBudWxsKSB7CgkJCXRocm93IG5ldyBJbGxlZ2FsU3RhdGVFeGNlcHRpb24oIklTdHJ1Y3R1cmVkRG9jdW1lbnQ6OmdldFBhcnNlci4gUGFyc2VyIG5lZWRzIHRvIGJlIHNldCBiZWZvcmUgdXNlIik7IC8vJE5PTi1OTFMtMSQKCQl9CgkJcmV0dXJuIGZQYXJzZXI7Cgl9CgoJLyoqCgkgKiBSZXR1cm5zIHRoZSBkb2N1bWVudCBwYXJ0aXRpb24gaW4gd2hpY2ggdGhlIHBvc2l0aW9uIGlzIGxvY2F0ZWQuIFRoZQoJICogcGFydGl0aW9uIGlzIHNwZWNpZmllZCBhcyB0eXBlZCByZWdpb24uCgkgKi8KCXB1YmxpYyBJVHlwZWRSZWdpb24gZ2V0UGFydGl0aW9uKGludCBvZmZzZXQpIHRocm93cyBCYWRMb2NhdGlvbkV4Y2VwdGlvbiB7CgkJSVR5cGVkUmVnaW9uIHBhcnRpdGlvbiA9IG51bGw7CgkJdHJ5IHsKCQkJcGFydGl0aW9uID0gZ2V0UGFydGl0aW9uKElTdHJ1Y3R1cmVkUGFydGl0aW9uaW5nLkRFRkFVTFRfU1RSVUNUVVJFRF9QQVJUSVRJT05JTkcsIG9mZnNldCwgZmFsc2UpOwoJCX0KCQljYXRjaCAoQmFkUGFydGl0aW9uaW5nRXhjZXB0aW9uIGUpIHsKCQkJdGhyb3cgbmV3IEVycm9yKGUpOwoJCX0KCQlpZiAocGFydGl0aW9uID09IG51bGwpIHsKCQkJdGhyb3cgbmV3IEVycm9yKCk7CgkJfQoJCXJldHVybiBwYXJ0aXRpb247Cgl9CgoKCXB1YmxpYyBJVHlwZWRSZWdpb24gZ2V0UGFydGl0aW9uKFN0cmluZyBwYXJ0aXRpb25pbmcsIGludCBvZmZzZXQsIGJvb2xlYW4gcHJlZmVyT3BlblBhcnRpdGlvbnMpIHRocm93cyBCYWRMb2NhdGlvbkV4Y2VwdGlvbiwgQmFkUGFydGl0aW9uaW5nRXhjZXB0aW9uIHsKCQlpZiAoKDAgPiBvZmZzZXQpIHx8IChvZmZzZXQgPiBnZXRMZW5ndGgoKSkpCgkJCXRocm93IG5ldyBCYWRMb2NhdGlvbkV4Y2VwdGlvbigpOwoJCUlUeXBlZFJlZ2lvbiByZXN1bHQgPSBudWxsOwoKCQlJRG9jdW1lbnRQYXJ0aXRpb25lciBwYXJ0aXRpb25lciA9IGdldERvY3VtZW50UGFydGl0aW9uZXIocGFydGl0aW9uaW5nKTsKCgkJaWYgKHBhcnRpdGlvbmVyIGluc3RhbmNlb2YgSURvY3VtZW50UGFydGl0aW9uZXJFeHRlbnNpb24yKSB7CgkJCXJlc3VsdCA9ICgoSURvY3VtZW50UGFydGl0aW9uZXJFeHRlbnNpb24yKSBwYXJ0aXRpb25lcikuZ2V0UGFydGl0aW9uKG9mZnNldCwgcHJlZmVyT3BlblBhcnRpdGlvbnMpOwoJCX0KCQllbHNlIGlmIChwYXJ0aXRpb25lciAhPSBudWxsKSB7CgkJCXJlc3VsdCA9IHBhcnRpdGlvbmVyLmdldFBhcnRpdGlvbihvZmZzZXQpOwoJCX0KCQllbHNlIGlmIChJU3RydWN0dXJlZFBhcnRpdGlvbmluZy5ERUZBVUxUX1NUUlVDVFVSRURfUEFSVElUSU9OSU5HLmVxdWFscyhwYXJ0aXRpb25pbmcpKSB7CgkJCXJlc3VsdCA9IG5ldyBUeXBlZFJlZ2lvbigwLCBnZXRMZW5ndGgoKSwgREVGQVVMVF9DT05URU5UX1RZUEUpOwoJCX0KCQllbHNlCgkJCXRocm93IG5ldyBCYWRQYXJ0aXRpb25pbmdFeGNlcHRpb24oKTsKCQlyZXR1cm4gcmVzdWx0OwoJfQoKCglwdWJsaWMgU3RyaW5nW10gZ2V0UGFydGl0aW9uaW5ncygpIHsKCQlpZiAoZkRvY3VtZW50UGFydGl0aW9uZXJzID09IG51bGwpCgkJCXJldHVybiBuZXcgU3RyaW5nWzBdOwoJCVN0cmluZ1tdIHBhcnRpdGlvbmluZ3MgPSBuZXcgU3RyaW5nW2ZEb2N1bWVudFBhcnRpdGlvbmVycy5zaXplKCldOwoJCWZEb2N1bWVudFBhcnRpdGlvbmVycy5rZXlTZXQoKS50b0FycmF5KHBhcnRpdGlvbmluZ3MpOwoJCXJldHVybiBwYXJ0aXRpb25pbmdzOwoJfQoKCS8qKgoJICogUmV0dXJucyBhbGwgcG9zaXRpb24gY2F0ZWdvcmllcyBhZGRlZCB0byB0aGlzIGRvY3VtZW50LgoJICovCglwdWJsaWMgU3RyaW5nW10gZ2V0UG9zaXRpb25DYXRlZ29yaWVzKCkgewoJCXJldHVybiBnZXRQb3NpdGlvbk1hbmFnZXIoKS5nZXRQb3NpdGlvbkNhdGVnb3JpZXMoKTsKCX0KCgkvKioKCSAqIEByZXR1cm4gUmV0dXJucyB0aGUgcG9zaXRpb25NYW5hZ2VyLgoJICovCglwcml2YXRlIEdlbmVyaWNQb3NpdGlvbk1hbmFnZXIgZ2V0UG9zaXRpb25NYW5hZ2VyKCkgewoJCWlmIChmUG9zaXRpb25NYW5hZ2VyID09IG51bGwpIHsKCQkJZlBvc2l0aW9uTWFuYWdlciA9IG5ldyBHZW5lcmljUG9zaXRpb25NYW5hZ2VyKHRoaXMpOwoJCX0KCQlyZXR1cm4gZlBvc2l0aW9uTWFuYWdlcjsKCX0KCgkvKioKCSAqIFJldHVybnMgYWxsIFBvc2l0aW9ucyBvZiB0aGUgZ2l2ZW4gcG9zaXRpb24gY2F0ZWdvcnkuCgkgKiAKCSAqIEBleGNlcHRpb24gQmFkUG9zaXRpb25DYXRlZ29yeUV4Y2VwdGlvbgoJICogICAgICAgICAgICAgICAgSWYgY2F0ZWdvcnkgaXMgbm90IGRlZmluZWQgZm9yIHRoZSBkb2N1bWVudAoJICovCglwdWJsaWMgUG9zaXRpb25bXSBnZXRQb3NpdGlvbnMoU3RyaW5nIGNhdGVnb3J5KSB0aHJvd3Mgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5CYWRQb3NpdGlvbkNhdGVnb3J5RXhjZXB0aW9uIHsKCQlyZXR1cm4gZ2V0UG9zaXRpb25NYW5hZ2VyKCkuZ2V0UG9zaXRpb25zKGNhdGVnb3J5KTsKCX0KCgkvKioKCSAqIEBzZWUgSURvY3VtZW50I2dldFBvc2l0aW9uVXBkYXRlcnMKCSAqLwoJcHVibGljIElQb3NpdGlvblVwZGF0ZXJbXSBnZXRQb3NpdGlvblVwZGF0ZXJzKCkgewoJCXJldHVybiBnZXRQb3NpdGlvbk1hbmFnZXIoKS5nZXRQb3NpdGlvblVwZGF0ZXJzKCk7Cgl9CgoJLyoqCgkgKiBUaGlzIG1ldGhvZCBjYW4gcmV0dXJuIG51bGwsIHdoaWNoIGlzIHRoZSBjYXNlIGlmIHRoZSBvZmZzZXQgaXMganVzdAoJICogYmVmb3JlIG9yIGp1c3QgYWZ0ZXIgdGhlIGV4aXN0aW5nIHRleHQuIENvbXBhcmUgd2l0aAoJICogZ2V0Tm9kZUF0Q2hhcmFjdGVyT2Zmc2V0LgoJICovCglwdWJsaWMgSVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbiBnZXRSZWdpb25BdENoYXJhY3Rlck9mZnNldChpbnQgb2Zmc2V0KSB7CgkJSVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbiByZXN1bHQgPSBudWxsOwoKCQkvLyBGSVhNRTogbmVlZCB0byBzeW5jaCBvbiAnY2FjaGVkUmVnaW9uJyAoYnV0IHNpbmNlIHRoYXQncyBhCgkJLy8gY29uc3RhbnRseSBjaGFuZ2luZyBvYmplY3QsIHdlCgkJLy8gY2FuJ3QsIHNvIG5lZWQgdG8gYWRkIGEgInJlZ2lvbl9sb2NrIiBvYmplY3QsIGFuZCB1c2UgaXQgaGVyZSwgYW5kCgkJLy8gaW4gcmUtcGFyc2VyLgoJCS8vIE9oLCBhbmQgbmVlZCB0byBtYWtlIHN1cmUsIGFmdGVyIHN5bmNoLCB0aGF0IHRoZSByZWdpb24gaXMgbm90CgkJLy8gZGVsZXRlZCwgYW5kIGlmIHNvLCBJIGd1ZXNzIGdvIGJhY2sKCQkvLyB0byB0aGUgYmVnaW5uaW5nIQoKCQkvLyBjYWNoZWQgbm9kZSBjYW4gYmUgbnVsbCB3aGVuIGRvY3VtZW50IGlzIGVtcHR5CgkJSVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbiBwb3RlbnRpYWxDYWNoZWRSZWdpb24gPSBnZXRDYWNoZWREb2N1bWVudFJlZ2lvbigpOwoJCWlmIChwb3RlbnRpYWxDYWNoZWRSZWdpb24gIT0gbnVsbCkgewoKCQkJLy8gCgoJCQkvLyBpZiB3ZSBhbHJlYWR5IGhhdmUgdGhlIHJpZ2h0IG5vZGUsIHJldHVybiB0aGF0LgoJCQlpZiAocG90ZW50aWFsQ2FjaGVkUmVnaW9uLmNvbnRhaW5zT2Zmc2V0KG9mZnNldCkpIHsKCQkJCXJlc3VsdCA9IHBvdGVudGlhbENhY2hlZFJlZ2lvbjsKCQkJfQoJCQllbHNlIHsKCQkJCS8vIGZpcnN0LCBmaW5kIG91dCB3aGF0IGRpcmVjdGlvbiB0byBnbywgcmVsYXRpdmUgdG8KCQkJCS8vIGNhY2hlZE5vZGUuCgkJCQkvLyBuZWdhdGl2ZSBtZWFucyAidG93YXJkcyB0aGUgZnJvbnQiIG9mIHRoZSBmaWxlLAoJCQkJLy8gcG9zdGl0aXZlCgkJCQkvLyBtZWFucwoJCQkJLy8gdG93YXJkcyB0aGUgZW5kLgoJCQkJaW50IGRpcmVjdGlvbiA9IG9mZnNldCAtIHBvdGVudGlhbENhY2hlZFJlZ2lvbi5nZXRTdGFydCgpOwoJCQkJaWYgKGRpcmVjdGlvbiA8IDApIHsKCQkJCQkvLyBzZWFyY2ggdG93YXJkcyBiZWdpbm5pbmcKCQkJCQl3aGlsZSAoIXBvdGVudGlhbENhY2hlZFJlZ2lvbi5jb250YWluc09mZnNldChvZmZzZXQpKSB7CgkJCQkJCUlTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb24gdGVtcE5vZGUgPSBwb3RlbnRpYWxDYWNoZWRSZWdpb24uZ2V0UHJldmlvdXMoKTsKCQkJCQkJaWYgKHRlbXBOb2RlID09IG51bGwpIHsKCQkJCQkJCWJyZWFrOwoJCQkJCQl9CgkJCQkJCWVsc2UgewoJCQkJCQkJcG90ZW50aWFsQ2FjaGVkUmVnaW9uID0gdGVtcE5vZGU7CgkJCQkJCX0KCQkJCQl9CgkJCQl9CgkJCQllbHNlIHsKCQkJCQkvLyBzZWFyY2ggdG93YXJkcyBlbmQKCQkJCQkvLyBUaGVyZSBpcyBhIGxlZ2l0YW1hdCBjb25kaXRpb24gd2hlcmUgdGhlCgkJCQkJLy8gb2Zmc2V0IHdpbGwgbm90IGJlIGNvbnRhaW5lZCBpbiBhbnkgbm9kZSwKCQkJCQkvLyB3aGljaCBpcyBpZiB0aGUgb2Zmc2V0IGlzIGp1c3QgcGFzdCB0aGUgbGFzdAoJCQkJCS8vIGNoYXJhY3RlciBvZiB0ZXh0LgoJCQkJCS8vIEFuZCwgd2UgbXVzdCBnYXVyZCBhZ2FpbnN0IHNldHRpbmcgY2FjaGVkTm9kZSB0bwoJCQkJCS8vIG51bGwhCgkJCQkJd2hpbGUgKCFwb3RlbnRpYWxDYWNoZWRSZWdpb24uY29udGFpbnNPZmZzZXQob2Zmc2V0KSkgewoJCQkJCQlJU3RydWN0dXJlZERvY3VtZW50UmVnaW9uIHRlbXBOb2RlID0gcG90ZW50aWFsQ2FjaGVkUmVnaW9uLmdldE5leHQoKTsKCQkJCQkJaWYgKHRlbXBOb2RlID09IG51bGwpCgkJCQkJCQlicmVhazsKCQkJCQkJZWxzZQoJCQkJCQkJcG90ZW50aWFsQ2FjaGVkUmVnaW9uID0gdGVtcE5vZGU7CgkJCQkJfQoJCQkJfQoJCQl9CgkJCXJlc3VsdCA9IHBvdGVudGlhbENhY2hlZFJlZ2lvbjsKCQl9CgkJLy8ganVzdCB0byBiZSBkb3VibHkgc3VyZSB3ZSBuZXZlciBhc3NpZ24gbnVsbCB0byBhbiBhbHJlYWR5IHZhbGlkCgkJLy8gY2FjaGVkUmVnaW9uLgoJCS8vIEkgYmVsaWV2ZSBhbnkgdGltZSAncmVzdWx0JyBpcyBudWxsIGF0IHRoaXMgcG9pbnQsIHRoYXQganVzdCBtZWFucwoJCS8vIHdlIGhhdmUgYW4KCQkvLyBlbXB0eSBkb2N1bWVudCwgYW5kIHRoZSBjYWNoZWRSZWdpb24gaXMgYWxyZWFkeSBudWxsLCBidXQgd2UgY2hlY2sKCQkvLyBhbmQgcHJpbnQKCQkvLyB3YXJuaW5nLCBqdXN0IHNvIGR1cmluZyBkZXZlbG9wbWVudCB3ZSBiZSBzdXJlIHdlIG5ldmVyIGFjY2lkZW50bHkKCQkvLyBicmVhayB0aGlzIGFzc3VtcHRpb24uCgkJaWYgKHJlc3VsdCAhPSBudWxsKQoJCQlzZXRDYWNoZWREb2N1bWVudFJlZ2lvbihyZXN1bHQpOwoJCWVsc2UgaWYgKGdldENhY2hlZERvY3VtZW50UmVnaW9uKCkgIT0gbnVsbCkgewoJCQl0aHJvdyBuZXcgSWxsZWdhbFN0YXRlRXhjZXB0aW9uKCJQcm9ncmFtIEVycm9yOiBubyByZWdpb24gY291bGQgYmUgZm91bmQgdG8gY2FjaGUsIGJ1dCBjYWNoZSB3YXMgbm9uIG51bGwuIEluZGljYXRlcyBjb3JydXB0ZWQgbW9kZWwgb3IgcmVnaW9uIGxpc3QiKTsgLy8kTk9OLU5MUy0xJAoJCX0KCgkJcmV0dXJuIHJlc3VsdDsKCX0KCglwdWJsaWMgSVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbkxpc3QgZ2V0UmVnaW9uTGlzdCgpIHsKCQlDb3JlTm9kZUxpc3QgcmVzdWx0ID0gbnVsbDsKCQlpZiAoZ2V0Q2FjaGVkRG9jdW1lbnRSZWdpb24oKSA9PSBudWxsKQoJCQlyZXN1bHQgPSBuZXcgQ29yZU5vZGVMaXN0KG51bGwpOwoJCWVsc2UKCQkJcmVzdWx0ID0gbmV3IENvcmVOb2RlTGlzdChnZXRGaXJzdFN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbigpKTsKCgkJcmV0dXJuIHJlc3VsdDsKCX0KCgoJcHVibGljIElTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb25bXSBnZXRTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb25zKCkgewoJCXJldHVybiBnZXRTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb25zKDAsIGdldExlbmd0aCgpKTsKCX0KCgkvKioKCSAqIDxwPgoJICogSW4gdGhlIGNhc2Ugb2YgMCBsZW5ndGgsIHRoZSA8Y29kZT5JU3RydWN0dXJlZERvY3VtZW50UmVnaW9uPC9jb2RlPgoJICogYXQgdGhlIGNoYXJhY3RlciBvZmZzZXQgaXMgcmV0dXJlbmVkLiBJbiBvdGhlciB3b3JkcywgdGhlIHJlZ2lvbiB0byB0aGUKCSAqIHJpZ2h0IG9mIHRoZSBjYXJldCBpcyByZXR1cm5lZC4gZXhjZXB0IGZvciBhdCB0aGUgZW5kIG9mIHRoZSBkb2N1bWVudCwKCSAqIHRoZW4gdGhlIGxhc3QgcmVnaW9uIGlzIHJldHVybmVkLgoJICogPC9wPgoJICogPHA+CgkgKiBPdGhlcndpc2UgYWxsIHRoZSByZWdpb25zICJpbmJldHdlZW4iIHRoZSBpbmRpY2F0ZWQgcmFuZ2UgYXJlIHJldHVybmVkLAoJICogaW5jbHVkaW5nIHRoZSByZWdpb25zIHdoaWNoIG92ZXJsYXAgdGhlIHJlZ2lvbi4KCSAqIDwvcD4KCSAqIAoJICogPGJyPgoJICogZWcuCgkgKiA8cD4KCSAqIDxicj4KCSAqIGVnLgoJICogCgkgKiA8cHJlPgoJICogICAgICAgICAgICAgICAgICAgICAgICAmbHQ7aHRtbCZndDtbJmx0O2hlYWQmZ3Q7Jmx0Oy9oZWFkJmd0O10mbHQ7L2h0bWwmZ3Q7IHJldHVybnMgJmx0O2hlYWQmZ3Q7LCZsdDsvaGVhZCZndDsKCSAqIDwvcHJlPgoJICogICAgPHByZT4KCSAqICAgICAgICAgICAgICAgICAgICAgICAgJmx0O2h0W21sJmd0OyZsdDtoZWFkJmd0OyZsdDsvaGVdYWQmZ3Q7Jmx0Oy9odG1sJmd0OyByZXR1cm5zICZsdDtodG1sJmd0OywmbHQ7aGVhZCZndDssJmx0Oy9oZWFkJmd0OwoJICogPC9wcmU+CgkgKiAKCSAqIDxwcmU+CgkgKiAgICAgICAgICAgICAgICAgICAgICAgICAgJmx0O2h0bWwmZ3Q7WyZsdDtoZWFkJmd0OyZsdDsvaGVhZCZndDtdJmx0Oy9odG1sJmd0OyByZXR1cm5zICZsdDtoZWFkJmd0OywmbHQ7L2hlYWQmZ3Q7CgkgKiA8L3ByZT4KCSAqICAgIDxwcmU+CgkgKiAgICAgICAgICAgICAgICAgICAgICAgICAgJmx0O2h0W21sJmd0OyZsdDtoZWFkJmd0OyZsdDsvaGVdYWQmZ3Q7Jmx0Oy9odG1sJmd0OyByZXR1cm5zICZsdDtodG1sJmd0OywmbHQ7aGVhZCZndDssJmx0Oy9oZWFkJmd0OwoJICogPC9wcmU+CgkgKiAKCSAqIDwvcD4KCSAqLwoJcHVibGljIElTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb25bXSBnZXRTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb25zKGludCBzdGFydCwgaW50IGxlbmd0aCkgewoKCQlpZiAobGVuZ3RoIDwgMCkKCQkJdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigiY2FuJ3QgaGF2ZSBuZWdhdGl2ZSBsZW5ndGgiKTsgLy8kTk9OLU5MUy0xJAoKCQkvLyB0aGlzIHdpbGwgbWFrZSB0aGUgcmlnaHQgZWRnZSBvZiB0aGUgcmFuZ2UgcG9pbnQgaW50byB0aGUgc2VsZWN0aW9uCgkJLy8gZWcuIDxodG1sPls8aGVhZD48L2hlYWQ+XTwvaHRtbD4KCQkvLyB3aWxsIHJldHVybiA8aGVhZD4sPC9oZWFkPiBpbnN0ZWFkIG9mIDxoZWFkPiw8L2hlYWQ+LDwvaHRtbD4KCQlpZiAobGVuZ3RoID4gMCkKCQkJbGVuZ3RoLS07CgoJCUxpc3QgcmVzdWx0cyA9IG5ldyBBcnJheUxpc3QoKTsKCgkJLy8gc3RhcnQgdGhyZWFkIHNhZmUgYmxvY2sKCQl0cnkgewoJCQlhY3F1aXJlTG9jaygpOwoKCQkJSVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbiBjdXJyZW50UmVnaW9uID0gZ2V0UmVnaW9uQXRDaGFyYWN0ZXJPZmZzZXQoc3RhcnQpOwoJCQlJU3RydWN0dXJlZERvY3VtZW50UmVnaW9uIGVuZFJlZ2lvbiA9IGdldFJlZ2lvbkF0Q2hhcmFjdGVyT2Zmc2V0KHN0YXJ0ICsgbGVuZ3RoKTsKCQkJd2hpbGUgKGN1cnJlbnRSZWdpb24gIT0gZW5kUmVnaW9uICYmIGN1cnJlbnRSZWdpb24gIT0gbnVsbCkgewoJCQkJcmVzdWx0cy5hZGQoY3VycmVudFJlZ2lvbik7CgkJCQljdXJyZW50UmVnaW9uID0gY3VycmVudFJlZ2lvbi5nZXROZXh0KCk7CgkJCX0KCQkJLy8gbmVlZCB0byBhZGQgdGhhdCBsYXN0IGVuZCByZWdpb24KCQkJLy8gY2FuIGJlIG51bGwgaW4gdGhlIGNhc2Ugb2YgYW4gZW1wdHkgZG9jdW1lbnQKCQkJaWYgKGVuZFJlZ2lvbiAhPSBudWxsKQoJCQkJcmVzdWx0cy5hZGQoZW5kUmVnaW9uKTsKCQl9CgkJZmluYWxseSB7CgkJCXJlbGVhc2VMb2NrKCk7CgkJfQoJCS8vIGVuZCB0aHJlYWQgc2FmZSBibG9jawoKCQlyZXR1cm4gKElTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb25bXSkgcmVzdWx0cy50b0FycmF5KG5ldyBJU3RydWN0dXJlZERvY3VtZW50UmVnaW9uW3Jlc3VsdHMuc2l6ZSgpXSk7Cgl9CgoJLyoqCgkgKiB3YXMgbWFkZSBwdWJsaWMgZm9yIGVhc2llciB0ZXN0aW5nLiBOb3JtYWxseSBzaG91bGQgbmV2ZXIgYmUgdXNlZCBieQoJICogY2xpZW50IGNvZGVzLgoJICovCglwdWJsaWMgSVN0cnVjdHVyZWRUZXh0UmVQYXJzZXIgZ2V0UmVQYXJzZXIoKSB7CgkJaWYgKGZSZVBhcnNlciA9PSBudWxsKSB7CgkJCWZSZVBhcnNlciA9IG5ldyBTdHJ1Y3R1cmVkRG9jdW1lbnRSZVBhcnNlcigpOwoJCQlmUmVQYXJzZXIuc2V0U3RydWN0dXJlZERvY3VtZW50KHRoaXMpOwoJCX0KCQlyZXR1cm4gZlJlUGFyc2VyOwoJfQoKCXByaXZhdGUgSVRleHRTdG9yZSBnZXRTdG9yZSgpIHsKCQlBc3NlcnQuaXNOb3ROdWxsKGZTdG9yZSk7CgkJcmV0dXJuIGZTdG9yZTsKCX0KCglwdWJsaWMgU3RyaW5nIGdldFRleHQoKSB7CgkJU3RyaW5nIHJlc3VsdCA9IGdldCgpOwoJCXJldHVybiByZXN1bHQ7Cgl9CgoJLyoqCgkgKiBSZXR1cm5zIHRoZSBkb2N1bWVudCdzIGxpbmUgdHJhY2tlci4gQXNzdW1lcyB0aGF0IHRoZSBkb2N1bWVudCBoYXMgYmVlbgoJICogaW5pdGlhbGl6ZWQgd2l0aCBhIGxpbmUgdHJhY2tlci4KCSAqIAoJICogQHJldHVybiB0aGUgZG9jdW1lbnQncyBsaW5lIHRyYWNrZXIKCSAqLwoJcHJpdmF0ZSBJTGluZVRyYWNrZXIgZ2V0VHJhY2tlcigpIHsKCQlBc3NlcnQuaXNOb3ROdWxsKGZUcmFja2VyKTsKCQlyZXR1cm4gZlRyYWNrZXI7Cgl9CgoJcHVibGljIElTdHJ1Y3R1cmVkVGV4dFVuZG9NYW5hZ2VyIGdldFVuZG9NYW5hZ2VyKCkgewoJCWlmIChmVW5kb01hbmFnZXIgPT0gbnVsbCkgewoJCQlmVW5kb01hbmFnZXIgPSBuZXcgU3RydWN0dXJlZFRleHRVbmRvTWFuYWdlcigpOwoJCX0KCQlyZXR1cm4gZlVuZG9NYW5hZ2VyOwoJfQoKCXZvaWQgaW5pdGlhbGl6ZUZpcnN0QW5kTGFzdERvY3VtZW50UmVnaW9uKCkgewoJCS8vIGNhY2hlZCBOb2RlIG11c3QgYWxzbyBiZSBmaXJzdCwgYXQgdGhlIGluaXRpYWwgcG9pbnQuIE9ubHkKCQkvLyB2YWxpZAoJCS8vIHRvIGNhbGwgdGhpcyBtZXRob2QgcmlnaHQgYWZ0ZXIgdGhlIGZpcnN0IHBhcnNlLgoJCS8vIAoJCS8vIHdoZW4gc3RhcnRpbmcgYWZyZXNoLCBvdXIgY2FjaGVkTm9kZSBzaG91bGQgYmUgb3VyIGZpcnN0Tm9kZSwKCQkvLyBzbyBiZSBzdXJlIHRvIGluaXRpYWxpemUgdGhlIGZpcnN0Tm9kZQoJCWZpcnN0RG9jdW1lbnRSZWdpb24gPSBnZXRDYWNoZWREb2N1bWVudFJlZ2lvbigpOwoJCS8vIGJlIHN1cmUgdG8gdXNlICdnZXROZXh0JyBmb3IgdGhpcyBpbml0aWFsIGZpbmRpbmcgb2YgdGhlIGxhc3QKCQkvLyBub2RlLAoJCS8vIHNpbmNlIHRoZSBpbXBsZW1lbnRhdGlvbiBvZiBub2RlLmdldExhc3ROb2RlIG1heSBzaW1wbHkgY2FsbAoJCS8vIHN0cnVjdHVyZWREb2N1bWVudC5nZXRMYXN0U3RydWN0dXJlZERvY3VtZW50UmVnaW9uIQoJCUlTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb24gYU5vZGUgPSBmaXJzdERvY3VtZW50UmVnaW9uOwoJCWlmIChhTm9kZSA9PSBudWxsKSB7CgkJCS8vIGRlZmVjdCAyNTQ2MDc6IHRvIGhhbmRsZSBlbXB0eSBkb2N1bWVudHMgcmlnaHQsIGlmCgkJCS8vIGZpcnN0bm9kZSBpcwoJCQkvLyBudWxsLCBtYWtlIHN1cmUgbGFzdCBub2RlIGlzIG51bGwgdG9vCgkJCWxhc3REb2N1bWVudFJlZ2lvbiA9IG51bGw7CgkJfQoJCWVsc2UgewoJCQl3aGlsZSAoYU5vZGUgIT0gbnVsbCkgewoJCQkJbGFzdERvY3VtZW50UmVnaW9uID0gYU5vZGU7CgkJCQlhTm9kZSA9IGFOb2RlLmdldE5leHQoKTsKCQkJfQoJCX0KCX0KCgkvKioKCSAqIEBzZWUgSURvY3VtZW50I2luc2VydFBvc2l0aW9uVXBkYXRlcgoJICovCglwdWJsaWMgdm9pZCBpbnNlcnRQb3NpdGlvblVwZGF0ZXIoSVBvc2l0aW9uVXBkYXRlciB1cGRhdGVyLCBpbnQgaW5kZXgpIHsKCQlnZXRQb3NpdGlvbk1hbmFnZXIoKS5pbnNlcnRQb3NpdGlvblVwZGF0ZXIodXBkYXRlciwgaW5kZXgpOwoJfQoKCXByaXZhdGUgdm9pZCBpbnRlcm5hbF9hZGRQb3NpdGlvbkNhdGVnb3J5KFN0cmluZyBjYXRlZ29yeSkgewoJCWdldFBvc2l0aW9uTWFuYWdlcigpLmFkZFBvc2l0aW9uQ2F0ZWdvcnkoY2F0ZWdvcnkpOwoJfQoKCXByaXZhdGUgdm9pZCBpbnRlcm5hbF9hZGRQb3NpdGlvblVwZGF0ZXIoSVBvc2l0aW9uVXBkYXRlciB1cGRhdGVyKSB7CgkJZ2V0UG9zaXRpb25NYW5hZ2VyKCkuYWRkUG9zaXRpb25VcGRhdGVyKHVwZGF0ZXIpOwoJfQoKCXByaXZhdGUgdm9pZCBpbnRlcm5hbF9zZXRQYXJzZXIoUmVnaW9uUGFyc2VyIG5ld1BhcnNlcikgewoJCWZQYXJzZXIgPSBuZXdQYXJzZXI7Cgl9CgoJU3RyaW5nIGludGVybmFsR2V0KGludCBvZmZzZXQsIGludCBsZW5ndGgpIHsKCQlTdHJpbmcgcmVzdWx0ID0gbnVsbDsKCQkvLyBpbnQgbXlMZW5ndGggPSBnZXRMZW5ndGgoKTsKCQkvLyBpZiAoKDAgPiBvZmZzZXQpIHx8ICgwID4gbGVuZ3RoKSB8fCAob2Zmc2V0ICsgbGVuZ3RoID4gbXlMZW5ndGgpKQoJCS8vIHRocm93IG5ldyBCYWRMb2NhdGlvbkV4Y2VwdGlvbigpOwoJCXJlc3VsdCA9IGdldFN0b3JlKCkuZ2V0KG9mZnNldCwgbGVuZ3RoKTsKCQlyZXR1cm4gcmVzdWx0OwoJfQoKCS8qKgoJICogQHBhcmFtIHJlcXVlc3RlcgoJICogQHBhcmFtIHN0YXJ0CgkgKiBAcGFyYW0gcmVwbGFjZW1lbnRMZW5ndGgKCSAqIEBwYXJhbSBjaGFuZ2VzCgkgKiBAcmV0dXJuCgkgKi8KCXByaXZhdGUgU3RydWN0dXJlZERvY3VtZW50RXZlbnQgaW50ZXJuYWxSZXBsYWNlVGV4dChPYmplY3QgcmVxdWVzdGVyLCBpbnQgc3RhcnQsIGludCByZXBsYWNlbWVudExlbmd0aCwgU3RyaW5nIGNoYW5nZXMsIGJvb2xlYW4gaWdub3JlUmVhZE9ubHlTZXR0aW5ncykgewoJCVN0cnVjdHVyZWREb2N1bWVudEV2ZW50IHJlc3VsdCA9IG51bGw7CgoJCXN0b3BQb3N0Tm90aWZpY2F0aW9uUHJvY2Vzc2luZygpOwoJCWlmIChjaGFuZ2VzID09IG51bGwpCgkJCWNoYW5nZXMgPSAiIjsgLy8kTk9OLU5MUy0xJAoJCS8vIAoJCWlmIChEZWJ1Zy5kZWJ1Z1N0cnVjdHVyZWREb2N1bWVudCkKCQkJU3lzdGVtLm91dC5wcmludGxuKGdldENsYXNzKCkuZ2V0TmFtZSgpICsgIjo6cmVwbGFjZVRleHQoIiArIHN0YXJ0ICsgIiwiICsgcmVwbGFjZW1lbnRMZW5ndGggKyAiLCIgKyBjaGFuZ2VzICsgIikiKTsgLy8kTk9OLU5MUy00JC8vJE5PTi1OTFMtMyQvLyROT04tTkxTLTIkLy8kTk9OLU5MUy0xJAoJCWlmIChEZWJ1Zy5wZXJmVGVzdFN0cnVjdHVyZWREb2N1bWVudE9ubHkgfHwgRGVidWcucGVyZlRlc3QgfHwgRGVidWcucGVyZlRlc3RSYXdTdHJ1Y3R1cmVkRG9jdW1lbnRPbmx5KSB7CgkJCXN0YXJ0U3RyZWFtVGltZSA9IFN5c3RlbS5jdXJyZW50VGltZU1pbGxpcygpOwoJCX0KCQl0cnkgewoJCQkvLyBOb3RlOiBldmVudCBtdXN0IGJlIGNvbXB1dGVkIGJlZm9yZSAnZmlyZScgbWV0aG9kIGNhbGxlZAoJCQlmRG9jdW1lbnRFdmVudCA9IG5ldyBEb2N1bWVudEV2ZW50KHRoaXMsIHN0YXJ0LCByZXBsYWNlbWVudExlbmd0aCwgY2hhbmdlcyk7CgkJCWZpcmVEb2N1bWVudEFib3V0VG9DaGFuZ2VkKCk7CgoJCQl0cnkgewoJCQkJYWNxdWlyZUxvY2soKTsKCgkJCQlpZiAoIWlnbm9yZVJlYWRPbmx5U2V0dGluZ3MgJiYgKGNvbnRhaW5zUmVhZE9ubHkoc3RhcnQsIHJlcGxhY2VtZW50TGVuZ3RoKSkpIHsKCQkJCQlOb0NoYW5nZUV2ZW50IG5vQ2hhbmdlRXZlbnQgPSBuZXcgTm9DaGFuZ2VFdmVudCh0aGlzLCByZXF1ZXN0ZXIsIGNoYW5nZXMsIHN0YXJ0LCByZXBsYWNlbWVudExlbmd0aCk7CgkJCQkJbm9DaGFuZ2VFdmVudC5yZWFzb24gPSBOb0NoYW5nZUV2ZW50LlJFQURfT05MWV9TVEFURV9DSEFOR0U7CgkJCQkJcmVzdWx0ID0gbm9DaGFuZ2VFdmVudDsKCQkJCX0KCQkJCWVsc2UgewoJCQkJCXJlc3VsdCA9IHVwZGF0ZU1vZGVsKHJlcXVlc3Rlciwgc3RhcnQsIHJlcGxhY2VtZW50TGVuZ3RoLCBjaGFuZ2VzKTsKCQkJCX0KCQkJfQoJCQlmaW5hbGx5IHsKCQkJCXJlbGVhc2VMb2NrKCk7CgkJCX0KCgoJCQlpZiAoRGVidWcucGVyZlRlc3RSYXdTdHJ1Y3R1cmVkRG9jdW1lbnRPbmx5IHx8IERlYnVnLnBlcmZUZXN0KSB7CgkJCQlsb25nIHN0b3BTdHJlYW1UaW1lID0gU3lzdGVtLmN1cnJlbnRUaW1lTWlsbGlzKCk7CgkJCQlTeXN0ZW0ub3V0LnByaW50bG4oIlxuXHRcdFx0XHQgVGltZSBmb3IgSVN0cnVjdHVyZWREb2N1bWVudCByYXcgcmVwbGFjZVRleHQ6ICIgKyAoc3RvcFN0cmVhbVRpbWUgLSBzdGFydFN0cmVhbVRpbWUpKTsgLy8kTk9OLU5MUy0xJAoJCQl9CgkJCWlmIChEZWJ1Zy5kZWJ1Z1N0cnVjdHVyZWREb2N1bWVudCkgewoJCQkJU3lzdGVtLm91dC5wcmludGxuKCJldmVudCB0eXBlIHJldHVybmVkIGJ5IHJlcGxhY2VUZXh0V2l0aE5vRGVidWdnaW5nVGhyZWFkOiAiICsgcmVzdWx0KTsgLy8kTk9OLU5MUy0xJAoJCQl9CgkJfQoJCWZpbmFsbHkgewoJCQkvLyBGVVRVUkVfVE9fRE86IGltcGxlbWVudCBjYWxsYmFjayBtZWNoYW5pc20/IHRvIGF2b2lkIGluc3RhbmNlb2YKCQkJLy8gYW5kIGNhc3RpbmcKCQkJLy8gZmlyZVN0cnVjdHVyZWREb2N1bWVudEV2ZW50IG11c3QgYmUgY2FsbGVkIGluIG9yZGVyIHRvIGVuZAoJCQkvLyBkb2N1bWVudEFib3V0VG9CZUNoYW5nZWQgc3RhdGUKCgkJCS8vIGluY3JlbWVudCBtb2RpZmljYXRpb24gc3RhbXAgaWYgbW9kaWZpY2F0aW9ucyB3ZXJlIG1hZGUKCQkJaWYgKHJlc3VsdCAhPSBudWxsICYmICEocmVzdWx0IGluc3RhbmNlb2YgTm9DaGFuZ2VFdmVudCkpCgkJCQlmTW9kaWZpY2F0aW9uU3RhbXArKzsKCgkJCWlmIChyZXN1bHQgPT0gbnVsbCkgewoJCQkJLy8gcmVzdWx0IHNob3VsZCBub3QgYmUgbnVsbCwgYnV0IGlmIGFuIGV4Y2VwdGlvbiB3YXMgdGhyb3duLAoJCQkJLy8gaXQgd2lsbCBiZQoJCQkJLy8gc28gc2VuZCBhIG5vQ2hhbmdlRXZlbnQgYW5kIGxvZyB0aGUgcHJvYmxlbQoJCQkJTm9DaGFuZ2VFdmVudCBub0NoYW5nZUV2ZW50ID0gbmV3IE5vQ2hhbmdlRXZlbnQodGhpcywgcmVxdWVzdGVyLCBjaGFuZ2VzLCBzdGFydCwgcmVwbGFjZW1lbnRMZW5ndGgpOwoJCQkJbm9DaGFuZ2VFdmVudC5yZWFzb24gPSBOb0NoYW5nZUV2ZW50Lk5PX0VWRU5UOwoJCQkJZmlyZVN0cnVjdHVyZWREb2N1bWVudEV2ZW50KG5vQ2hhbmdlRXZlbnQpOwoJCQkJTG9nZ2VyLmxvZyhMb2dnZXIuRVJST1IsICJQcm9ncmFtIEVycm9yOiBpbnZhbGlkIHN0cnVjdHVyZWQgZG9jdW1lbnQgZXZlbnQiKTsgLy8kTk9OLU5MUy0xJAoJCQl9CgkJCWVsc2UgewoJCQkJaWYgKHJlc3VsdCBpbnN0YW5jZW9mIFJlZ2lvbkNoYW5nZWRFdmVudCkgewoJCQkJCWZpcmVTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudCgoUmVnaW9uQ2hhbmdlZEV2ZW50KSByZXN1bHQpOwoJCQkJfQoJCQkJZWxzZSB7CgkJCQkJaWYgKHJlc3VsdCBpbnN0YW5jZW9mIFJlZ2lvbnNSZXBsYWNlZEV2ZW50KSB7CgkJCQkJCWZpcmVTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudCgoUmVnaW9uc1JlcGxhY2VkRXZlbnQpIHJlc3VsdCk7CgkJCQkJfQoJCQkJCWVsc2UgewoJCQkJCQlpZiAocmVzdWx0IGluc3RhbmNlb2YgU3RydWN0dXJlZERvY3VtZW50UmVnaW9uc1JlcGxhY2VkRXZlbnQpIHsKCQkJCQkJCS8vIHByb2JhYmx5IG1vcmUgZWZmaWNpZW50IHRvIG1hcmsgb2xkIHJlZ2lvbnMgYXMKCQkJCQkJCS8vICdkZWxldGVkJyBhdCB0aGUgdGltZQoJCQkJCQkJLy8gdGhhdCBhcmUgZGV0ZXJtaW5lZCB0byBiZSBkZWxldGVkLCBidXQgSSdsbCBkbwoJCQkJCQkJLy8gaGVyZQoJCQkJCQkJLy8gaW4gdGhlbiBjZW50cmFsIHNwb3QKCQkJCQkJCS8vIGZvciBwcm9ncmFtbWluZyBlYXNlLgoJCQkJCQkJdXBkYXRlRGVsZXRlZEZpZWxkcygoU3RydWN0dXJlZERvY3VtZW50UmVnaW9uc1JlcGxhY2VkRXZlbnQpIHJlc3VsdCk7CgkJCQkJCQlmaXJlU3RydWN0dXJlZERvY3VtZW50RXZlbnQoKFN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbnNSZXBsYWNlZEV2ZW50KSByZXN1bHQpOwoJCQkJCQl9CgkJCQkJCWVsc2UgewoJCQkJCQkJaWYgKHJlc3VsdCBpbnN0YW5jZW9mIE5vQ2hhbmdlRXZlbnQpIHsKCQkJCQkJCQlmaXJlU3RydWN0dXJlZERvY3VtZW50RXZlbnQoKE5vQ2hhbmdlRXZlbnQpIHJlc3VsdCk7CgkJCQkJCQl9CgkJCQkJCQllbHNlIHsKCQkJCQkJCQkvLyBpZiBoZXJlLCB0aGlzIG1lYW5zIGEgbmV3IGV2ZW50IHdhcyBjcmVhdGVkCgkJCQkJCQkJLy8gYW5kIG5vdCBoYW5kbGVkIGhlcmUKCQkJCQkJCQkvLyBqdXN0IHNlbmQgYSBubyBldmVudCB1bnRpbCB0aGlzIGlzc3VlIGlzCgkJCQkJCQkJLy8gcmVzb2x2ZWQuCgkJCQkJCQkJTm9DaGFuZ2VFdmVudCBub0NoYW5nZUV2ZW50ID0gbmV3IE5vQ2hhbmdlRXZlbnQodGhpcywgcmVxdWVzdGVyLCBjaGFuZ2VzLCBzdGFydCwgcmVwbGFjZW1lbnRMZW5ndGgpOwoJCQkJCQkJCW5vQ2hhbmdlRXZlbnQucmVhc29uID0gTm9DaGFuZ2VFdmVudC5OT19FVkVOVDsKCQkJCQkJCQlmaXJlU3RydWN0dXJlZERvY3VtZW50RXZlbnQobm9DaGFuZ2VFdmVudCk7CgkJCQkJCQkJTG9nZ2VyLmxvZyhMb2dnZXIuSU5GTywgIlByb2dyYW0gRXJyb3I6IHVuZXhwZWN0ZWQgc3RydWN0dXJlZCBkb2N1bWVudCBldmVudDogIiArIHJlc3VsdCk7IC8vJE5PTi1OTFMtMSQKCQkJCQkJCX0KCQkJCQkJfQoJCQkJCX0KCQkJCX0KCQkJfQoJCQlpZiAoRGVidWcucGVyZlRlc3QgfHwgRGVidWcucGVyZlRlc3RTdHJ1Y3R1cmVkRG9jdW1lbnRPbmx5KSB7CgkJCQlsb25nIHN0b3BTdHJlYW1UaW1lID0gU3lzdGVtLmN1cnJlbnRUaW1lTWlsbGlzKCk7CgkJCQlTeXN0ZW0ub3V0LnByaW50bG4oIlxuXHRcdFx0XHQgVG90YWwgVGltZSBmb3IgSVN0cnVjdHVyZWREb2N1bWVudCBldmVudCBzaWduYWxpbmcvcHJvY2Vzc2luZyBpbiByZXBsYWNlVGV4dDogIiArIChzdG9wU3RyZWFtVGltZSAtIHN0YXJ0U3RyZWFtVGltZSkpOyAvLyROT04tTkxTLTEkCgkJCX0KCQkJcmVzdW1lUG9zdE5vdGlmaWNhdGlvblByb2Nlc3NpbmcoKTsKCQl9CgkJcmV0dXJuIHJlc3VsdDsKCX0KCgkvKgoJICogKG5vbi1KYXZhZG9jKQoJICogCgkgKiBAc2VlIGphdmEubGFuZy5DaGFyU2VxdWVuY2UjbGVuZ3RoKCkKCSAqLwoJcHVibGljIGludCBsZW5ndGgoKSB7CgoJCXJldHVybiBnZXRMZW5ndGgoKTsKCX0KCQoJcHVibGljIHZvaWQgbWFrZVJlYWRPbmx5KGludCBzdGFydE9mZnNldCwgaW50IGxlbmd0aCkgewoJCW1ha2VSZWFkT25seShzdGFydE9mZnNldCwgbGVuZ3RoLCBmYWxzZSwgZmFsc2UpOwoJfQoKCXB1YmxpYyB2b2lkIG1ha2VSZWFkT25seShpbnQgc3RhcnRPZmZzZXQsIGludCBsZW5ndGgsIGJvb2xlYW4gY2FuSW5zZXJ0QmVmb3JlLCBib29sZWFuIGNhbkluc2VydEFmdGVyKSB7CQoJCS8vIGRvZXNuJ3QgbWFrZSBzZW5zZSB0byBoYXZlIGEgcmVhZG9ubHkgcmVnaW9uIG9mIDAgbGVuZ3RoLAoJCS8vIHNvIHdlJ2xsIGlnbm9yZSB0aG9zZSByZXF1ZXN0cwoJCWlmIChsZW5ndGggPD0gMCkKCQkJcmV0dXJuOwoJCVN0cmluZyBhZmZlY3RlZFRleHQgPSB0aGlzLmdldChzdGFydE9mZnNldCwgbGVuZ3RoKTsKCQkvLyBhIGRvY3VtZW50IGV2ZW50IGZvciAicmVhZCBvbmx5IiBjaGFuZ2UgLi4uIG11c3QKCQkvLyBiZSBmb2xsb3dlZCBieSAibm8gY2hhbmdlIiBzdHJ1Y3R1cmVkRG9jdW1lbnQgZXZlbnQKCQkvLyBmRG9jdW1lbnRFdmVudCA9IG5ldyBEb2N1bWVudEV2ZW50KHRoaXMsIHN0YXJ0T2Zmc2V0LCBsZW5ndGgsCgkJLy8gYWZmZWN0ZWRUZXh0KTsKCQlmaXJlUmVhZE9ubHlBYm91dFRvQmVDaGFuZ2VkKCk7CgkJLy8gaWYgKGNvbnRhaW5zUmVhZE9ubHkoc3RhcnRPZmZzZXQsIGxlbmd0aCkpIHsKCQkvLyBhZGp1c3RSZWFkT25seVJlZ2lvbnMoc3RhcnRPZmZzZXQsIGxlbmd0aCk7CgkJLy8gfSBlbHNlIHsKCQkvLyB3ZSBjYW4gYmxpbmRseSBhZGQgY2F0ZWdvcnksIHNpbmNlIG5vIGhhcm0gZG9uZSBpZiBhbHJlYWR5CgkJLy8gZXhpc3RzLgoJCWFkZFBvc2l0aW9uQ2F0ZWdvcnkoUkVBRF9PTkxZX1JFR0lPTlNfQ0FURUdPUlkpOwoJCVBvc2l0aW9uIG5ld1Bvc2l0aW9uID0gbmV3IFJlYWRPbmx5UG9zaXRpb24oc3RhcnRPZmZzZXQsIGxlbmd0aCwgY2FuSW5zZXJ0QmVmb3JlKTsKCQl0cnkgewoJCQlhZGRQb3NpdGlvbihSRUFEX09OTFlfUkVHSU9OU19DQVRFR09SWSwgbmV3UG9zaXRpb24pOwoJCQkvLyBGSVhNRTogbmVlZCB0byBjaGFuZ2UgQVBJIHRvIHBhc3MgaW4gcmVxdWVzdGVyLCBzbyB0aGlzIGV2ZW50CgkJCS8vIGNhbiBiZQoJCQkvLyBjcmVhdGVkIGNvcnJlY3RseSwgaW5zdGVhZCBvZiB1c2luZyBudWxsLgoJCQlOb0NoYW5nZUV2ZW50IG5vQ2hhbmdlRXZlbnQgPSBuZXcgTm9DaGFuZ2VFdmVudCh0aGlzLCBudWxsLCBhZmZlY3RlZFRleHQsIHN0YXJ0T2Zmc2V0LCBsZW5ndGgpOwoJCQlub0NoYW5nZUV2ZW50LnJlYXNvbiA9IE5vQ2hhbmdlRXZlbnQuUkVBRF9PTkxZX1NUQVRFX0NIQU5HRTsKCQkJZmlyZVJlYWRPbmx5U3RydWN0dXJlZERvY3VtZW50RXZlbnQobm9DaGFuZ2VFdmVudCk7CgkJfQoJCWNhdGNoIChCYWRMb2NhdGlvbkV4Y2VwdGlvbiBlKSB7CgkJCS8vIGZvciBub3csIGxvZyBhbmQgaWdub3JlLiBQZXJoYXBzIGxhdGVyIHdlCgkJCS8vIGNvdWxkIGFkanVzdCB0byBoYW5kbGUgc29tZSBjYXNlcz8KCQkJTG9nZ2VyLmxvZ0V4Y2VwdGlvbigoImNvdWxkIG5vdCBjcmVhdGUgcmVhZG9ubHkgcmVnaW9uIGF0ICIgKyBzdGFydE9mZnNldCArICIgdG8gIiArIGxlbmd0aCksIGUpOyAvLyROT04tTkxTLTEkIC8vJE5PTi1OTFMtMiQKCQl9CgkJY2F0Y2ggKEJhZFBvc2l0aW9uQ2F0ZWdvcnlFeGNlcHRpb24gZSkgewoJCQkvLyBzaG91bGQgbmV2ZXIgb2NjdXIsIHNpbmNlIHdlIGFkZCBjYXRlZ29yeQoJCQlMb2dnZXIubG9nRXhjZXB0aW9uKGUpOwoJCX0KCX0KCglwdWJsaWMgSVN0cnVjdHVyZWREb2N1bWVudCBuZXdJbnN0YW5jZSgpIHsKCQlJU3RydWN0dXJlZERvY3VtZW50IG5ld0luc3RhbmNlID0gU3RydWN0dXJlZERvY3VtZW50RmFjdG9yeS5nZXROZXdTdHJ1Y3R1cmVkRG9jdW1lbnRJbnN0YW5jZShnZXRQYXJzZXIoKS5uZXdJbnN0YW5jZSgpKTsKCQkoKEJhc2ljU3RydWN0dXJlZERvY3VtZW50KSBuZXdJbnN0YW5jZSkuc2V0UmVQYXJzZXIoZ2V0UmVQYXJzZXIoKS5uZXdJbnN0YW5jZSgpKTsKCQlpZiAoZ2V0RG9jdW1lbnRQYXJ0aXRpb25lcigpIGluc3RhbmNlb2YgU3RydWN0dXJlZFRleHRQYXJ0aXRpb25lcikgewoJCQluZXdJbnN0YW5jZS5zZXREb2N1bWVudFBhcnRpdGlvbmVyKCgoU3RydWN0dXJlZFRleHRQYXJ0aXRpb25lcikgZ2V0RG9jdW1lbnRQYXJ0aXRpb25lcigpKS5uZXdJbnN0YW5jZSgpKTsKCQkJbmV3SW5zdGFuY2UuZ2V0RG9jdW1lbnRQYXJ0aXRpb25lcigpLmNvbm5lY3QobmV3SW5zdGFuY2UpOwoJCX0KCQluZXdJbnN0YW5jZS5zZXRMaW5lRGVsaW1pdGVyKGdldExpbmVEZWxpbWl0ZXIoKSk7CgkJaWYgKGdldEVuY29kaW5nTWVtZW50bygpICE9IG51bGwpIHsKCQkJbmV3SW5zdGFuY2Uuc2V0RW5jb2RpbmdNZW1lbnRvKChFbmNvZGluZ01lbWVudG8pIGdldEVuY29kaW5nTWVtZW50bygpLmNsb25lKCkpOwoJCX0KCQlyZXR1cm4gbmV3SW5zdGFuY2U7Cgl9CgoJLyoKCSAqIChub24tSmF2YWRvYykKCSAqIAoJICogQHNlZSBvcmcuZWNsaXBzZS53c3Quc3NlLmNvcmUuaW50ZXJuYWwudGV4dC5JUmVnaW9uQ29tcGFyaWJsZSNyZWdpb25NYXRjaGVzKGludCwKCSAqICAgICAgaW50LCBqYXZhLmxhbmcuU3RyaW5nKQoJICovCglwdWJsaWMgYm9vbGVhbiByZWdpb25NYXRjaGVzKGludCBvZmZzZXQsIGludCBsZW5ndGgsIFN0cmluZyBzdHJpbmdUb0NvbXBhcmUpIHsKCQlib29sZWFuIHJlc3VsdCA9IGZhbHNlOwoJCUlUZXh0U3RvcmUgc3RvcmUgPSBnZXRTdG9yZSgpOwoJCWlmIChzdG9yZSBpbnN0YW5jZW9mIElSZWdpb25Db21wYXJpYmxlKSB7CgkJCXJlc3VsdCA9ICgoSVJlZ2lvbkNvbXBhcmlibGUpIHN0b3JlKS5yZWdpb25NYXRjaGVzKG9mZnNldCwgbGVuZ3RoLCBzdHJpbmdUb0NvbXBhcmUpOwoJCX0KCQllbHNlIHsKCQkJcmVzdWx0ID0gZ2V0KG9mZnNldCwgbGVuZ3RoKS5lcXVhbHMoc3RyaW5nVG9Db21wYXJlKTsKCQl9CgkJcmV0dXJuIHJlc3VsdDsKCX0KCglwdWJsaWMgYm9vbGVhbiByZWdpb25NYXRjaGVzSWdub3JlQ2FzZShpbnQgb2Zmc2V0LCBpbnQgbGVuZ3RoLCBTdHJpbmcgc3RyaW5nVG9Db21wYXJlKSB7CgkJYm9vbGVhbiByZXN1bHQgPSBmYWxzZTsKCQlJVGV4dFN0b3JlIHN0b3JlID0gZ2V0U3RvcmUoKTsKCQlpZiAoc3RvcmUgaW5zdGFuY2VvZiBJUmVnaW9uQ29tcGFyaWJsZSkgewoJCQlyZXN1bHQgPSAoKElSZWdpb25Db21wYXJpYmxlKSBzdG9yZSkucmVnaW9uTWF0Y2hlc0lnbm9yZUNhc2Uob2Zmc2V0LCBsZW5ndGgsIHN0cmluZ1RvQ29tcGFyZSk7CgkJfQoJCWVsc2UgewoJCQlyZXN1bHQgPSBnZXQob2Zmc2V0LCBsZW5ndGgpLmVxdWFsc0lnbm9yZUNhc2Uoc3RyaW5nVG9Db21wYXJlKTsKCQl9CgkJcmV0dXJuIHJlc3VsdDsKCX0KCgkvKgoJICogKG5vbi1KYXZhZG9jKQoJICogCgkgKiBAc2VlIG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSURvY3VtZW50RXh0ZW5zaW9uI3JlZ2lzdGVyUG9zdE5vdGlmaWNhdGlvblJlcGxhY2Uob3JnLmVjbGlwc2UuamZhY2UudGV4dC5JRG9jdW1lbnRMaXN0ZW5lciwKCSAqICAgICAgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5JRG9jdW1lbnRFeHRlbnNpb24uSVJlcGxhY2UpCgkgKi8KCXB1YmxpYyB2b2lkIHJlZ2lzdGVyUG9zdE5vdGlmaWNhdGlvblJlcGxhY2UoSURvY3VtZW50TGlzdGVuZXIgb3duZXIsIElEb2N1bWVudEV4dGVuc2lvbi5JUmVwbGFjZSByZXBsYWNlKSB7CgkJaWYgKGZBY2NlcHRQb3N0Tm90aWZpY2F0aW9uUmVwbGFjZXMpIHsKCQkJaWYgKGZQb3N0Tm90aWZpY2F0aW9uQ2hhbmdlcyA9PSBudWxsKQoJCQkJZlBvc3ROb3RpZmljYXRpb25DaGFuZ2VzID0gbmV3IEFycmF5TGlzdCgxKTsKCQkJZlBvc3ROb3RpZmljYXRpb25DaGFuZ2VzLmFkZChuZXcgUmVnaXN0ZXJlZFJlcGxhY2Uob3duZXIsIHJlcGxhY2UpKTsKCQl9Cgl9CgoJcHJvdGVjdGVkIHZvaWQgcmVsZWFzZUxvY2soKSB7CgkJLy8gZG8gbm90aGluZyBoZXJlIGluIHN1cGVyIGNsYXNzCgl9CgoJcHVibGljIHZvaWQgcmVtb3ZlRG9jdW1lbnRBYm91dFRvQ2hhbmdlTGlzdGVuZXIoSU1vZGVsQWJvdXRUb0JlQ2hhbmdlZExpc3RlbmVyIGxpc3RlbmVyKSB7CgkJc3luY2hyb25pemVkIChsaXN0ZW5lckxvY2spIHsKCgkJCWlmICgoZlN0cnVjdHVyZWREb2N1bWVudEFib3V0VG9DaGFuZ2VMaXN0ZW5lcnMgIT0gbnVsbCkgJiYgKGxpc3RlbmVyICE9IG51bGwpKSB7CgkJCQkvLyBpZiBpdHMgbm90IGluIHRoZSBsaXN0ZW5lcnMsIHdlJ2xsIGlnbm9yZSB0aGUgcmVxdWVzdAoJCQkJaWYgKFV0aWxpdGllcy5jb250YWlucyhmU3RydWN0dXJlZERvY3VtZW50QWJvdXRUb0NoYW5nZUxpc3RlbmVycywgbGlzdGVuZXIpKSB7CgkJCQkJaW50IG9sZFNpemUgPSBmU3RydWN0dXJlZERvY3VtZW50QWJvdXRUb0NoYW5nZUxpc3RlbmVycy5sZW5ndGg7CgkJCQkJaW50IG5ld1NpemUgPSBvbGRTaXplIC0gMTsKCQkJCQlPYmplY3RbXSBuZXdMaXN0ZW5lcnMgPSBuZXcgT2JqZWN0W25ld1NpemVdOwoJCQkJCWludCBpbmRleCA9IDA7CgkJCQkJZm9yIChpbnQgaSA9IDA7IGkgPCBvbGRTaXplOyBpKyspIHsKCQkJCQkJaWYgKGZTdHJ1Y3R1cmVkRG9jdW1lbnRBYm91dFRvQ2hhbmdlTGlzdGVuZXJzW2ldID09IGxpc3RlbmVyKSB7IC8vIGlnbm9yZQoJCQkJCQl9CgkJCQkJCWVsc2UgewoJCQkJCQkJLy8gY29weSBvbGQgdG8gbmV3IGlmIGl0cyBub3QgdGhlIG9uZSB3ZSBhcmUKCQkJCQkJCS8vIHJlbW92aW5nCgkJCQkJCQluZXdMaXN0ZW5lcnNbaW5kZXgrK10gPSBmU3RydWN0dXJlZERvY3VtZW50QWJvdXRUb0NoYW5nZUxpc3RlbmVyc1tpXTsKCQkJCQkJfQoJCQkJCX0KCQkJCQkvLyBub3cgdGhhdCB3ZSBoYXZlIGEgbmV3IGFycmF5LCBsZXQncyBzd2l0Y2ggaXQgZm9yIHRoZQoJCQkJCS8vIG9sZAoJCQkJCS8vIG9uZQoJCQkJCWZTdHJ1Y3R1cmVkRG9jdW1lbnRBYm91dFRvQ2hhbmdlTGlzdGVuZXJzID0gbmV3TGlzdGVuZXJzOwoJCQkJfQoJCQl9CgkJfQoJfQoKCS8qKgoJICogcmVtb3ZlTW9kZWxDaGFuZ2VkTGlzdGVuZXIgbWV0aG9kIGNvbW1lbnQuCgkgKi8KCXB1YmxpYyB2b2lkIHJlbW92ZURvY3VtZW50Q2hhbmdlZExpc3RlbmVyKElTdHJ1Y3R1cmVkRG9jdW1lbnRMaXN0ZW5lciBsaXN0ZW5lcikgewoJCXN5bmNocm9uaXplZCAobGlzdGVuZXJMb2NrKSB7CgoJCQlpZiAoKGZTdHJ1Y3R1cmVkRG9jdW1lbnRDaGFuZ2VkTGlzdGVuZXJzICE9IG51bGwpICYmIChsaXN0ZW5lciAhPSBudWxsKSkgewoJCQkJLy8gaWYgaXRzIG5vdCBpbiB0aGUgbGlzdGVuZXJzLCB3ZSdsbCBpZ25vcmUgdGhlIHJlcXVlc3QKCQkJCWlmIChVdGlsaXRpZXMuY29udGFpbnMoZlN0cnVjdHVyZWREb2N1bWVudENoYW5nZWRMaXN0ZW5lcnMsIGxpc3RlbmVyKSkgewoJCQkJCWludCBvbGRTaXplID0gZlN0cnVjdHVyZWREb2N1bWVudENoYW5nZWRMaXN0ZW5lcnMubGVuZ3RoOwoJCQkJCWludCBuZXdTaXplID0gb2xkU2l6ZSAtIDE7CgkJCQkJT2JqZWN0W10gbmV3TGlzdGVuZXJzID0gbmV3IE9iamVjdFtuZXdTaXplXTsKCQkJCQlpbnQgaW5kZXggPSAwOwoJCQkJCWZvciAoaW50IGkgPSAwOyBpIDwgb2xkU2l6ZTsgaSsrKSB7CgkJCQkJCWlmIChmU3RydWN0dXJlZERvY3VtZW50Q2hhbmdlZExpc3RlbmVyc1tpXSA9PSBsaXN0ZW5lcikgeyAvLyBpZ25vcmUKCQkJCQkJfQoJCQkJCQllbHNlIHsKCQkJCQkJCS8vIGNvcHkgb2xkIHRvIG5ldyBpZiBpdHMgbm90IHRoZSBvbmUgd2UgYXJlCgkJCQkJCQkvLyByZW1vdmluZwoJCQkJCQkJbmV3TGlzdGVuZXJzW2luZGV4KytdID0gZlN0cnVjdHVyZWREb2N1bWVudENoYW5nZWRMaXN0ZW5lcnNbaV07CgkJCQkJCX0KCQkJCQl9CgkJCQkJLy8gbm93IHRoYXQgd2UgaGF2ZSBhIG5ldyBhcnJheSwgbGV0J3Mgc3dpdGNoIGl0IGZvciB0aGUKCQkJCQkvLyBvbGQKCQkJCQkvLyBvbmUKCQkJCQlmU3RydWN0dXJlZERvY3VtZW50Q2hhbmdlZExpc3RlbmVycyA9IG5ld0xpc3RlbmVyczsKCQkJCX0KCQkJfQoJCX0KCX0KCglwdWJsaWMgdm9pZCByZW1vdmVEb2N1bWVudENoYW5naW5nTGlzdGVuZXIoSVN0cnVjdHVyZWREb2N1bWVudExpc3RlbmVyIGxpc3RlbmVyKSB7CgkJc3luY2hyb25pemVkIChsaXN0ZW5lckxvY2spIHsKCgkJCWlmICgoZlN0cnVjdHVyZWREb2N1bWVudENoYW5naW5nTGlzdGVuZXJzICE9IG51bGwpICYmIChsaXN0ZW5lciAhPSBudWxsKSkgewoJCQkJLy8gaWYgaXRzIG5vdCBpbiB0aGUgbGlzdGVuZXJzLCB3ZSdsbCBpZ25vcmUgdGhlIHJlcXVlc3QKCQkJCWlmIChVdGlsaXRpZXMuY29udGFpbnMoZlN0cnVjdHVyZWREb2N1bWVudENoYW5naW5nTGlzdGVuZXJzLCBsaXN0ZW5lcikpIHsKCQkJCQlpbnQgb2xkU2l6ZSA9IGZTdHJ1Y3R1cmVkRG9jdW1lbnRDaGFuZ2luZ0xpc3RlbmVycy5sZW5ndGg7CgkJCQkJaW50IG5ld1NpemUgPSBvbGRTaXplIC0gMTsKCQkJCQlPYmplY3RbXSBuZXdMaXN0ZW5lcnMgPSBuZXcgT2JqZWN0W25ld1NpemVdOwoJCQkJCWludCBpbmRleCA9IDA7CgkJCQkJZm9yIChpbnQgaSA9IDA7IGkgPCBvbGRTaXplOyBpKyspIHsKCQkJCQkJaWYgKGZTdHJ1Y3R1cmVkRG9jdW1lbnRDaGFuZ2luZ0xpc3RlbmVyc1tpXSA9PSBsaXN0ZW5lcikgeyAvLyBpZ25vcmUKCQkJCQkJfQoJCQkJCQllbHNlIHsKCQkJCQkJCS8vIGNvcHkgb2xkIHRvIG5ldyBpZiBpdHMgbm90IHRoZSBvbmUgd2UgYXJlCgkJCQkJCQkvLyByZW1vdmluZwoJCQkJCQkJbmV3TGlzdGVuZXJzW2luZGV4KytdID0gZlN0cnVjdHVyZWREb2N1bWVudENoYW5naW5nTGlzdGVuZXJzW2ldOwoJCQkJCQl9CgkJCQkJfQoJCQkJCS8vIG5vdyB0aGF0IHdlIGhhdmUgYSBuZXcgYXJyYXksIGxldCdzIHN3aXRjaCBpdCBmb3IgdGhlCgkJCQkJLy8gb2xkCgkJCQkJLy8gb25lCgkJCQkJZlN0cnVjdHVyZWREb2N1bWVudENoYW5naW5nTGlzdGVuZXJzID0gbmV3TGlzdGVuZXJzOwoJCQkJfQoJCQl9CgkJfQoJfQoKCXB1YmxpYyB2b2lkIHJlbW92ZURvY3VtZW50TGlzdGVuZXIoSURvY3VtZW50TGlzdGVuZXIgbGlzdGVuZXIpIHsKCQlzeW5jaHJvbml6ZWQgKGxpc3RlbmVyTG9jaykgewoKCQkJaWYgKChmRG9jdW1lbnRMaXN0ZW5lcnMgIT0gbnVsbCkgJiYgKGxpc3RlbmVyICE9IG51bGwpKSB7CgkJCQkvLyBpZiBpdHMgbm90IGluIHRoZSBsaXN0ZW5lcnMsIHdlJ2xsIGlnbm9yZSB0aGUgcmVxdWVzdAoJCQkJaWYgKFV0aWxpdGllcy5jb250YWlucyhmRG9jdW1lbnRMaXN0ZW5lcnMsIGxpc3RlbmVyKSkgewoJCQkJCWludCBvbGRTaXplID0gZkRvY3VtZW50TGlzdGVuZXJzLmxlbmd0aDsKCQkJCQlpbnQgbmV3U2l6ZSA9IG9sZFNpemUgLSAxOwoJCQkJCUlEb2N1bWVudExpc3RlbmVyW10gbmV3TGlzdGVuZXJzID0gbmV3IElEb2N1bWVudExpc3RlbmVyW25ld1NpemVdOwoJCQkJCWludCBpbmRleCA9IDA7CgkJCQkJZm9yIChpbnQgaSA9IDA7IGkgPCBvbGRTaXplOyBpKyspIHsKCQkJCQkJaWYgKGZEb2N1bWVudExpc3RlbmVyc1tpXSA9PSBsaXN0ZW5lcikgeyAvLyBpZ25vcmUKCQkJCQkJfQoJCQkJCQllbHNlIHsKCQkJCQkJCS8vIGNvcHkgb2xkIHRvIG5ldyBpZiBpdHMgbm90IHRoZSBvbmUgd2UgYXJlCgkJCQkJCQkvLyByZW1vdmluZwoJCQkJCQkJbmV3TGlzdGVuZXJzW2luZGV4KytdID0gZkRvY3VtZW50TGlzdGVuZXJzW2ldOwoJCQkJCQl9CgkJCQkJfQoJCQkJCS8vIG5vdyB0aGF0IHdlIGhhdmUgYSBuZXcgYXJyYXksIGxldCdzIHN3aXRjaCBpdCBmb3IgdGhlCgkJCQkJLy8gb2xkCgkJCQkJLy8gb25lCgkJCQkJZkRvY3VtZW50TGlzdGVuZXJzID0gbmV3TGlzdGVuZXJzOwoJCQkJfQoJCQl9CgkJfQoJfQoKCS8qCgkgKiBAc2VlIG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSURvY3VtZW50I3JlbW92ZURvY3VtZW50UGFydGl0aW9uaW5nTGlzdGVuZXIob3JnLmVjbGlwc2UuamZhY2UudGV4dC5JRG9jdW1lbnRQYXJ0aXRpb25pbmdMaXN0ZW5lcikKCSAqLwoJcHVibGljIHZvaWQgcmVtb3ZlRG9jdW1lbnRQYXJ0aXRpb25pbmdMaXN0ZW5lcihJRG9jdW1lbnRQYXJ0aXRpb25pbmdMaXN0ZW5lciBsaXN0ZW5lcikgewoJCXN5bmNocm9uaXplZCAobGlzdGVuZXJMb2NrKSB7CgoJCQlBc3NlcnQuaXNOb3ROdWxsKGxpc3RlbmVyKTsKCQkJaWYgKGZEb2N1bWVudFBhcnRpdGlvbmluZ0xpc3RlbmVycyAhPSBudWxsKQoJCQkJZkRvY3VtZW50UGFydGl0aW9uaW5nTGlzdGVuZXJzLnJlbW92ZShsaXN0ZW5lcik7CgkJfQoJfQoKCS8qKgoJICogUmVtb3ZlcyB0aGUgZ2l2ZW4gPGNvZGU+UG9zaXRpb248L2NvZGU+IGZyb20gdGhlIGRvY3VtZW50J3MgZGVmYXVsdAoJICogcG9zaXRpb24gY2F0ZWdvcnkuIFRoZSBkZWZhdWx0IHBvc2l0aW9uIGNhdGVnb3J5IGlzIHRvIGJlIGRlZmluZWQgYnkKCSAqIHRoZSBpbXBsZW1lbnRlcnMuIElmIHRoZSBwb3NpdGlvbiBpcyBub3QgcGFydCBvZiB0aGUgZG9jdW1lbnQncyBkZWZhdWx0CgkgKiBjYXRlZ29yeSBub3RoaW5nIGhhcHBlbnMuCgkgKi8KCXB1YmxpYyB2b2lkIHJlbW92ZVBvc2l0aW9uKFBvc2l0aW9uIHBvc2l0aW9uKSB7CgkJZ2V0UG9zaXRpb25NYW5hZ2VyKCkucmVtb3ZlUG9zaXRpb24ocG9zaXRpb24pOwoJfQoKCS8qKgoJICogQHNlZSBJRG9jdW1lbnQjcmVtb3ZlUG9zaXRpb24KCSAqIEBleGNlcHRpb24gQmFkUG9zaXRpb25DYXRlZ29yeUV4Y2VwdGlvbgoJICogICAgICAgICAgICAgICAgSWYgdGhlIGNhdGVnb3J5IGlzIG5vdCBkZWZpbmVkIGZvciB0aGUgZG9jdW1lbnQKCSAqLwoJcHVibGljIHZvaWQgcmVtb3ZlUG9zaXRpb24oU3RyaW5nIGNhdGVnb3J5LCBQb3NpdGlvbiBwb3NpdGlvbikgdGhyb3dzIEJhZFBvc2l0aW9uQ2F0ZWdvcnlFeGNlcHRpb24gewoJCWdldFBvc2l0aW9uTWFuYWdlcigpLnJlbW92ZVBvc2l0aW9uKGNhdGVnb3J5LCBwb3NpdGlvbik7Cgl9CgoJLyoqCgkgKiBAc2VlIElEb2N1bWVudCNyZW1vdmVQb3NpdGlvbkNhdGVnb3J5CgkgKiBAZXhjZXB0aW9uIEJhZFBvc2l0aW9uQ2F0ZWdvcnlFeGNlcHRpb24KCSAqICAgICAgICAgICAgICAgIElmIHRoZSBjYXRlZ29yeSBpcyBub3QgZGVmaW5lZCBmb3IgdGhlIGRvY3VtZW50CgkgKi8KCXB1YmxpYyB2b2lkIHJlbW92ZVBvc2l0aW9uQ2F0ZWdvcnkoU3RyaW5nIGNhdGVnb3J5KSB0aHJvd3MgQmFkUG9zaXRpb25DYXRlZ29yeUV4Y2VwdGlvbiB7CgkJZ2V0UG9zaXRpb25NYW5hZ2VyKCkucmVtb3ZlUG9zaXRpb25DYXRlZ29yeShjYXRlZ29yeSk7Cgl9CgoJLyoqCgkgKiBAc2VlIElEb2N1bWVudCNyZW1vdmVQb3NpdGlvblVwZGF0ZXIKCSAqLwoJcHVibGljIHZvaWQgcmVtb3ZlUG9zaXRpb25VcGRhdGVyKElQb3NpdGlvblVwZGF0ZXIgdXBkYXRlcikgewoJCWdldFBvc2l0aW9uTWFuYWdlcigpLnJlbW92ZVBvc2l0aW9uVXBkYXRlcih1cGRhdGVyKTsKCX0KCgkvKioKCSAqIFJlbW92ZXMgdGhlIGdpdmVuIGRvY3VtZW50IGxpc3RlbmVyIGZyb20gdGVoIGRvY3VtZW50J3MgbGlzdCBvZgoJICogcHJlbm90aWZpZWQgZG9jdW1lbnQgbGlzdGVuZXJzLiBJZiB0aGUgbGlzdGVuZXIgaXMgbm90IHJlZ2lzdGVyZWQgd2l0aAoJICogdGhlIGRvY3VtZW50IG5vdGhpbmcgaGFwcGVucy4KCSAqIDxwPgoJICogCgkgKiBUaGlzIG1ldGhvZCBpcyBub3QgZm9yIHB1YmxpYyB1c2UsIGl0IG1heSBvbmx5IGJlIGNhbGxlZCBieQoJICogaW1wbGVtZW50ZXJzIG9mIDxjb2RlPklEb2N1bWVudEFkYXB0ZXI8L2NvZGU+IGFuZCBvbmx5IGlmIHRob3NlCgkgKiBpbXBsZW1lbnRlcnMgbmVlZCB0byBpbXBsZW1lbnQgPGNvZGU+SURvY3VtZW50TGlzdGVuZXI8L2NvZGU+LgoJICogCgkgKiBAcGFyYW0gZG9jdW1lbnRBZGFwdGVyCgkgKiAgICAgICAgICAgIHRoZSBsaXN0ZW5lciB0byBiZSByZW1vdmVkCgkgKiAKCSAqIEBzZWUgI2FkZFByZW5vdGlmaWVkRG9jdW1lbnRMaXN0ZW5lcihJRG9jdW1lbnRMaXN0ZW5lcikKCSAqLwoJcHVibGljIHZvaWQgcmVtb3ZlUHJlbm90aWZpZWREb2N1bWVudExpc3RlbmVyKG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSURvY3VtZW50TGlzdGVuZXIgZG9jdW1lbnRBZGFwdGVyKSB7CgkJc3luY2hyb25pemVkIChsaXN0ZW5lckxvY2spIHsKCgkJCWlmIChVdGlsaXRpZXMuY29udGFpbnMoZlByZW5vdGlmaWVkRG9jdW1lbnRMaXN0ZW5lcnMsIGRvY3VtZW50QWRhcHRlcikpIHsKCQkJCWludCBwcmV2aW91c1NpemUgPSBmUHJlbm90aWZpZWREb2N1bWVudExpc3RlbmVycy5sZW5ndGg7CgkJCQlpZiAocHJldmlvdXNTaXplID4gMSkgewoJCQkJCUlEb2N1bWVudExpc3RlbmVyW10gbGlzdGVuZXJzID0gbmV3IElEb2N1bWVudExpc3RlbmVyW3ByZXZpb3VzU2l6ZSAtIDFdOwoJCQkJCWludCBwcmV2aW91c0luZGV4ID0gMDsKCQkJCQlpbnQgbmV3SW5kZXggPSAwOwoJCQkJCXdoaWxlIChwcmV2aW91c0luZGV4IDwgcHJldmlvdXNTaXplKSB7CgkJCQkJCWlmIChmUHJlbm90aWZpZWREb2N1bWVudExpc3RlbmVyc1twcmV2aW91c0luZGV4XSAhPSBkb2N1bWVudEFkYXB0ZXIpCgkJCQkJCQlsaXN0ZW5lcnNbbmV3SW5kZXgrK10gPSBmUHJlbm90aWZpZWREb2N1bWVudExpc3RlbmVyc1twcmV2aW91c0luZGV4XTsKCQkJCQkJcHJldmlvdXNJbmRleCsrOwoJCQkJCX0KCQkJCQlmUHJlbm90aWZpZWREb2N1bWVudExpc3RlbmVycyA9IGxpc3RlbmVyczsKCQkJCX0KCQkJCWVsc2UgewoJCQkJCWZQcmVub3RpZmllZERvY3VtZW50TGlzdGVuZXJzID0gbnVsbDsKCQkJCX0KCQkJfQoJCX0KCX0KCgkvKioKCSAqIFRoaXMgbWV0aG9kIGlzIGZvciBJTlRFUk5BTCBVU0UgT05MWSBhbmQgaXMgTk9UIEFQSS4KCSAqIAoJICogUmVidWlsZHMgdGhlIFN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbiBjaGFpbiBmcm9tIHRoZSBleGlzdGluZyB0ZXh0LgoJICogRmlsZUJ1ZmZlciBzdXBwb3J0IGRvZXMgbm90IGFsbG93IGNsaWVudHMgdG8ga25vdyB0aGUgZG9jdW1lbnQncwoJICogbG9jYXRpb24gYmVmb3JlIHRoZSB0ZXh0IGNvbnRlbnRzIGFyZSBzZXQuCgkgKiAKCSAqIEBzZWUgc2V0KFN0cmluZykKCSAqLwoJcHVibGljIHZvaWQgcmVwYXJzZShPYmplY3QgcmVxdWVzdGVyKSB7CgkJc3RvcFBvc3ROb3RpZmljYXRpb25Qcm9jZXNzaW5nKCk7CgkJY2xlYXJSZWFkT25seSgpOwoKCQlhY3F1aXJlTG9jaygpOwoJCXRyeSB7CgkJCUNoYXJTZXF1ZW5jZVJlYWRlciBzdWJTZXRUZXh0U3RvcmVSZWFkZXIgPSBuZXcgQ2hhclNlcXVlbmNlUmVhZGVyKChDaGFyU2VxdWVuY2UpIGdldFN0b3JlKCksIDAsIGdldFN0b3JlKCkuZ2V0TGVuZ3RoKCkpOwoJCQlyZXNldFBhcnNlcihzdWJTZXRUZXh0U3RvcmVSZWFkZXIsIDApOwoJCQkvLwoJCQlzZXRDYWNoZWREb2N1bWVudFJlZ2lvbihnZXRQYXJzZXIoKS5nZXREb2N1bWVudFJlZ2lvbnMoKSk7CgkJCS8vIHdoZW4gc3RhcnRpbmcgYWZyZXNoLCBvdXIgY2FjaGVkTm9kZSBzaG91bGQgYmUgb3VyIGZpcnN0Tm9kZSwKCQkJLy8gc28gYmUgc3VyZSB0byBpbml0aWFsaXplIHRoZSBmaXJzdE5vZGUgYW5kIGxhc3ROb2RlCgkJCWluaXRpYWxpemVGaXJzdEFuZExhc3REb2N1bWVudFJlZ2lvbigpOwoJCQlTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb25JdGVyYXRvci5zZXRQYXJlbnREb2N1bWVudChnZXRDYWNoZWREb2N1bWVudFJlZ2lvbigpLCB0aGlzKTsKCQl9CgkJZmluYWxseSB7CgkJCXJlbGVhc2VMb2NrKCk7CgkJfQoKCQlyZXN1bWVQb3N0Tm90aWZpY2F0aW9uUHJvY2Vzc2luZygpOwoJfQoKCS8qKgoJICogQHNlZSBJRG9jdW1lbnQjcmVwbGFjZQoJICogQGV4Y2VwdGlvbiBCYWRMb2NhdGlvbkV4Y2VwdGlvbgoJICogICAgICAgICAgICAgICAgSWYgcG9zaXRpb24gaXMgbm90IGEgdmFsaWQgcmFuZ2UgaW4gdGhlIGRvY3VtZW50CgkgKi8KCXB1YmxpYyB2b2lkIHJlcGxhY2UoaW50IHBvcywgaW50IGxlbmd0aCwgU3RyaW5nIHN0cmluZykgdGhyb3dzIEJhZExvY2F0aW9uRXhjZXB0aW9uIHsKCQlpZiAoRGVidWcuZGlzcGxheVdhcm5pbmdzKSB7CgkJCVN5c3RlbS5vdXQucHJpbnRsbigiTm90ZTogSVN0cnVjdHVyZWREb2N1bWVudDo6cmVwbGFjZShpbnQsIGludCwgU3RyaW5nKSAuLi4uIGl0cyBiZXR0ZXIgdG8gdXNlIHJlcGxhY2VUZXh0KHNvdXJjZSwgc3RyaW5nLCBpbnQsIGludCkgQVBJIGZvciBzdHJ1Y3R1cmVkRG9jdW1lbnQgdXBkYXRlcyIpOyAvLyROT04tTkxTLTEkCgkJfQoJCXJlcGxhY2VUZXh0KHRoaXMsIHBvcywgbGVuZ3RoLCBzdHJpbmcpOwoJfQoKCS8qKgoJICogUmVwbGFjZSB0aGUgdGV4dCB3aXRoICJuZXdUZXh0IiBzdGFydGluZyBhdCBwb3NpdGlvbiAic3RhcnQiIGZvciBhCgkgKiBsZW5ndGggb2YgInJlcGxhY2VMZW5ndGgiLgoJICogPHA+CgkgKiAKCSAqIEBwYXJhbSBzdGFydAoJICogICAgICAgICAgICBzdGFydCBvZmZzZXQgb2YgdGV4dCB0byByZXBsYWNlIE5vbmUgb2YgdGhlIG9mZnNldHMgaW5jbHVkZQoJICogICAgICAgICAgICBkZWxpbWl0ZXJzIG9mIHByZWNlZWRpbmcgbGluZXMuIE9mZnNldCAwIGlzIHRoZSBmaXJzdAoJICogICAgICAgICAgICBjaGFyYWN0ZXIgb2YgdGhlIGRvY3VtZW50LgoJICogQHBhcmFtIHJlcGxhY2VMZW5ndGgKCSAqICAgICAgICAgICAgc3RhcnQgb2Zmc2V0IG9mIHRleHQgdG8gcmVwbGFjZQoJICogQHBhcmFtIG5ld1RleHQKCSAqICAgICAgICAgICAgc3RhcnQgb2Zmc2V0IG9mIHRleHQgdG8gcmVwbGFjZQoJICogICAgICAgICAgICA8cD4KCSAqICAgICAgICAgICAgSW1wbGVtZW50b3JzIGhhdmUgdG8gbm90aWZ5IFRleHRDaGFuZ2VkIGxpc3RlbmVycyBhZnRlciB0aGUKCSAqICAgICAgICAgICAgY29udGVudCBoYXMgYmVlbiB1cGRhdGVkLiBUaGUgVGV4dENoYW5nZWRFdmVudCBzaG91bGQgYmUgc2V0CgkgKiAgICAgICAgICAgIGFzIGZvbGxvd3M6CgkgKiAKCSAqIGV2ZW50LnR5cGUgPSBTV1QuVGV4dFJlcGxhY2VkIGV2ZW50LnN0YXJ0ID0gc3RhcnQgb2YgdGhlIHJlcGxhY2VkIHRleHQKCSAqIGV2ZW50Lm51bVJlcGxhY2VkTGluZXMgPSBudW1iZXIgb2YgcmVwbGFjZWQgbGluZXMgZXZlbnQubnVtTmV3TGluZXMgPQoJICogbnVtYmVyIG9mIG5ldyBsaW5lcyBldmVudC5yZXBsYWNlZExlbmd0aCA9IGxlbmd0aCBvZiB0aGUgcmVwbGFjZWQgdGV4dAoJICogZXZlbnQubmV3TGVuZ3RoID0gbGVuZ3RoIG9mIHRoZSBuZXcgdGV4dAoJICogCgkgKiBOT1RFOiBudW1OZXdMaW5lcyBpcyB0aGUgbnVtYmVyIG9mIGluc2VydGVkIGxpbmVzIGFuZCBudW1SZXBsYWNlZExpbmVzCgkgKiBpcyB0aGUgbnVtYmVyIG9mIGRlbGV0ZWQgbGluZXMgYmFzZWQgb24gdGhlIGNoYW5nZSB0aGF0IG9jY3VycwoJICogdmlzdWFsbHkuIEZvciBleGFtcGxlOgoJICogCgkgKiByZXBsYWNlZFRleHQgbmV3VGV4dCBudW1SZXBsYWNlZExpbmVzIG51bU5ld0xpbmVzICIiICJcbiIgMCAxICJcblxuIgoJICogImEiIDIgMCAiYSIgIlxuXG4iIDAgMgoJICovCgkvKioKCSAqIE9uZSBvZiB0aGUgQVBJcyB0byBtYW5pcHVsYXRlIHRoZSBJU3RydWN0dXJlZERvY3VtZW50IGluIHRlcm1zIG9mIHRleHQuCgkgKi8KCXB1YmxpYyBTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudCByZXBsYWNlVGV4dChPYmplY3QgcmVxdWVzdGVyLCBpbnQgc3RhcnQsIGludCByZXBsYWNlbWVudExlbmd0aCwgU3RyaW5nIGNoYW5nZXMpIHsKCQlyZXR1cm4gcmVwbGFjZVRleHQocmVxdWVzdGVyLCBzdGFydCwgcmVwbGFjZW1lbnRMZW5ndGgsIGNoYW5nZXMsIGZhbHNlKTsKCX0KCglwdWJsaWMgU3RydWN0dXJlZERvY3VtZW50RXZlbnQgcmVwbGFjZVRleHQoT2JqZWN0IHJlcXVlc3RlciwgaW50IHN0YXJ0LCBpbnQgcmVwbGFjZW1lbnRMZW5ndGgsIFN0cmluZyBjaGFuZ2VzLCBib29sZWFuIGlnbm9yZVJlYWRPbmx5U2V0dGluZ3MpIHsKCQlyZXR1cm4gaW50ZXJuYWxSZXBsYWNlVGV4dChyZXF1ZXN0ZXIsIHN0YXJ0LCByZXBsYWNlbWVudExlbmd0aCwgY2hhbmdlcywgaWdub3JlUmVhZE9ubHlTZXR0aW5ncyk7Cgl9CgoJdm9pZCByZXNldFBhcnNlcihpbnQgc3RhcnRPZmZzZXQsIGludCBlbmRPZmZzZXQpIHsKCgkJUmVnaW9uUGFyc2VyIHBhcnNlciA9IGdldFBhcnNlcigpOwoJCUlUZXh0U3RvcmUgdGV4dFN0b3JlID0gZ2V0U3RvcmUoKTsKCQlpZiAodGV4dFN0b3JlIGluc3RhbmNlb2YgQ2hhclNlcXVlbmNlKSB7CgkJCUNoYXJTZXF1ZW5jZVJlYWRlciBzdWJTZXRUZXh0U3RvcmVSZWFkZXIgPSBuZXcgQ2hhclNlcXVlbmNlUmVhZGVyKChDaGFyU2VxdWVuY2UpIHRleHRTdG9yZSwgc3RhcnRPZmZzZXQsIGVuZE9mZnNldCAtIHN0YXJ0T2Zmc2V0KTsKCQkJcGFyc2VyLnJlc2V0KHN1YlNldFRleHRTdG9yZVJlYWRlciwgc3RhcnRPZmZzZXQpOwoJCX0KCQllbHNlIHsKCQkJU3RyaW5nIG5ld05vZGVUZXh0ID0gZ2V0KHN0YXJ0T2Zmc2V0LCBlbmRPZmZzZXQgLSBzdGFydE9mZnNldCk7CgkJCXBhcnNlci5yZXNldChuZXdOb2RlVGV4dCwgc3RhcnRPZmZzZXQpOwoKCQl9CgoJfQoKCXZvaWQgcmVzZXRQYXJzZXIoUmVhZGVyIHJlYWRlciwgaW50IHN0YXJ0T2Zmc2V0KSB7CgkJUmVnaW9uUGFyc2VyIHBhcnNlciA9IGdldFBhcnNlcigpOwoJCXBhcnNlci5yZXNldChyZWFkZXIsIHN0YXJ0T2Zmc2V0KTsKCX0KCgkvKgoJICogKG5vbi1KYXZhZG9jKQoJICogCgkgKiBAc2VlIG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSURvY3VtZW50RXh0ZW5zaW9uI3Jlc3VtZVBvc3ROb3RpZmljYXRpb25Qcm9jZXNzaW5nKCkKCSAqLwoJcHVibGljIHZvaWQgcmVzdW1lUG9zdE5vdGlmaWNhdGlvblByb2Nlc3NpbmcoKSB7CgkJLS1mU3RvcHBlZENvdW50OwoJCWlmIChmU3RvcHBlZENvdW50ID09IDAgJiYgZlJlZW50cmFuY2VDb3VudCA9PSAwKQoJCQlleGVjdXRlUG9zdE5vdGlmaWNhdGlvbkNoYW5nZXMoKTsKCX0KCgkvKioKCSAqIEBkZXByZWNhdGVkIGluIHN1cGVyY2xhc3MgaW4gMy4wIC0gdXNlIGEgRmluZFJlcGxhY2VEb2N1bWVudEFkYXB0ZXIKCSAqICAgICAgICAgICAgIGRpcmVjdGx5CgkgKiBAc2VlIElEb2N1bWVudCNzZWFyY2gKCSAqLwoJcHVibGljIGludCBzZWFyY2goaW50IHN0YXJ0UG9zaXRpb24sIFN0cmluZyBmaW5kU3RyaW5nLCBib29sZWFuIGZvcndhcmRTZWFyY2gsIGJvb2xlYW4gY2FzZVNlbnNpdGl2ZSwgYm9vbGVhbiB3aG9sZVdvcmQpIHRocm93cyBCYWRMb2NhdGlvbkV4Y2VwdGlvbiB7CgkJLy8gKGRtdykgSSBhZGRlZCB0aGlzIHdhcm5pbmcsIHRvIGtub3cgaWYgc3RpbGwgYmVpbmcgdXNlZC4gSSdtIG5vdAoJCS8vIHN1cmUgaXQKCQkvLyB3b3JrcyBhcyBleHBlY3RlZCBhbnkgbG9uZ2VyLgoJCS8vIGJ1dCB0aGUgd2FybmluZyBzaG91bGQgYmUgcmVtb3ZlZCwgb25jZSBrbm93LgoJCUxvZ2dlci5sb2coTG9nZ2VyLklORk8sICJXQVJOSU5HOiB1c2luZyB1bnN1cHBvcnRlZCBkZXByZWNhdGVkIG1ldGhvZCAnc2VhcmNoJyIpOyAvLyROT04tTkxTLTEkCgkJaW50IG9mZnNldCA9IC0xOwoJCUlSZWdpb24gbWF0Y2ggPSBuZXcgRmluZFJlcGxhY2VEb2N1bWVudEFkYXB0ZXIodGhpcykuZmluZChzdGFydFBvc2l0aW9uLCBmaW5kU3RyaW5nLCBmb3J3YXJkU2VhcmNoLCBjYXNlU2Vuc2l0aXZlLCB3aG9sZVdvcmQsIGZhbHNlKTsKCQlpZiAobWF0Y2ggIT0gbnVsbCkgewoJCQlvZmZzZXQgPSBtYXRjaC5nZXRPZmZzZXQoKTsKCQl9CgkJcmV0dXJuIG9mZnNldDsKCX0KCgkvKioKCSAqIEBzZWUgSURvY3VtZW50I3NldFRleHQKCSAqLwoJcHVibGljIHZvaWQgc2V0KFN0cmluZyBzdHJpbmcpIHsKCQlpZiAoRGVidWcuZGlzcGxheUluZm8pIHsKCQkJU3lzdGVtLm91dC5wcmludGxuKCJOb3RlOiBJU3RydWN0dXJlZERvY3VtZW50OjpzZXRUZXh0KFN0cmluZykgLi4uLiBpdHMgYmV0dGVyIHRvIHVzZSBzZXRUZXh0KHNvdXJjZSwgc3RyaW5nKSBBUEkgZm9yIHN0cnVjdHVyZWREb2N1bWVudCB1cGRhdGVzIik7IC8vJE5PTi1OTFMtMSQKCQl9CgkJc2V0VGV4dChudWxsLCBzdHJpbmcpOwoJfQoKCS8qKgoJICogVGhpcyBtYXkgYmUgbWFya2VkIHB1YmxpYywgYnV0IHNob3VsZCBiZSBwYWNrYWdlZCBwcm90ZWN0ZWQsIG9uY2UKCSAqIHJlZmFjdG9yaW5nIGlzIGNvbXBsZXRlIChpbiBvdGhlciB3b3Jkcywgbm90IGZvciBjbGllbnQgdXNlKS4KCSAqLwoJcHVibGljIHZvaWQgc2V0Q2FjaGVkRG9jdW1lbnRSZWdpb24oSVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbiBzdHJ1Y3R1cmVkUmVnaW9uKSB7CgkJaWYgKFVTRV9MT0NBTF9USFJFQUQpIHsKCQkJZkN1cnJlbnREb2N1bW5ldFJlZ2lvbkNhY2hlLnNldChzdHJ1Y3R1cmVkUmVnaW9uKTsKCQl9CgkJZWxzZSB7CgkJCWNhY2hlZERvY3VtZW50UmVnaW9uID0gc3RydWN0dXJlZFJlZ2lvbjsKCQl9Cgl9CgoJLyoqCgkgKiBTZXRzIHRoZSBkb2N1bWVudCdzIHBhcnRpdGlvbmVyLgoJICogCgkgKiBAc2VlIElEb2N1bWVudFBhcnRpdGlvbmVyCgkgKi8KCXB1YmxpYyB2b2lkIHNldERvY3VtZW50UGFydGl0aW9uZXIoSURvY3VtZW50UGFydGl0aW9uZXIgcGFydGl0aW9uZXIpIHsKCQlzZXREb2N1bWVudFBhcnRpdGlvbmVyKElEb2N1bWVudEV4dGVuc2lvbjMuREVGQVVMVF9QQVJUSVRJT05JTkcsIHBhcnRpdGlvbmVyKTsKCX0KCgoJcHVibGljIHZvaWQgc2V0RG9jdW1lbnRQYXJ0aXRpb25lcihTdHJpbmcgcGFydGl0aW9uaW5nLCBJRG9jdW1lbnRQYXJ0aXRpb25lciBwYXJ0aXRpb25lcikgewoJCWlmIChwYXJ0aXRpb25lciA9PSBudWxsKSB7CgkJCWlmIChmRG9jdW1lbnRQYXJ0aXRpb25lcnMgIT0gbnVsbCkgewoJCQkJZkRvY3VtZW50UGFydGl0aW9uZXJzLnJlbW92ZShwYXJ0aXRpb25pbmcpOwoJCQkJaWYgKGZEb2N1bWVudFBhcnRpdGlvbmVycy5zaXplKCkgPT0gMCkKCQkJCQlmRG9jdW1lbnRQYXJ0aXRpb25lcnMgPSBudWxsOwoJCQl9CgkJfQoJCWVsc2UgewoJCQlpZiAoZkRvY3VtZW50UGFydGl0aW9uZXJzID09IG51bGwpCgkJCQlmRG9jdW1lbnRQYXJ0aXRpb25lcnMgPSBuZXcgSGFzaE1hcCgpOwoJCQlmRG9jdW1lbnRQYXJ0aXRpb25lcnMucHV0KHBhcnRpdGlvbmluZywgcGFydGl0aW9uZXIpOwoJCX0KCQlEb2N1bWVudFBhcnRpdGlvbmluZ0NoYW5nZWRFdmVudCBldmVudCA9IG5ldyBEb2N1bWVudFBhcnRpdGlvbmluZ0NoYW5nZWRFdmVudCh0aGlzKTsKCQlldmVudC5zZXRQYXJ0aXRpb25DaGFuZ2UocGFydGl0aW9uaW5nLCAwLCBnZXRMZW5ndGgoKSk7CgkJZmlyZURvY3VtZW50UGFydGl0aW9uaW5nQ2hhbmdlZChldmVudCk7Cgl9CgoJcHVibGljIHZvaWQgc2V0RW5jb2RpbmdNZW1lbnRvKEVuY29kaW5nTWVtZW50byBlbmNvZGluZ01lbWVudG8pIHsKCQl0aGlzLmVuY29kaW5nTWVtZW50byA9IGVuY29kaW5nTWVtZW50bzsKCX0KCgl2b2lkIHNldEZpcnN0RG9jdW1lbnRSZWdpb24oSVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbiByZWdpb24pIHsKCQlmaXJzdERvY3VtZW50UmVnaW9uID0gcmVnaW9uOwoKCX0KCgkvKgoJICogKG5vbi1KYXZhZG9jKQoJICogCgkgKiBAc2VlIG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSURvY3VtZW50RXh0ZW5zaW9uNCNzZXRJbml0aWFsTGluZURlbGltaXRlcihqYXZhLmxhbmcuU3RyaW5nKQoJICovCglwdWJsaWMgdm9pZCBzZXRJbml0aWFsTGluZURlbGltaXRlcihTdHJpbmcgZGVsaW1pdGVyKSB7CgkJLy8gbWFrZSBzdXJlIG91ciBwcmVmZXJyZWQgZGVsaW1pdGVyIGlzCgkJLy8gb25lIG9mIHRoZSBsZWdhbCBvbmVzCgkJaWYgKFV0aWxpdGllcy5jb250YWluc1N0cmluZyhnZXRMZWdhbExpbmVEZWxpbWl0ZXJzKCksIGRlbGltaXRlcikpIHsKCQkJcHJlZmVyZWREZWxpbWl0ZXIgPSBkZWxpbWl0ZXI7CgkJfQoJCWVsc2UgewoJCQlpZiAoTG9nZ2VyLkRFQlVHX0RPQ1VNRU5UKQoJCQkJTG9nZ2VyLmxvZyhMb2dnZXIuSU5GTywgIkF0dGVtcHQgdG8gc2V0IGxpbmVkZWxpbWl0ZXIgdG8gbm9uLWxlZ2FsIGRlbGltaXRlciIpOyAvLyROT04tTkxTLTEkIC8vJE5PTi1OTFMtMiQKCQkJcHJlZmVyZWREZWxpbWl0ZXIgPSBQbGF0Zm9ybUxpbmVEZWxpbWl0ZXI7CgkJfQoJfQoKCXZvaWQgc2V0TGFzdERvY3VtZW50UmVnaW9uKElTdHJ1Y3R1cmVkRG9jdW1lbnRSZWdpb24gcmVnaW9uKSB7CgkJbGFzdERvY3VtZW50UmVnaW9uID0gcmVnaW9uOwoKCX0KCgkvKgoJICogKG5vbi1KYXZhZG9jKQoJICogCgkgKiBAc2VlIG9yZy5lY2xpcHNlLndzdC5zc2UuY29yZS5pbnRlcm5hbC5wcm92aXNpb25hbC50ZXh0LklTdHJ1Y3R1cmVkRG9jdW1lbnQjc2V0TGluZURlbGltaXRlcihqYXZhLmxhbmcuU3RyaW5nKQoJICovCglwdWJsaWMgdm9pZCBzZXRMaW5lRGVsaW1pdGVyKFN0cmluZyBkZWxpbWl0ZXIpIHsKCQlzZXRJbml0aWFsTGluZURlbGltaXRlcihkZWxpbWl0ZXIpOwoJfQoKCS8qKgoJICogU2V0cyB0aGUgZG9jdW1lbnQncyBsaW5lIHRyYWNrZXIuIE11c3QgYmUgY2FsbGVkIGF0IHRoZSBiZWdpbm5pbmcgb2YKCSAqIHRoZSBjb25zdHJ1Y3Rvci4KCSAqIAoJICogQHBhcmFtIHRyYWNrZXIKCSAqICAgICAgICAgICAgdGhlIGRvY3VtZW50J3MgbGluZSB0cmFja2VyCgkgKi8KCXByaXZhdGUgdm9pZCBzZXRMaW5lVHJhY2tlcihJTGluZVRyYWNrZXIgdHJhY2tlcikgewoJCWZUcmFja2VyID0gdHJhY2tlcjsKCX0KCglwdWJsaWMgdm9pZCBzZXRQYXJzZXIoUmVnaW9uUGFyc2VyIG5ld1BhcnNlcikgewoJCWludGVybmFsX3NldFBhcnNlcihuZXdQYXJzZXIpOwoJfQoKCS8qKgoJICogQHBhcmFtIHBvc2l0aW9uTWFuYWdlcgoJICogICAgICAgICAgICBUaGUgcG9zaXRpb25NYW5hZ2VyIHRvIHNldC4KCSAqLwoJLy8gVE9ETzogbWFrZSBwcml2YXRlIGlzIG5lZWRlZCwgZWxzZSByZW1vdmUKCXZvaWQgc2V0UG9zaXRpb25NYW5hZ2VyKEdlbmVyaWNQb3NpdGlvbk1hbmFnZXIgcG9zaXRpb25NYW5hZ2VyKSB7CgkJZlBvc2l0aW9uTWFuYWdlciA9IHBvc2l0aW9uTWFuYWdlcjsKCX0KCgkvKioKCSAqIAoJICovCglwdWJsaWMgdm9pZCBzZXRSZVBhcnNlcihJU3RydWN0dXJlZFRleHRSZVBhcnNlciBuZXdSZVBhcnNlcikgewoJCWZSZVBhcnNlciA9IG5ld1JlUGFyc2VyOwoJCWlmIChmUmVQYXJzZXIgIT0gbnVsbCkgewoJCQlmUmVQYXJzZXIuc2V0U3RydWN0dXJlZERvY3VtZW50KHRoaXMpOwoJCX0KCX0KCgkvKioKCSAqIE9uZSBvZiB0aGUgQVBJcyB0byBtYW5pcHVsYXRlIHRoZSBJU3RydWN0dXJlZERvY3VtZW50IGluIHRlcm1zIG9mIHRleHQuCgkgKi8KCXB1YmxpYyBTdHJ1Y3R1cmVkRG9jdW1lbnRFdmVudCBzZXRUZXh0KE9iamVjdCByZXF1ZXN0ZXIsIFN0cmluZyB0aGVTdHJpbmcpIHsKCgkJU3RydWN0dXJlZERvY3VtZW50RXZlbnQgcmVzdWx0ID0gbnVsbDsKCgkJcmVzdWx0ID0gcmVwbGFjZVRleHQocmVxdWVzdGVyLCAwLCBnZXRMZW5ndGgoKSwgdGhlU3RyaW5nLCB0cnVlKTsKCgkJcmV0dXJuIHJlc3VsdDsKCX0KCgkvKioKCSAqIFNldHMgdGhlIGRvY3VtZW50J3MgdGV4dCBzdG9yZS4gTXVzdCBiZSBjYWxsZWQgYXQgdGhlIGJlZ2lubmluZyBvZiB0aGUKCSAqIGNvbnN0cnVjdG9yLgoJICogCgkgKiBAcGFyYW0gc3RvcmUKCSAqICAgICAgICAgICAgdGhlIGRvY3VtZW50J3MgdGV4dCBzdG9yZQoJICovCglwcml2YXRlIHZvaWQgc2V0VGV4dFN0b3JlKElUZXh0U3RvcmUgc3RvcmUpIHsKCQlmU3RvcmUgPSBzdG9yZTsKCX0KCglwdWJsaWMgdm9pZCBzZXRVbmRvTWFuYWdlcihJU3RydWN0dXJlZFRleHRVbmRvTWFuYWdlciB1bmRvTWFuYWdlcikgewoKCQkvLyBpZiB0aGUgdW5kbyBtYW5hZ2VyIGhhcyBhbHJlYWR5IGJlZW4gc2V0LCB0aGVuCgkJLy8gZmFpbCBmYXN0LCBzaW5jZSBjaGFuZ2luZyB0aGUgdW5kbyBtYW5hZ2VyIHdpbGwgbGVhZAoJCS8vIHRvIHVudXN1YWwgcmVzdWx0cyAob3IgYXQgbGVhc3QgbG9zcyBvZiB1bmRvIHN0YWNrKS4KCQlpZiAoZlVuZG9NYW5hZ2VyICE9IG51bGwgJiYgZlVuZG9NYW5hZ2VyICE9IHVuZG9NYW5hZ2VyKSB7CgkJCXRocm93IG5ldyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oImNhbiBub3QgY2hhbmdlIHVuZG8gbWFuYWdlciBvbmNlIGl0cyBiZWVuIHNldCIpOyAvLyROT04tTkxTLTEkCgkJfQoJCWVsc2UgewoJCQlmVW5kb01hbmFnZXIgPSB1bmRvTWFuYWdlcjsKCQl9Cgl9CgoKCXB1YmxpYyB2b2lkIHN0YXJ0U2VxdWVudGlhbFJld3JpdGUoYm9vbGVhbiBub3JtYWxpemVkKSB7CgkJSVRleHRTdG9yZSBzdG9yZSA9IG5ldyBTZXF1ZW50aWFsUmV3cml0ZVRleHRTdG9yZShnZXRTdG9yZSgpKTsKCQlzZXRUZXh0U3RvcmUoc3RvcmUpOwoJfQoKCS8qCgkgKiAobm9uLUphdmFkb2MpCgkgKiAKCSAqIEBzZWUgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5JRG9jdW1lbnRFeHRlbnNpb24jc3RvcFBvc3ROb3RpZmljYXRpb25Qcm9jZXNzaW5nKCkKCSAqLwoJcHVibGljIHZvaWQgc3RvcFBvc3ROb3RpZmljYXRpb25Qcm9jZXNzaW5nKCkgewoJCSsrZlN0b3BwZWRDb3VudDsKCX0KCgoJcHVibGljIHZvaWQgc3RvcFNlcXVlbnRpYWxSZXdyaXRlKCkgewoJCWlmIChnZXRTdG9yZSgpIGluc3RhbmNlb2YgU2VxdWVudGlhbFJld3JpdGVUZXh0U3RvcmUpIHsKCQkJU2VxdWVudGlhbFJld3JpdGVUZXh0U3RvcmUgc3J3cyA9IChTZXF1ZW50aWFsUmV3cml0ZVRleHRTdG9yZSkgZ2V0U3RvcmUoKTsKCQkJSVRleHRTdG9yZSBzb3VyY2UgPSBzcndzLmdldFNvdXJjZVN0b3JlKCk7CgkJCXNldFRleHRTdG9yZShzb3VyY2UpOwoJCQlzcndzLmRpc3Bvc2UoKTsKCQl9Cgl9CgoJLyoKCSAqIChub24tSmF2YWRvYykKCSAqIAoJICogQHNlZSBqYXZhLmxhbmcuQ2hhclNlcXVlbmNlI3N1YlNlcXVlbmNlKGludCwgaW50KQoJICovCglwdWJsaWMgQ2hhclNlcXVlbmNlIHN1YlNlcXVlbmNlKGludCBhcmcwLCBpbnQgYXJnMSkgewoJCXJldHVybiBnZXQoYXJnMCwgYXJnMSk7Cgl9CgoJLyoqCgkgKiBAcGFyYW0gcmVzdWx0CgkgKi8KCXByaXZhdGUgdm9pZCB1cGRhdGVEZWxldGVkRmllbGRzKFN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbnNSZXBsYWNlZEV2ZW50IGV2ZW50KSB7CgkJSVN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbkxpc3Qgb2xkUmVnaW9ucyA9IGV2ZW50LmdldE9sZFN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbnMoKTsKCQlmb3IgKGludCBpID0gMDsgaSA8IG9sZFJlZ2lvbnMuZ2V0TGVuZ3RoKCk7IGkrKykgewoJCQlJU3RydWN0dXJlZERvY3VtZW50UmVnaW9uIHN0cnVjdHVyZWREb2N1bWVudFJlZ2lvbiA9IG9sZFJlZ2lvbnMuaXRlbShpKTsKCQkJc3RydWN0dXJlZERvY3VtZW50UmVnaW9uLnNldERlbGV0ZWQodHJ1ZSk7CgkJfQoKCX0KCgkvKioKCSAqIENhbGxlZCBieSByZS1wYXJzZXIuIE5vdGU6IHRoaXMgbWV0aG9kIG1heSBiZSAicHVibGljIiBidXQgc2hvdWxkIG9ubHkKCSAqIGJlIGNhbGxlZCBieSByZS1wYXJzZXJzIGluIHRoZSByaWdodCBjaXJjdW1zdGFuY2VzLgoJICovCglwdWJsaWMgdm9pZCB1cGRhdGVEb2N1bWVudERhdGEoaW50IHN0YXJ0LCBpbnQgbGVuZ3RoVG9SZXBsYWNlLCBTdHJpbmcgY2hhbmdlcykgewoJCXN0b3BQb3N0Tm90aWZpY2F0aW9uUHJvY2Vzc2luZygpOwoJCWdldFN0b3JlKCkucmVwbGFjZShzdGFydCwgbGVuZ3RoVG9SZXBsYWNlLCBjaGFuZ2VzKTsKCQl0cnkgewoJCQlnZXRUcmFja2VyKCkucmVwbGFjZShzdGFydCwgbGVuZ3RoVG9SZXBsYWNlLCBjaGFuZ2VzKTsKCQl9CgoJCWNhdGNoIChCYWRMb2NhdGlvbkV4Y2VwdGlvbiBlKSB7CgkJCS8vIHNob3VsZCBiZSBpbXBvc3NpYmxlIGhlcmUsIGJ1dCB3aWxsIGxvZyBmb3Igbm93CgkJCUxvZ2dlci5sb2dFeGNlcHRpb24oZSk7CgkJfQoJCWlmIChmUG9zaXRpb25NYW5hZ2VyICE9IG51bGwpIHsKCQkJZlBvc2l0aW9uTWFuYWdlci51cGRhdGVQb3NpdGlvbnMobmV3IERvY3VtZW50RXZlbnQodGhpcywgc3RhcnQsIGxlbmd0aFRvUmVwbGFjZSwgY2hhbmdlcykpOwoJCX0KCQlmTW9kaWZpY2F0aW9uU3RhbXArKzsKCQlyZXN1bWVQb3N0Tm90aWZpY2F0aW9uUHJvY2Vzc2luZygpOwoJfQoKCXByaXZhdGUgU3RydWN0dXJlZERvY3VtZW50RXZlbnQgdXBkYXRlTW9kZWwoT2JqZWN0IHJlcXVlc3RlciwgaW50IHN0YXJ0LCBpbnQgbGVuZ3RoVG9SZXBsYWNlLCBTdHJpbmcgY2hhbmdlcykgewoJCVN0cnVjdHVyZWREb2N1bWVudEV2ZW50IHJlc3VsdCA9IG51bGw7CgkJSVN0cnVjdHVyZWRUZXh0UmVQYXJzZXIgcmVQYXJzZXIgPSBnZXRSZVBhcnNlcigpOwoJCS8vIGluaXRpYWxpemUgdGhlIElTdHJ1Y3R1cmVkVGV4dFJlUGFyc2VyIHdpdGggdGhlIHN0YW5kYXJkIGRhdGEKCQkvLyB0aGF0J3MKCQkvLyBhbHdheXMgbmVlZGVkCgkJcmVQYXJzZXIuaW5pdGlhbGl6ZShyZXF1ZXN0ZXIsIHN0YXJ0LCBsZW5ndGhUb1JlcGxhY2UsIGNoYW5nZXMpOwoJCXJlc3VsdCA9IHJlUGFyc2VyLnJlcGFyc2UoKTsKCQkvLyBpZiByZXN1bHQgaXMgbnVsbCBhdCB0aGlzIHBvaW50LCB0aGVuIHRoZXJlIG11c3QgYmUgYW4gZXJyb3IsIHNpbmNlCgkJLy8gZXZlbiBpZiB0aGVyZQoJCS8vIHdhcyBubyBjaGFuZ2UgKGVpdGhlciBkaXNhbGxvdyBkdWUgdG8gcmVhZG9ubHksIG9yIGEgcGVyc29uIHBhc3RlZAoJCS8vIHRoZSBzYW1lIHRoaW5nCgkJLy8gdGhleSBoYWQgc2VsZWN0ZWQpIHRoZW4gYSAiTm9DaGFuZ2UiIGV2ZW50IHNob3VsZCBoYXZlIGJlZW4gZmlyZWQuCgkJQXNzZXJ0LmlzTm90TnVsbChyZXN1bHQsICJubyBzdHJ1Y3R1cmVkRG9jdW1lbnQgZXZlbnQgd2FzIGNyZWF0ZWQgaW4gSVN0cnVjdHVyZWREb2N1bWVudDo6dXBkYXRlU3RydWN0dXJlZERvY3VtZW50Iik7IC8vJE5PTi1OTFMtMSQKCQlyZXR1cm4gcmVzdWx0OwoJfQoKCS8qCgkgKiAobm9uLUphdmFkb2MpCgkgKiAKCSAqIEBzZWUgb3JnLmVjbGlwc2Uud3N0LnNzZS5jb3JlLmludGVybmFsLnByb3Zpc2lvbmFsLmRvY3VtZW50LklFbmNvZGVkRG9jdW1lbnQjZ2V0UHJlZmVycmVkTGluZURlbGltaXRlcigpCgkgKi8KCXB1YmxpYyBTdHJpbmcgZ2V0UHJlZmVycmVkTGluZURlbGltaXRlcigpIHsKCQlyZXR1cm4gZ2V0RGVmYXVsdExpbmVEZWxpbWl0ZXIoKTsKCX0KCgkvKgoJICogKG5vbi1KYXZhZG9jKQoJICogCgkgKiBAc2VlIG9yZy5lY2xpcHNlLndzdC5zc2UuY29yZS5pbnRlcm5hbC5wcm92aXNpb25hbC5kb2N1bWVudC5JRW5jb2RlZERvY3VtZW50I3NldFByZWZlcnJlZExpbmVEZWxpbWl0ZXIoamF2YS5sYW5nLlN0cmluZykKCSAqLwoJcHVibGljIHZvaWQgc2V0UHJlZmVycmVkTGluZURlbGltaXRlcihTdHJpbmcgcHJvYmFibGVMaW5lRGVsaW1pdGVyKSB7CgkJc2V0SW5pdGlhbExpbmVEZWxpbWl0ZXIocHJvYmFibGVMaW5lRGVsaW1pdGVyKTsKCgl9CgoKCS8qKgoJICogQ2xhc3Mgd2hpY2ggaW1wbGVtZW50cyB0aGUgcmV3cml0YWJsZSBzZXNzaW9uIGZvciB0aGUgU1NFLgoJICogCgkgKi8KCWNsYXNzIFN0cnVjdHVyZWREb2N1bWVudFJld3JpdGVTZXNzaW9uIGV4dGVuZHMgRG9jdW1lbnRSZXdyaXRlU2Vzc2lvbiB7CgoJCS8qKgoJCSAqIENyZWF0ZXMgYSBuZXcgc2Vzc2lvbi4KCQkgKiAKCQkgKiBAcGFyYW0gc2Vzc2lvblR5cGUKCQkgKiAgICAgICAgICAgIHRoZSB0eXBlIG9mIHRoaXMgc2Vzc2lvbgoJCSAqLwoJCXByb3RlY3RlZCBTdHJ1Y3R1cmVkRG9jdW1lbnRSZXdyaXRlU2Vzc2lvbihEb2N1bWVudFJld3JpdGVTZXNzaW9uVHlwZSBzZXNzaW9uVHlwZSkgewoJCQlzdXBlcihzZXNzaW9uVHlwZSk7CgkJfQoJfQoKCS8qCgkgKiAobm9uLUphdmFkb2MpCgkgKiAKCSAqIEBzZWUgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5JRG9jdW1lbnRFeHRlbnNpb240I3N0YXJ0UmV3cml0ZVNlc3Npb24ob3JnLmVjbGlwc2UuamZhY2UudGV4dC5Eb2N1bWVudFJld3JpdGVTZXNzaW9uVHlwZSkKCSAqLwoJcHVibGljIERvY3VtZW50UmV3cml0ZVNlc3Npb24gc3RhcnRSZXdyaXRlU2Vzc2lvbihEb2N1bWVudFJld3JpdGVTZXNzaW9uVHlwZSBzZXNzaW9uVHlwZSkgdGhyb3dzIElsbGVnYWxTdGF0ZUV4Y2VwdGlvbiB7CgkJLy8gZGVsZWdhdGUgdG8gc3ViLWNsYXNzLCBzbyBVSSB0aHJlYWRpbmcgaXMgaGFuZGxlZCBjb3JyZWN0bHkKCQlyZXR1cm4gaW50ZXJuYWxTdGFydFJld3JpdGVTZXNzaW9uKHNlc3Npb25UeXBlKTsKCX0KCgkvKioKCSAqIE5PVC1BUEkuIEZpbmFsIHByb3RlY3RlZCBzbyBjbGllbnRzIG1heSBjYWxsIHRoaXMgbWV0aG9kIGlmIG5lZWRlZCwgYnV0CgkgKiBjYW5ub3Qgb3ZlcnJpZGUuCgkgKiAKCSAqIEBwYXJhbSBzZXNzaW9uVHlwZQoJICogQHJldHVybgoJICogQHRocm93cyBJbGxlZ2FsU3RhdGVFeGNlcHRpb24KCSAqLwoJZmluYWwgcHJvdGVjdGVkIERvY3VtZW50UmV3cml0ZVNlc3Npb24gaW50ZXJuYWxTdGFydFJld3JpdGVTZXNzaW9uKERvY3VtZW50UmV3cml0ZVNlc3Npb25UeXBlIHNlc3Npb25UeXBlKSB0aHJvd3MgSWxsZWdhbFN0YXRlRXhjZXB0aW9uIHsKCQlpZiAoZ2V0QWN0aXZlUmV3cml0ZVNlc3Npb24oKSAhPSBudWxsKQoJCQl0aHJvdyBuZXcgSWxsZWdhbFN0YXRlRXhjZXB0aW9uKCJhbHJlYWR5IGluIGEgcmV3cml0ZSBzZXNzaW9uIik7CgoJCURvY3VtZW50UmV3cml0ZVNlc3Npb24gc2Vzc2lvbiA9IG5ldyBTdHJ1Y3R1cmVkRG9jdW1lbnRSZXdyaXRlU2Vzc2lvbihzZXNzaW9uVHlwZSk7CgkJRG9jdW1lbnRSZXdyaXRlU2Vzc2lvbkV2ZW50IGV2ZW50ID0gbmV3IERvY3VtZW50UmV3cml0ZVNlc3Npb25FdmVudCh0aGlzLCBzZXNzaW9uLCBEb2N1bWVudFJld3JpdGVTZXNzaW9uRXZlbnQuU0VTU0lPTl9TVEFSVCk7CgkJZmlyZURvY3VtZW50UmV3cml0ZVNlc3Npb25FdmVudChldmVudCk7CgoJCUlMaW5lVHJhY2tlciB0cmFja2VyID0gZ2V0VHJhY2tlcigpOwoJCWlmICh0cmFja2VyIGluc3RhbmNlb2YgSUxpbmVUcmFja2VyRXh0ZW5zaW9uKSB7CgkJCUlMaW5lVHJhY2tlckV4dGVuc2lvbiBleHRlbnNpb24gPSAoSUxpbmVUcmFja2VyRXh0ZW5zaW9uKSB0cmFja2VyOwoJCQlleHRlbnNpb24uc3RhcnRSZXdyaXRlU2Vzc2lvbihzZXNzaW9uKTsKCQl9CgoJCXN0YXJ0UmV3cml0ZVNlc3Npb25PblBhcnRpdGlvbmVycyhzZXNzaW9uKTsKCgkJaWYgKERvY3VtZW50UmV3cml0ZVNlc3Npb25UeXBlLlNFUVVFTlRJQUwgPT0gc2Vzc2lvblR5cGUpCgkJCXN0YXJ0U2VxdWVudGlhbFJld3JpdGUoZmFsc2UpOwoJCWVsc2UgaWYgKERvY3VtZW50UmV3cml0ZVNlc3Npb25UeXBlLlNUUklDVExZX1NFUVVFTlRJQUwgPT0gc2Vzc2lvblR5cGUpCgkJCXN0YXJ0U2VxdWVudGlhbFJld3JpdGUodHJ1ZSk7CgoJCWZBY3RpdmVSZXdyaXRlU2Vzc2lvbiA9IHNlc3Npb247CgkJcmV0dXJuIHNlc3Npb247Cgl9CgoJLyoqCgkgKiBTdGFydHMgdGhlIGdpdmVuIHJld3JpdGUgc2Vzc2lvbi4KCSAqCgkgKiBAcGFyYW0gc2Vzc2lvbiB0aGUgcmV3cml0ZSBzZXNzaW9uCgkgKiBAc2luY2UgMi4wCgkgKi8KCWZpbmFsIHZvaWQgc3RhcnRSZXdyaXRlU2Vzc2lvbk9uUGFydGl0aW9uZXJzKERvY3VtZW50UmV3cml0ZVNlc3Npb24gc2Vzc2lvbikgewoJCWlmIChmRG9jdW1lbnRQYXJ0aXRpb25lcnMgIT0gbnVsbCkgewoJCQlJdGVyYXRvciBlPSBmRG9jdW1lbnRQYXJ0aXRpb25lcnMudmFsdWVzKCkuaXRlcmF0b3IoKTsKCQkJd2hpbGUgKGUuaGFzTmV4dCgpKSB7CgkJCQlPYmplY3QgcGFydGl0aW9uZXI9IGUubmV4dCgpOwoJCQkJaWYgKHBhcnRpdGlvbmVyIGluc3RhbmNlb2YgSURvY3VtZW50UGFydGl0aW9uZXJFeHRlbnNpb24zKSB7CgkJCQkJSURvY3VtZW50UGFydGl0aW9uZXJFeHRlbnNpb24zIGV4dGVuc2lvbj0gKElEb2N1bWVudFBhcnRpdGlvbmVyRXh0ZW5zaW9uMykgcGFydGl0aW9uZXI7CgkJCQkJZXh0ZW5zaW9uLnN0YXJ0UmV3cml0ZVNlc3Npb24oc2Vzc2lvbik7CgkJCQl9CgkJCX0KCQl9Cgl9CgoKCXB1YmxpYyB2b2lkIHN0b3BSZXdyaXRlU2Vzc2lvbihEb2N1bWVudFJld3JpdGVTZXNzaW9uIHNlc3Npb24pIHsKCQkvLyBkZWxlZ2F0ZSB0byBzdWItY2xhc3MsIHNvIFVJIHRocmVhZGluZyBpcyBoYW5kbGVkIGNvcnJlY3RseQoJCWludGVybmFsU3RvcFJld3JpdGVTZXNzaW9uKHNlc3Npb24pOwoJfQoKCS8qKgoJICogTk9ULUFQSS4gRmluYWwgcHJvdGVjdGVkIHNvIGNsaWVudHMgbWF5IGNhbGwgdGhpcyBtZXRob2QgaWYgbmVlZGVkLCBidXQKCSAqIGNhbm5vdCBvdmVycmlkZS4KCSAqIAoJICogQHBhcmFtIHNlc3Npb24KCSAqLwoJZmluYWwgcHJvdGVjdGVkIHZvaWQgaW50ZXJuYWxTdG9wUmV3cml0ZVNlc3Npb24oRG9jdW1lbnRSZXdyaXRlU2Vzc2lvbiBzZXNzaW9uKSB7CgkJaWYgKGZBY3RpdmVSZXdyaXRlU2Vzc2lvbiA9PSBzZXNzaW9uKSB7CgkJCURvY3VtZW50UmV3cml0ZVNlc3Npb25UeXBlIHNlc3Npb25UeXBlID0gc2Vzc2lvbi5nZXRTZXNzaW9uVHlwZSgpOwoJCQlpZiAoRG9jdW1lbnRSZXdyaXRlU2Vzc2lvblR5cGUuU0VRVUVOVElBTCA9PSBzZXNzaW9uVHlwZSB8fCBEb2N1bWVudFJld3JpdGVTZXNzaW9uVHlwZS5TVFJJQ1RMWV9TRVFVRU5USUFMID09IHNlc3Npb25UeXBlKQoJCQkJc3RvcFNlcXVlbnRpYWxSZXdyaXRlKCk7CgoJCQlzdG9wUmV3cml0ZVNlc3Npb25PblBhcnRpdGlvbmVycyhzZXNzaW9uKTsKCgkJCUlMaW5lVHJhY2tlciB0cmFja2VyID0gZ2V0VHJhY2tlcigpOwoJCQlpZiAodHJhY2tlciBpbnN0YW5jZW9mIElMaW5lVHJhY2tlckV4dGVuc2lvbikgewoJCQkJSUxpbmVUcmFja2VyRXh0ZW5zaW9uIGV4dGVuc2lvbiA9IChJTGluZVRyYWNrZXJFeHRlbnNpb24pIHRyYWNrZXI7CgkJCQlleHRlbnNpb24uc3RvcFJld3JpdGVTZXNzaW9uKHNlc3Npb24sIGdldCgpKTsKCQkJfQoKCQkJRG9jdW1lbnRSZXdyaXRlU2Vzc2lvbkV2ZW50IGV2ZW50ID0gbmV3IERvY3VtZW50UmV3cml0ZVNlc3Npb25FdmVudCh0aGlzLCBzZXNzaW9uLCBEb2N1bWVudFJld3JpdGVTZXNzaW9uRXZlbnQuU0VTU0lPTl9TVE9QKTsKCQkJZmlyZURvY3VtZW50UmV3cml0ZVNlc3Npb25FdmVudChldmVudCk7CgkJCWZBY3RpdmVSZXdyaXRlU2Vzc2lvbiA9IG51bGw7CgkJfQoJfQoKCS8qKgoJICogU3RvcHMgdGhlIGdpdmVuIHJld3JpdGUgc2Vzc2lvbi4KCSAqCgkgKiBAcGFyYW0gc2Vzc2lvbiB0aGUgcmV3cml0ZSBzZXNzaW9uCgkgKiBAc2luY2UgMi4wCgkgKi8KCWZpbmFsIHZvaWQgc3RvcFJld3JpdGVTZXNzaW9uT25QYXJ0aXRpb25lcnMoRG9jdW1lbnRSZXdyaXRlU2Vzc2lvbiBzZXNzaW9uKSB7CgkJaWYgKGZEb2N1bWVudFBhcnRpdGlvbmVycyAhPSBudWxsKSB7CgkJCURvY3VtZW50UGFydGl0aW9uaW5nQ2hhbmdlZEV2ZW50IGV2ZW50PSBuZXcgRG9jdW1lbnRQYXJ0aXRpb25pbmdDaGFuZ2VkRXZlbnQodGhpcyk7CgkJCUl0ZXJhdG9yIGU9IGZEb2N1bWVudFBhcnRpdGlvbmVycy5rZXlTZXQoKS5pdGVyYXRvcigpOwoJCQl3aGlsZSAoZS5oYXNOZXh0KCkpIHsKCQkJCVN0cmluZyBwYXJ0aXRpb25pbmc9IChTdHJpbmcpIGUubmV4dCgpOwoJCQkJSURvY3VtZW50UGFydGl0aW9uZXIgcGFydGl0aW9uZXI9IChJRG9jdW1lbnRQYXJ0aXRpb25lcikgZkRvY3VtZW50UGFydGl0aW9uZXJzLmdldChwYXJ0aXRpb25pbmcpOwoJCQkJaWYgKHBhcnRpdGlvbmVyIGluc3RhbmNlb2YgSURvY3VtZW50UGFydGl0aW9uZXJFeHRlbnNpb24zKSB7CgkJCQkJSURvY3VtZW50UGFydGl0aW9uZXJFeHRlbnNpb24zIGV4dGVuc2lvbj0gKElEb2N1bWVudFBhcnRpdGlvbmVyRXh0ZW5zaW9uMykgcGFydGl0aW9uZXI7CgkJCQkJZXh0ZW5zaW9uLnN0b3BSZXdyaXRlU2Vzc2lvbihzZXNzaW9uKTsKCQkJCQlldmVudC5zZXRQYXJ0aXRpb25DaGFuZ2UocGFydGl0aW9uaW5nLCAwLCBnZXRMZW5ndGgoKSk7CgkJCQl9CgkJCX0KCQkJaWYgKCFldmVudC5pc0VtcHR5KCkpCgkJCQlmaXJlRG9jdW1lbnRQYXJ0aXRpb25pbmdDaGFuZ2VkKGV2ZW50KTsKCQl9Cgl9CgoJLyoKCSAqIChub24tSmF2YWRvYykKCSAqIAoJICogQHNlZSBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklEb2N1bWVudEV4dGVuc2lvbjQjZ2V0QWN0aXZlUmV3cml0ZVNlc3Npb24oKQoJICovCglwdWJsaWMgRG9jdW1lbnRSZXdyaXRlU2Vzc2lvbiBnZXRBY3RpdmVSZXdyaXRlU2Vzc2lvbigpIHsKCQlyZXR1cm4gZkFjdGl2ZVJld3JpdGVTZXNzaW9uOwoJfQoKCS8qCgkgKiAobm9uLUphdmFkb2MpCgkgKiAKCSAqIEBzZWUgb3JnLmVjbGlwc2UuamZhY2UudGV4dC5JRG9jdW1lbnRFeHRlbnNpb240I2FkZERvY3VtZW50UmV3cml0ZVNlc3Npb25MaXN0ZW5lcihvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklEb2N1bWVudFJld3JpdGVTZXNzaW9uTGlzdGVuZXIpCgkgKi8KCXB1YmxpYyB2b2lkIGFkZERvY3VtZW50UmV3cml0ZVNlc3Npb25MaXN0ZW5lcihJRG9jdW1lbnRSZXdyaXRlU2Vzc2lvbkxpc3RlbmVyIGxpc3RlbmVyKSB7CgkJc3luY2hyb25pemVkIChsaXN0ZW5lckxvY2spIHsKCQkJQXNzZXJ0LmlzTm90TnVsbChsaXN0ZW5lcik7CgkJCWlmIChmRG9jdW1lbnRSZXdyaXRlU2Vzc2lvbkxpc3RlbmVycyA9PSBudWxsKSB7CgkJCQlmRG9jdW1lbnRSZXdyaXRlU2Vzc2lvbkxpc3RlbmVycyA9IG5ldyBBcnJheUxpc3QoMSk7CgkJCX0KCQkJaWYgKCFmRG9jdW1lbnRSZXdyaXRlU2Vzc2lvbkxpc3RlbmVycy5jb250YWlucyhsaXN0ZW5lcikpCgkJCQlmRG9jdW1lbnRSZXdyaXRlU2Vzc2lvbkxpc3RlbmVycy5hZGQobGlzdGVuZXIpOwoJCX0KCX0KCgkvKgoJICogKG5vbi1KYXZhZG9jKQoJICogCgkgKiBAc2VlIG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSURvY3VtZW50RXh0ZW5zaW9uNCNyZW1vdmVEb2N1bWVudFJld3JpdGVTZXNzaW9uTGlzdGVuZXIob3JnLmVjbGlwc2UuamZhY2UudGV4dC5JRG9jdW1lbnRSZXdyaXRlU2Vzc2lvbkxpc3RlbmVyKQoJICovCglwdWJsaWMgdm9pZCByZW1vdmVEb2N1bWVudFJld3JpdGVTZXNzaW9uTGlzdGVuZXIoSURvY3VtZW50UmV3cml0ZVNlc3Npb25MaXN0ZW5lciBsaXN0ZW5lcikgewoJCXN5bmNocm9uaXplZCAobGlzdGVuZXJMb2NrKSB7CgoJCQlBc3NlcnQuaXNOb3ROdWxsKGxpc3RlbmVyKTsKCQkJaWYgKGZEb2N1bWVudFJld3JpdGVTZXNzaW9uTGlzdGVuZXJzICE9IG51bGwpCgkJCQlmRG9jdW1lbnRSZXdyaXRlU2Vzc2lvbkxpc3RlbmVycy5yZW1vdmUobGlzdGVuZXIpOwoJCX0KCX0KCgkvKgoJICogKG5vbi1KYXZhZG9jKQoJICogCgkgKiBAc2VlIG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSURvY3VtZW50RXh0ZW5zaW9uNCNyZXBsYWNlKGludCwgaW50LAoJICogICAgICBqYXZhLmxhbmcuU3RyaW5nLCBsb25nKQoJICovCglwdWJsaWMgdm9pZCByZXBsYWNlKGludCBvZmZzZXQsIGludCBsZW5ndGgsIFN0cmluZyB0ZXh0LCBsb25nIG1vZGlmaWNhdGlvblN0YW1wKSB0aHJvd3MgQmFkTG9jYXRpb25FeGNlcHRpb24gewoJCXJlcGxhY2VUZXh0KHRoaXMsIG9mZnNldCwgbGVuZ3RoLCB0ZXh0KTsKCQlmTW9kaWZpY2F0aW9uU3RhbXAgPSBtb2RpZmljYXRpb25TdGFtcDsKCX0KCgkvKgoJICogKG5vbi1KYXZhZG9jKQoJICogCgkgKiBAc2VlIG9yZy5lY2xpcHNlLmpmYWNlLnRleHQuSURvY3VtZW50RXh0ZW5zaW9uNCNzZXQoamF2YS5sYW5nLlN0cmluZywKCSAqICAgICAgbG9uZykKCSAqLwoJcHVibGljIHZvaWQgc2V0KFN0cmluZyB0ZXh0LCBsb25nIG1vZGlmaWNhdGlvblN0YW1wKSB7CgkJLy8gYnVnIDE1MTA2OSAtIG92ZXJ3cml0ZSByZWFkIG9ubHkgcmVnaW9ucyB3aGVuIHNldHRpbmcgZW50aXJlIGRvY3VtZW50CgkJIHJlcGxhY2VUZXh0KG51bGwsIDAsIGdldExlbmd0aCgpLCB0ZXh0LCB0cnVlKTsKCgkJZk1vZGlmaWNhdGlvblN0YW1wID0gbW9kaWZpY2F0aW9uU3RhbXA7Cgl9CgoJLyoKCSAqIChub24tSmF2YWRvYykKCSAqIAoJICogQHNlZSBvcmcuZWNsaXBzZS5qZmFjZS50ZXh0LklEb2N1bWVudEV4dGVuc2lvbjQjZ2V0TW9kaWZpY2F0aW9uU3RhbXAoKQoJICovCglwdWJsaWMgbG9uZyBnZXRNb2RpZmljYXRpb25TdGFtcCgpIHsKCQlyZXR1cm4gZk1vZGlmaWNhdGlvblN0YW1wOwoJfQoKCS8qKgoJICogRmlyZXMgYW4gZXZlbnQsIGFzIHNwZWNpZmllZCwgdG8gdGhlIGFzc29jaWF0ZWQgbGlzdGVuZXJzLgoJICogCgkgKiBAcGFyYW0gZXZlbnQKCSAqICAgICAgICAgICAgVGhlIGV2ZW50IHRvIGZpcmUsIGVpdGhlciBhIHN0YXJ0IG9yIHN0b3AgZXZlbnQuCgkgKi8KCXByaXZhdGUgdm9pZCBmaXJlRG9jdW1lbnRSZXdyaXRlU2Vzc2lvbkV2ZW50KERvY3VtZW50UmV3cml0ZVNlc3Npb25FdmVudCBldmVudCkgewoJCWlmIChmRG9jdW1lbnRSZXdyaXRlU2Vzc2lvbkxpc3RlbmVycyA9PSBudWxsIHx8IGZEb2N1bWVudFJld3JpdGVTZXNzaW9uTGlzdGVuZXJzLnNpemUoKSA9PSAwKQoJCQlyZXR1cm47CgoJCUxpc3QgbGlzdCA9IG5ldyBBcnJheUxpc3QoZkRvY3VtZW50UmV3cml0ZVNlc3Npb25MaXN0ZW5lcnMpOwoJCUl0ZXJhdG9yIGUgPSBsaXN0Lml0ZXJhdG9yKCk7CgkJd2hpbGUgKGUuaGFzTmV4dCgpKSB7CgkJCUlEb2N1bWVudFJld3JpdGVTZXNzaW9uTGlzdGVuZXIgbCA9IChJRG9jdW1lbnRSZXdyaXRlU2Vzc2lvbkxpc3RlbmVyKSBlLm5leHQoKTsKCQkJbC5kb2N1bWVudFJld3JpdGVTZXNzaW9uQ2hhbmdlZChldmVudCk7CgkJfQoJfQp9Cg==