LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogQ29weXJpZ2h0IChjKSAyMDAzLCAyMDA0IElCTSBDb3Jwb3JhdGlvbiBhbmQgb3RoZXJzLgogKiBBbGwgcmlnaHRzIHJlc2VydmVkLiBUaGlzIHByb2dyYW0gYW5kIHRoZSBhY2NvbXBhbnlpbmcgbWF0ZXJpYWxzCiAqIGFyZSBtYWRlIGF2YWlsYWJsZSB1bmRlciB0aGUgdGVybXMgb2YgdGhlIENvbW1vbiBQdWJsaWMgTGljZW5zZSB2MS4wCiAqIHdoaWNoIGFjY29tcGFuaWVzIHRoaXMgZGlzdHJpYnV0aW9uLCBhbmQgaXMgYXZhaWxhYmxlIGF0CiAqIGh0dHA6Ly93d3cuZWNsaXBzZS5vcmcvbGVnYWwvY3BsLXYxMC5odG1sCqAqCiAqIENvbnRyaWJ1dG9yczoKICogICAgSUJNIC0gSW5pdGlhbCBBUEkgYW5kIGltcGxlbWVudGF0aW9uCiAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLwpwYWNrYWdlIG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIudWkuaW50ZXJuYWwuZWRpdG9yOwoKaW1wb3J0IGphdmEuYmVhbnMuUHJvcGVydHlDaGFuZ2VFdmVudDsKaW1wb3J0IGphdmEuYmVhbnMuUHJvcGVydHlDaGFuZ2VMaXN0ZW5lcjsKaW1wb3J0IGphdmEudXRpbC4qOwppbXBvcnQgamF2YS51dGlsLkxpc3Q7CgppbXBvcnQgb3JnLmVjbGlwc2UuY29yZS5yZXNvdXJjZXMuSUZpbGU7CmltcG9ydCBvcmcuZWNsaXBzZS5jb3JlLnJlc291cmNlcy5JTWFya2VyOwppbXBvcnQgb3JnLmVjbGlwc2UuY29yZS5ydW50aW1lLio7CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS5hY3Rpb24uKjsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLmRpYWxvZ3MuSURpYWxvZ0NvbnN0YW50czsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLmRpYWxvZ3MuTWVzc2FnZURpYWxvZzsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLnZpZXdlcnMuSUxhYmVsUHJvdmlkZXI7CmltcG9ydCBvcmcuZWNsaXBzZS5zd3QuZXZlbnRzLio7CmltcG9ydCBvcmcuZWNsaXBzZS5zd3Qud2lkZ2V0cy4qOwppbXBvcnQgb3JnLmVjbGlwc2UudWkuKjsKaW1wb3J0IG9yZy5lY2xpcHNlLnVpLnBhcnQuTXVsdGlQYWdlRWRpdG9yUGFydDsKCmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc2VydmVyLmNvcmUuKjsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIudWkuU2VydmVyVUlDb3JlOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNlcnZlci51aS5lZGl0b3IuKjsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIudWkuaW50ZXJuYWwuKjsKLyoqCiAqIEEgbXVsdGktcGFnZSBzZXJ2ZXIgcmVzb3VyY2UgZWRpdG9yLgogKi8KcHVibGljIGNsYXNzIFNlcnZlckVkaXRvciBleHRlbmRzIE11bHRpUGFnZUVkaXRvclBhcnQgewoJLyoqCgkgKiBJbnRlcm5hbCBwYXJ0IGFuZCBzaGVsbCBhY3RpdmF0aW9uIGxpc3RlbmVyCgkgKi8KCWNsYXNzIEFjdGl2YXRpb25MaXN0ZW5lciBleHRlbmRzIFNoZWxsQWRhcHRlciBpbXBsZW1lbnRzIElQYXJ0TGlzdGVuZXIgewoJCXByaXZhdGUgSVdvcmtiZW5jaFBhcnQgZkFjdGl2ZVBhcnQ7CgkJcHJpdmF0ZSBib29sZWFuIGZJc0hhbmRsaW5nQWN0aXZhdGlvbiA9IGZhbHNlOwoJCQoJCXB1YmxpYyB2b2lkIHBhcnRBY3RpdmF0ZWQoSVdvcmtiZW5jaFBhcnQgcGFydCkgewoJCQlmQWN0aXZlUGFydCA9IHBhcnQ7CgkJCWhhbmRsZUFjdGl2YXRpb24oKTsKCQl9CgoJCXB1YmxpYyB2b2lkIHBhcnRCcm91Z2h0VG9Ub3AoSVdvcmtiZW5jaFBhcnQgcGFydCkgewoJCQkvLyBkbyBub3RoaW5nCgkJfQoKCQlwdWJsaWMgdm9pZCBwYXJ0Q2xvc2VkKElXb3JrYmVuY2hQYXJ0IHBhcnQpIHsKCQkJLy8gZG8gbm90aGluZwoJCX0KCgkJcHVibGljIHZvaWQgcGFydERlYWN0aXZhdGVkKElXb3JrYmVuY2hQYXJ0IHBhcnQpIHsKCQkJZkFjdGl2ZVBhcnQgPSBudWxsOwoJCX0KCgkJcHVibGljIHZvaWQgcGFydE9wZW5lZChJV29ya2JlbmNoUGFydCBwYXJ0KSB7CgkJCS8vIGRvIG5vdGhpbmcKCQl9CgoJCXB1YmxpYyB2b2lkIHNoZWxsQWN0aXZhdGVkKFNoZWxsRXZlbnQgZSkgewoJCQloYW5kbGVBY3RpdmF0aW9uKCk7CgkJfQoKCQlwcml2YXRlIHZvaWQgaGFuZGxlQWN0aXZhdGlvbigpIHsKCQkJaWYgKGZJc0hhbmRsaW5nQWN0aXZhdGlvbikKCQkJCXJldHVybjsKCQkJCgkJCWlmIChmQWN0aXZlUGFydCA9PSBTZXJ2ZXJFZGl0b3IudGhpcykgewoJCQkJZklzSGFuZGxpbmdBY3RpdmF0aW9uID0gdHJ1ZTsKCQkJCXRyeSB7CgkJCQkJY2hlY2tSZXNvdXJjZVN0YXRlKCk7CgkJCQl9IGZpbmFsbHkgewoJCQkJCWZJc0hhbmRsaW5nQWN0aXZhdGlvbj0gZmFsc2U7CgkJCQl9CgkJCX0KCQl9Cgl9CgkKCWNsYXNzIExpZmVjeWNsZUxpc3RlbmVyIGltcGxlbWVudHMgSVNlcnZlckxpZmVjeWNsZUxpc3RlbmVyIHsKCQlwdWJsaWMgdm9pZCBzZXJ2ZXJBZGRlZChJU2VydmVyIG9sZFNlcnZlcikgewoJCQkvLyBkbyBub3RoaW5nCgkJfQoJCXB1YmxpYyB2b2lkIHNlcnZlckNoYW5nZWQoSVNlcnZlciBvbGRTZXJ2ZXIpIHsKCQkJLy8gZG8gbm90aGluZwoJCX0KCQlwdWJsaWMgdm9pZCBzZXJ2ZXJSZW1vdmVkKElTZXJ2ZXIgb2xkU2VydmVyKSB7CgkJCWlmIChvbGRTZXJ2ZXIuZXF1YWxzKHNlcnZlcikgJiYgIWlzRGlydHkoKSkKCQkJCWNsb3NlRWRpdG9yKCk7CgkJfQoJfQoKCXByb3RlY3RlZCBJU2VydmVyV29ya2luZ0NvcHkgc2VydmVyOwoJcHJvdGVjdGVkIFN0cmluZyBzZXJ2ZXJJZDsKCglwcm90ZWN0ZWQgR2xvYmFsQ29tbWFuZE1hbmFnZXIgY29tbWFuZE1hbmFnZXI7CgoJcHJvdGVjdGVkIFByb3BlcnR5Q2hhbmdlTGlzdGVuZXIgbGlzdGVuZXI7CgoJcHJvdGVjdGVkIElBY3Rpb24gdW5kb0FjdGlvbjsKCXByb3RlY3RlZCBJQWN0aW9uIHJlZG9BY3Rpb247CgkKCXByb3RlY3RlZCBUZXh0QWN0aW9uIGN1dEFjdGlvbjsKCXByb3RlY3RlZCBUZXh0QWN0aW9uIGNvcHlBY3Rpb247Cglwcm90ZWN0ZWQgVGV4dEFjdGlvbiBwYXN0ZUFjdGlvbjsKCXByb3RlY3RlZCBib29sZWFuIHVwZGF0aW5nQWN0aW9uczsKCQoJcHJvdGVjdGVkIElBY3Rpb25bXSBlZGl0b3JBY3Rpb25zOwoKCXByb3RlY3RlZCBqYXZhLnV0aWwuTGlzdCBzZXJ2ZXJQYWdlczsKCQoJLy8gb24gZm9jdXMgY2hhbmdlIGZsYWcKCXByb3RlY3RlZCBib29sZWFuIHJlc291cmNlRGVsZXRlZDsKCQoJLy8gaW5wdXQgZ2l2ZW4gdG8gdGhlIGNvbnRhaW5lZCBwYWdlcwoJcHJvdGVjdGVkIElTZXJ2ZXJFZGl0b3JQYXJ0SW5wdXQgZWRpdG9yUGFydElucHV0OwoJCgkvLyBzdGF0dXMgbGluZSBhbmQgc3RhdHVzCglwcm90ZWN0ZWQgSVN0YXR1c0xpbmVNYW5hZ2VyIHN0YXR1czsKCXByb3RlY3RlZCBTdGF0dXNMaW5lQ29udHJpYnV0aW9uSXRlbSBzdGF0dXNJdGVtOwoJCglwcml2YXRlIEFjdGl2YXRpb25MaXN0ZW5lciBhY3RpdmF0aW9uTGlzdGVuZXIgPSBuZXcgQWN0aXZhdGlvbkxpc3RlbmVyKCk7Cglwcm90ZWN0ZWQgTGlmZWN5Y2xlTGlzdGVuZXIgcmVzb3VyY2VMaXN0ZW5lcjsKCQoJLy8gVXNlZCBmb3IgZGlzYWJsaW5nIHJlc291cmNlIGNoYW5nZSBjaGVjayB3aGVuIHNhdmluZyB0aHJvdWdoIGVkaXRvci4KCXByb3RlY3RlZCBib29sZWFuIGlzU2F2aW5nID0gZmFsc2U7CgoJLyoqCgkgKiBTZXJ2ZXJFZGl0b3IgY29uc3RydWN0b3IgY29tbWVudC4KCSAqLwoJcHVibGljIFNlcnZlckVkaXRvcigpIHsKCQlzdXBlcigpOwoJCQoJCUlTaGFyZWRJbWFnZXMgc2hhcmVkSW1hZ2VzID0gUGxhdGZvcm1VSS5nZXRXb3JrYmVuY2goKS5nZXRTaGFyZWRJbWFnZXMoKTsKCgkJdW5kb0FjdGlvbiA9IG5ldyBBY3Rpb24oKSB7CgkJCXB1YmxpYyB2b2lkIHJ1bigpIHsKCQkJCWdldENvbW1hbmRNYW5hZ2VyKCkudW5kbyhzZXJ2ZXJJZCk7CgkJCX0KCQl9OwoJCXVuZG9BY3Rpb24uc2V0RW5hYmxlZChmYWxzZSk7CgkJdW5kb0FjdGlvbi5zZXRJbWFnZURlc2NyaXB0b3Ioc2hhcmVkSW1hZ2VzLmdldEltYWdlRGVzY3JpcHRvcihJU2hhcmVkSW1hZ2VzLklNR19UT09MX1VORE8pKTsKCQkvL3VuZG9BY3Rpb24uc2V0SG92ZXJJbWFnZURlc2NyaXB0b3Ioc2hhcmVkSW1hZ2VzLmdldEltYWdlRGVzY3JpcHRvcihJU2hhcmVkSW1hZ2VzLklNR19UT09MX1VORE9fSE9WRVIpKTsKCQkvL3VuZG9BY3Rpb24uc2V0RGlzYWJsZWRJbWFnZURlc2NyaXB0b3Ioc2hhcmVkSW1hZ2VzLmdldEltYWdlRGVzY3JpcHRvcihJU2hhcmVkSW1hZ2VzLklNR19UT09MX1VORE9fRElTQUJMRUQpKTsKCQoJCXJlZG9BY3Rpb24gPSBuZXcgQWN0aW9uKCkgewoJCQlwdWJsaWMgdm9pZCBydW4oKSB7CgkJCQlnZXRDb21tYW5kTWFuYWdlcigpLnJlZG8oc2VydmVySWQpOwoJCQl9CgkJfTsKCQlyZWRvQWN0aW9uLnNldEVuYWJsZWQoZmFsc2UpOwoJCXJlZG9BY3Rpb24uc2V0SW1hZ2VEZXNjcmlwdG9yKHNoYXJlZEltYWdlcy5nZXRJbWFnZURlc2NyaXB0b3IoSVNoYXJlZEltYWdlcy5JTUdfVE9PTF9SRURPKSk7CgkJLy9yZWRvQWN0aW9uLnNldEhvdmVySW1hZ2VEZXNjcmlwdG9yKHNoYXJlZEltYWdlcy5nZXRJbWFnZURlc2NyaXB0b3IoSVNoYXJlZEltYWdlcy5JTUdfVE9PTF9SRURPX0hPVkVSKSk7CgkJLy9yZWRvQWN0aW9uLnNldERpc2FibGVkSW1hZ2VEZXNjcmlwdG9yKHNoYXJlZEltYWdlcy5nZXRJbWFnZURlc2NyaXB0b3IoSVNoYXJlZEltYWdlcy5JTUdfVE9PTF9SRURPX0RJU0FCTEVEKSk7Cgl9CgoJLyoqCgkgKiBDbG9zZSB0aGUgZWRpdG9yIGNvcnJlY3RseS4KCSAqLwoJcHJvdGVjdGVkIHZvaWQgY2xvc2VFZGl0b3IoKSB7CgkJRGlzcGxheS5nZXREZWZhdWx0KCkuYXN5bmNFeGVjKG5ldyBSdW5uYWJsZSgpIHsKCQkJcHVibGljIHZvaWQgcnVuKCkgewoJCQkJZ2V0RWRpdG9yU2l0ZSgpLmdldFBhZ2UoKS5jbG9zZUVkaXRvcihTZXJ2ZXJFZGl0b3IudGhpcywgZmFsc2UpOwoJCQl9CgkJfSk7Cgl9CgkKCXByb3RlY3RlZCB2b2lkIGNyZWF0ZUFjdGlvbnMoKSB7CgkJTGlzdCBhY3Rpb25MaXN0ID0gbmV3IEFycmF5TGlzdCgpOwoJCQoJCS8vIGFkZCBzZXJ2ZXIgYWN0aW9ucwoJCWlmIChzZXJ2ZXIgIT0gbnVsbCAmJiBzZXJ2ZXIuZ2V0U2VydmVyVHlwZSgpICE9IG51bGwpIHsKCQkJSXRlcmF0b3IgaXRlcmF0b3IgPSBTZXJ2ZXJFZGl0b3JDb3JlLmdldFNlcnZlckVkaXRvckFjdGlvbkZhY3RvcmllcygpLml0ZXJhdG9yKCk7CgkJCVN0cmluZyBpZCA9IHNlcnZlci5nZXRTZXJ2ZXJUeXBlKCkuZ2V0SWQoKTsKCQkJd2hpbGUgKGl0ZXJhdG9yLmhhc05leHQoKSkgewoJCQkJU2VydmVyRWRpdG9yQWN0aW9uRmFjdG9yeSBmYWN0b3J5ID0gKFNlcnZlckVkaXRvckFjdGlvbkZhY3RvcnkpIGl0ZXJhdG9yLm5leHQoKTsKCQkJCWlmIChmYWN0b3J5LnN1cHBvcnRzU2VydmVyRWxlbWVudFR5cGUoaWQpICYmIGZhY3Rvcnkuc2hvdWxkRGlzcGxheShzZXJ2ZXIpKQoJCQkJCWFjdGlvbkxpc3QuYWRkKGZhY3RvcnkuY3JlYXRlQWN0aW9uKGdldEVkaXRvclNpdGUoKSwgZWRpdG9yUGFydElucHV0KSk7CgkJCX0KCQl9CgoJCWVkaXRvckFjdGlvbnMgPSBuZXcgSUFjdGlvblthY3Rpb25MaXN0LnNpemUoKV07CgkJYWN0aW9uTGlzdC50b0FycmF5KGVkaXRvckFjdGlvbnMpOwoJfQoKCS8qKgoJICogQ3JlYXRlcyB0aGUgcGFnZXMgb2YgdGhpcyBtdWx0aS1wYWdlIGVkaXRvci4KCSAqIDxwPgoJICogU3ViY2xhc3NlcyBvZiA8Y29kZT5NdWx0aVBhZ2VFZGl0b3I8L2NvZGU+IG11c3QgaW1wbGVtZW50IHRoaXMgbWV0aG9kLgoJICogPC9wPgoJICovCglwcm90ZWN0ZWQgdm9pZCBjcmVhdGVQYWdlcygpIHsJCgkJdHJ5IHsKCQkJaW50IGluZGV4ID0gMDsKCQkJc2VydmVyUGFnZXMgPSBuZXcgQXJyYXlMaXN0KCk7CgkJCQoJCQkvLyBhZGQgZWRpdG9yIHBhZ2VzCgkJCWludCBwYWdlQ291bnQgPSAwOwoJCQkKCQkJU3RyaW5nIHNlcnZlclR5cGVJZCA9IG51bGw7CgkJCWlmIChzZXJ2ZXIgIT0gbnVsbCAmJiBzZXJ2ZXIuZ2V0U2VydmVyVHlwZSgpICE9IG51bGwpCgkJCQlzZXJ2ZXJUeXBlSWQgPSBzZXJ2ZXIuZ2V0U2VydmVyVHlwZSgpLmdldElkKCk7CgkJCQoJCQlJdGVyYXRvciBpdGVyYXRvciA9IFNlcnZlckVkaXRvckNvcmUuZ2V0U2VydmVyRWRpdG9yUGFnZUZhY3RvcmllcygpLml0ZXJhdG9yKCk7CgkJCXdoaWxlIChpdGVyYXRvci5oYXNOZXh0KCkpIHsKCQkJCUlTZXJ2ZXJFZGl0b3JQYXJ0RmFjdG9yeSBmYWN0b3J5ID0gKElTZXJ2ZXJFZGl0b3JQYXJ0RmFjdG9yeSkgaXRlcmF0b3IubmV4dCgpOwoJCQkJaWYgKHNlcnZlclR5cGVJZCAhPSBudWxsICYmIGZhY3Rvcnkuc3VwcG9ydHNUeXBlKHNlcnZlclR5cGVJZCkgJiYgZmFjdG9yeS5zaG91bGRDcmVhdGVQYWdlKHNlcnZlcikpIHsKCQkJCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICJBZGRpbmcgcGFnZTogIiArIGZhY3RvcnkuZ2V0SWQoKSArICIgIiArIGVkaXRvclBhcnRJbnB1dCk7CgkJCQkJdHJ5IHsKCQkJCQkJSUVkaXRvclBhcnQgcGFnZSA9IGZhY3RvcnkuY3JlYXRlUGFnZSgpOwoJCQkJCQlpZiAocGFnZSBpbnN0YW5jZW9mIFNlcnZlckVkaXRvclBhcnQpIHsKCQkJCQkJCVNlcnZlckVkaXRvclBhcnQgc3JlcCA9IChTZXJ2ZXJFZGl0b3JQYXJ0KSBwYWdlOwoJCQkJCQkJc3JlcC5zZXRQYWdlRmFjdG9yeShmYWN0b3J5KTsKCQkJCQkJfQoJCQkJCQlpbmRleCA9IGFkZFBhZ2UocGFnZSwgZWRpdG9yUGFydElucHV0KTsKCQkJCQkJc2VydmVyUGFnZXMuYWRkKHBhZ2UpOwoJCgkJCQkJCXNldFBhZ2VUZXh0KGluZGV4LCBmYWN0b3J5LmdldE5hbWUoKSk7CgkJCQkKCQkJCQkJcGFnZUNvdW50ICsrOwoJCQkJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCQkJCVRyYWNlLnRyYWNlKFRyYWNlLlNFVkVSRSwgIkNvdWxkIG5vdCBkaXNwbGF5IGVkaXRvciBwYWdlICIgKyBmYWN0b3J5LmdldElkKCksIGUpOwoJCQkJCX0KCQkJCX0KCQkJfQoJCQkKCQkJc2V0QWN0aXZlUGFnZSgwKTsKCQkJCgkJCS8vIHJlZ2lzdGVyIGZvciBldmVudHMgdGhhdCBtaWdodCBjaGFuZ2UgdGhlIGN1dC9jb3B5L3Bhc3RlIGFjdGlvbnMKCQkJaW50IGNvdW50ID0gZ2V0UGFnZUNvdW50KCk7CgkJCWZvciAoaW50IGkgPSAwOyBpIDwgY291bnQ7IGkrKykgewoJCQkJQ29udHJvbCBjb250cm9sID0gZ2V0Q29udHJvbChpKTsKCQkJCXJlZ2lzdGVyRXZlbnRzKGNvbnRyb2wpOwoJCQl9CgkJCXVwZGF0ZUFjdGlvbnMoKTsKCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQlUcmFjZS50cmFjZSgiRXJyb3IgY3JlYXRpbmcgc2VydmVyIGVkaXRvciBwYWdlcyIsIGUpOwoJCX0KCX0KCglwdWJsaWMgdm9pZCBkaXNwb3NlKCkgewoJCWlmIChhY3RpdmF0aW9uTGlzdGVuZXIgIT0gbnVsbCkgewoJCQlJV29ya2JlbmNoV2luZG93IHdpbmRvdyA9IGdldFNpdGUoKS5nZXRXb3JrYmVuY2hXaW5kb3coKTsKCQkJd2luZG93LmdldFBhcnRTZXJ2aWNlKCkucmVtb3ZlUGFydExpc3RlbmVyKGFjdGl2YXRpb25MaXN0ZW5lcik7CgkJCVNoZWxsIHNoZWxsID0gd2luZG93LmdldFNoZWxsKCk7CgkJCWlmIChzaGVsbCAhPSBudWxsICYmICFzaGVsbC5pc0Rpc3Bvc2VkKCkpCgkJCQlzaGVsbC5yZW1vdmVTaGVsbExpc3RlbmVyKGFjdGl2YXRpb25MaXN0ZW5lcik7CgkJCWFjdGl2YXRpb25MaXN0ZW5lciA9IG51bGw7CgkJfQoJCQoJCWlmIChyZXNvdXJjZUxpc3RlbmVyICE9IG51bGwpCgkJCVNlcnZlckNvcmUucmVtb3ZlU2VydmVyTGlmZWN5Y2xlTGlzdGVuZXIocmVzb3VyY2VMaXN0ZW5lcik7CgoJCXN1cGVyLmRpc3Bvc2UoKTsKCQlpZiAoY29tbWFuZE1hbmFnZXIgIT0gbnVsbCkKCQkJY29tbWFuZE1hbmFnZXIucmVtb3ZlUHJvcGVydHlDaGFuZ2VMaXN0ZW5lcihsaXN0ZW5lcik7CgoJCWlmIChzZXJ2ZXJJZCAhPSBudWxsKQoJCQljb21tYW5kTWFuYWdlci5yZWxlYXNlQ29tbWFuZE1hbmFnZXIoc2VydmVySWQpOwoJfQoKCS8qIChub24tSmF2YWRvYykKCSAqIFNhdmVzIHRoZSBjb250ZW50cyBvZiB0aGlzIGVkaXRvci4KCSAqIDxwPgoJICogU3ViY2xhc3NlcyBtdXN0IG92ZXJyaWRlIHRoaXMgbWV0aG9kIHRvIGltcGxlbWVudCB0aGUgb3Blbi1zYXZlLWNsb3NlIGxpZmVjeWNsZQoJICogZm9yIGFuIGVkaXRvci4gIEZvciBncmVhdGVyIGRldGFpbHMsIHNlZSA8Y29kZT5JRWRpdG9yUGFydDwvY29kZT4KCSAqIDwvcD4KCSAqCgkgKiBAc2VlIElFZGl0b3JQYXJ0CgkgKi8KCXB1YmxpYyB2b2lkIGRvU2F2ZShJUHJvZ3Jlc3NNb25pdG9yIG1vbml0b3IpIHsKCQkvLyBTZXQgdGhlIGlzU2F2aW5nIGZsYWcgdG8gdHJ1ZS4KCQlpc1NhdmluZyA9IHRydWU7CgkJCgkJLy8gY2hlY2sgcGFnZXMgZm9yIGVycm9ycyBmaXJzdAoJCWphdmEudXRpbC5MaXN0IGVycm9ycyA9IG5ldyBBcnJheUxpc3QoKTsKCQlJdGVyYXRvciBpdGVyYXRvciA9IHNlcnZlclBhZ2VzLml0ZXJhdG9yKCk7CgkJaW50IGNvdW50ID0gMDsKCQl3aGlsZSAoaXRlcmF0b3IuaGFzTmV4dCgpKSB7CgkJCUlFZGl0b3JQYXJ0IHBhcnQgPSAoSUVkaXRvclBhcnQpIGl0ZXJhdG9yLm5leHQoKTsKCQkJaWYgKHBhcnQgaW5zdGFuY2VvZiBTZXJ2ZXJFZGl0b3JQYXJ0KSB7CgkJCQlJU3RhdHVzW10gc3RhdHVzMiA9ICgoU2VydmVyRWRpdG9yUGFydCkgcGFydCkuZ2V0U2F2ZVN0YXR1cygpOwoJCQkJaWYgKHN0YXR1czIgIT0gbnVsbCkgewoJCQkJCWludCBzaXplID0gc3RhdHVzMi5sZW5ndGg7CgkJCQkJZm9yIChpbnQgaSA9IDA7IGkgPCBzaXplOyBpKyspCgkJCQkJCWVycm9ycy5hZGQoIlsiICsgZ2V0UGFnZVRleHQoY291bnQpICsgIl0gIiArIHN0YXR1czJbaV0uZ2V0TWVzc2FnZSgpKTsKCQkJCX0KCQkJfQoJCQljb3VudCArKzsKCQl9CgkJaWYgKCFlcnJvcnMuaXNFbXB0eSgpKSB7CgkJCVN0cmluZ0J1ZmZlciBzYiA9IG5ldyBTdHJpbmdCdWZmZXIoKTsKCQkJc2IuYXBwZW5kKFNlcnZlclVJUGx1Z2luLmdldFJlc291cmNlKCIlZXJyb3JFZGl0b3JDYW50U2F2ZSIpICsgIlxuIik7CgkJCWl0ZXJhdG9yID0gZXJyb3JzLml0ZXJhdG9yKCk7CgkJCXdoaWxlIChpdGVyYXRvci5oYXNOZXh0KCkpCgkJCQlzYi5hcHBlbmQoIlx0IiArICgoU3RyaW5nKSBpdGVyYXRvci5uZXh0KCkpICsgIlxuIik7CgoJCQlFY2xpcHNlVXRpbC5vcGVuRXJyb3IoZ2V0RWRpdG9yU2l0ZSgpLmdldFNoZWxsKCksIHNiLnRvU3RyaW5nKCkpOwoJCQltb25pdG9yLnNldENhbmNlbGVkKHRydWUpOwoJCQkvLyBSZXNldCB0aGUgaXNTYXZpbmcgZmxhZy4KCQkJaXNTYXZpbmcgPSBmYWxzZTsKCQkJcmV0dXJuOwoJCX0KCQkKCQl0cnkgewoJCQltb25pdG9yID0gUHJvZ3Jlc3NVdGlsLmdldE1vbml0b3JGb3IobW9uaXRvcik7CgkJCWludCB0aWNrcyA9IDIwMDA7CgkJCVN0cmluZyBuYW1lID0gIiI7CgkJCWlmIChzZXJ2ZXIgIT0gbnVsbCkKCQkJCW5hbWUgPSBzZXJ2ZXIuZ2V0TmFtZSgpOwoJCQltb25pdG9yLmJlZ2luVGFzayhTZXJ2ZXJVSVBsdWdpbi5nZXRSZXNvdXJjZSgiJXNhdmluZ1Rhc2siLCBuYW1lKSwgdGlja3MpOwoJCQlpZiAoc2VydmVyICE9IG51bGwpCgkJCQl0aWNrcyAvPSAyOwoKCQkJaWYgKHNlcnZlciAhPSBudWxsKSAgewoJCQkJc2VydmVyLnNhdmUoZmFsc2UsIFByb2dyZXNzVXRpbC5nZXRTdWJNb25pdG9yRm9yKG1vbml0b3IsIHRpY2tzKSk7CgkJCQlnZXRDb21tYW5kTWFuYWdlcigpLnJlc291cmNlU2F2ZWQoc2VydmVySWQpOwoJCQkJY29tbWFuZE1hbmFnZXIudXBkYXRlVGltZXN0YW1wcyhzZXJ2ZXJJZCk7CgkJCX0KCQkJCgkJCUlMYWJlbFByb3ZpZGVyIGxhYmVsUHJvdmlkZXIgPSBTZXJ2ZXJVSUNvcmUuZ2V0TGFiZWxQcm92aWRlcigpOwoJCQlpZiAoc2VydmVyICE9IG51bGwpCgkJCQlzZXRQYXJ0TmFtZShsYWJlbFByb3ZpZGVyLmdldFRleHQoc2VydmVyKSk7CgkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJVHJhY2UudHJhY2UoIkVycm9yIHNhdmluZyBmcm9tIGNvbmZpZ3VyYXRpb24gZWRpdG9yIiwgZSk7CgkKCQkJbW9uaXRvci5zZXRDYW5jZWxlZCh0cnVlKTsKCQoJCQlTdHJpbmcgdGl0bGUgPSBTZXJ2ZXJVSVBsdWdpbi5nZXRSZXNvdXJjZSgiJWVkaXRvclNhdmVFcnJvckRpYWxvZyIpOwoJCQlTdHJpbmcgbWVzc2FnZSA9IFNlcnZlclVJUGx1Z2luLmdldFJlc291cmNlKCIlZWRpdG9yU2F2ZUVycm9yTWVzc2FnZSIsIGUuZ2V0TG9jYWxpemVkTWVzc2FnZSgpKTsKCQkJTWVzc2FnZURpYWxvZy5vcGVuRXJyb3IoZ2V0RWRpdG9yU2l0ZSgpLmdldFNoZWxsKCksIHRpdGxlLCAgbWVzc2FnZSk7CgkJfSBmaW5hbGx5IHsKCQkJbW9uaXRvci5kb25lKCk7CgkJfQoJCS8vIFJlc2V0IHRoZSBpc1NhdmluZyBmbGFnLgoJCWlzU2F2aW5nID0gZmFsc2U7Cgl9CgoJLyogKG5vbi1KYXZhZG9jKQoJICogU2F2ZXMgdGhlIGNvbnRlbnRzIG9mIHRoaXMgZWRpdG9yIHRvIGFub3RoZXIgb2JqZWN0LgoJICogPHA+CgkgKiBTdWJjbGFzc2VzIG11c3Qgb3ZlcnJpZGUgdGhpcyBtZXRob2QgdG8gaW1wbGVtZW50IHRoZSBvcGVuLXNhdmUtY2xvc2UgbGlmZWN5Y2xlCgkgKiBmb3IgYW4gZWRpdG9yLiAgRm9yIGdyZWF0ZXIgZGV0YWlscywgc2VlIDxjb2RlPklFZGl0b3JQYXJ0PC9jb2RlPgoJICogPC9wPgoJICoKCSAqIEBzZWUgSUVkaXRvclBhcnQKCSAqLwoJcHVibGljIHZvaWQgZG9TYXZlQXMoKSB7CgkJLy8gZG8gbm90aGluZwoJfQoKCS8qKgoJICogRmlyZSBhIHByb3BlcnR5IGNoYW5nZSBldmVudC4KCSAqCgkgKiBAcGFyYW0gaSBpbnQKCSAqLwoJcHJvdGVjdGVkIHZvaWQgZmlyZVByb3BlcnR5Q2hhbmdlKGludCBpKSB7CgkJaWYgKGkgPT0gU2VydmVyRWRpdG9yUGFydC5QUk9QX0VSUk9SKQoJCQl1cGRhdGVTdGF0dXNFcnJvcigpOwoJCXN1cGVyLmZpcmVQcm9wZXJ0eUNoYW5nZShpKTsKCX0KCgkvKioKCSAqIAoJICovCglwdWJsaWMgR2xvYmFsQ29tbWFuZE1hbmFnZXIgZ2V0Q29tbWFuZE1hbmFnZXIoKSB7CgkJcmV0dXJuIGNvbW1hbmRNYW5hZ2VyOwoJfQoKCS8qKgoJICogUmV0dXJuIHRoZSByZWRvIGFjdGlvbi4KCSAqCgkgKiBAcmV0dXJuIG9yZy5lY2xpcHNlLmpmYWNlLmFjdGlvbi5BY3Rpb24KCSAqLwoJcHVibGljIElBY3Rpb24gZ2V0UmVkb0FjdGlvbigpIHsKCQlyZXR1cm4gcmVkb0FjdGlvbjsKCX0KCgkvKioKCSAqIFJldHVybiB0aGUgdW5kbyBhY3Rpb24uCgkgKgoJICogQHJldHVybiBvcmcuZWNsaXBzZS5qZmFjZS5hY3Rpb24uQWN0aW9uCgkgKi8KCXB1YmxpYyBJQWN0aW9uIGdldFVuZG9BY3Rpb24oKSB7CgkJcmV0dXJuIHVuZG9BY3Rpb247Cgl9CgoJLyogKG5vbi1KYXZhZG9jKQoJICogU2V0cyB0aGUgY3Vyc29yIGFuZCBzZWxlY3Rpb24gc3RhdGUgZm9yIHRoaXMgZWRpdG9yIHRvIHRoZSBwYXNzYWdlIGRlZmluZWQKCSAqIGJ5IHRoZSBnaXZlbiBtYXJrZXIuCgkgKiA8cD4KCSAqIFN1YmNsYXNzZXMgbWF5IG92ZXJyaWRlLiAgRm9yIGdyZWF0ZXIgZGV0YWlscywgc2VlIDxjb2RlPklFZGl0b3JQYXJ0PC9jb2RlPgoJICogPC9wPgoJICoKCSAqIEBzZWUgSUVkaXRvclBhcnQKCSAqLwoJcHVibGljIHZvaWQgZ290b01hcmtlcihJTWFya2VyIG1hcmtlcikgewoJCS8vIGRvIG5vdGhpbmcKCX0KCgkvKioKCSAqIFVwZGF0ZSB0aGUgY3V0LCBjb3B5LCBhbmQgcGFzdGUgYWN0aW9ucy4KCSAqLwoJcHVibGljIHZvaWQgdXBkYXRlQWN0aW9uc0ltcGwoKSB7CgkJaWYgKHVwZGF0aW5nQWN0aW9ucykKCQkJcmV0dXJuOwoJCQoJCXVwZGF0aW5nQWN0aW9ucyA9IHRydWU7CgkJRGlzcGxheS5nZXREZWZhdWx0KCkuYXN5bmNFeGVjKG5ldyBSdW5uYWJsZSgpIHsKCQkJcHVibGljIHZvaWQgcnVuKCkgewoJCQkJdXBkYXRpbmdBY3Rpb25zID0gZmFsc2U7CgkJCQl1cGRhdGVBY3Rpb25zKCk7CgkJCX0KCQl9KTsKCX0KCgkvKioKCSAqIFVwZGF0ZSB0aGUgY3V0LCBjb3B5LCBhbmQgcGFzdGUgYWN0aW9ucy4KCSAqLwoJcHVibGljIHZvaWQgdXBkYXRlQWN0aW9ucygpIHsKCQljdXRBY3Rpb24udXBkYXRlKCk7CgkJY29weUFjdGlvbi51cGRhdGUoKTsKCQlwYXN0ZUFjdGlvbi51cGRhdGUoKTsKCX0KCQoJLyoqCgkgKiBVcGRhdGUgdGhlIGN1dCwgY29weSwgYW5kIHBhc3RlIGFjdGlvbnMuCgkgKi8KCXByb3RlY3RlZCB2b2lkIHVwZGF0ZVN0YXR1c0xpbmUoKSB7CgkJaWYgKHN0YXR1c0l0ZW0gIT0gbnVsbCkgewoJCQlib29sZWFuIHJlYWRPbmx5ID0gZmFsc2U7CgkJCWlmIChzZXJ2ZXIgIT0gbnVsbCAmJiBjb21tYW5kTWFuYWdlci5pc1JlYWRPbmx5KHNlcnZlcklkKSkKCQkJCXJlYWRPbmx5ID0gdHJ1ZTsKCQkJCgkJCWlmIChyZWFkT25seSkKCQkJCXN0YXR1c0l0ZW0uc2V0VGV4dChTZXJ2ZXJVSVBsdWdpbi5nZXRSZXNvdXJjZSgiJWVkaXRvclJlYWRPbmx5IikpOwoJCQllbHNlCgkJCQlzdGF0dXNJdGVtLnNldFRleHQoU2VydmVyVUlQbHVnaW4uZ2V0UmVzb3VyY2UoIiVlZGl0b3JXcml0YWJsZSIpKTsKCQl9CgoJCWlmIChzdGF0dXMgIT0gbnVsbCkgewoJCQlTdHJpbmdCdWZmZXIgc2IgPSBuZXcgU3RyaW5nQnVmZmVyKCk7CgkJCWJvb2xlYW4gZmlyc3QgPSB0cnVlOwoJCQlpZiAoc2VydmVyICE9IG51bGwpIHsKCQkJCUlGaWxlW10gZmlsZXMgPSBjb21tYW5kTWFuYWdlci5nZXRSZWFkT25seUZpbGVzKHNlcnZlcklkKTsKCQkJCWZvciAoaW50IGkgPSAwOyBpIDwgZmlsZXMubGVuZ3RoOyBpKyspIHsKCQkJCQlpZiAoIWZpcnN0KQoJCQkJCQlzYi5hcHBlbmQoIiwgIik7CgkJCQkJc2IuYXBwZW5kKGZpbGVzW2ldLmdldE5hbWUoKSk7CgkJCQkJZmlyc3QgPSBmYWxzZTsKCQkJCX0KCQkJfQoJCQkvKmlmIChzZXJ2ZXJDb25maWd1cmF0aW9uICE9IG51bGwpIHsKCQkJCUlGaWxlW10gZmlsZXMgPSBjb21tYW5kTWFuYWdlci5nZXRSZWFkT25seUZpbGVzKHNlcnZlckNvbmZpZ3VyYXRpb25JZCk7CgkJCQlmb3IgKGludCBpID0gMDsgaSA8IGZpbGVzLmxlbmd0aDsgaSsrKSB7CgkJCQkJaWYgKCFmaXJzdCkKCQkJCQkJc2IuYXBwZW5kKCIsICIpOwoJCQkJCXNiLmFwcGVuZChmaWxlc1tpXS5nZXROYW1lKCkpOwoJCQkJCWZpcnN0ID0gZmFsc2U7CgkJCQl9CgkJCX0qLwoJCQlpZiAoc2IubGVuZ3RoKCkgPiAxKQoJCQkJc3RhdHVzLnNldE1lc3NhZ2UoU2VydmVyVUlQbHVnaW4uZ2V0UmVzb3VyY2UoIiVlZGl0b3JSZWFkT25seUZpbGVzIiwgc2IudG9TdHJpbmcoKSkpOwoJCQllbHNlCgkJCQlzdGF0dXMuc2V0TWVzc2FnZSgiIik7CgkJfQoJfQoJCgkvKioKCSAqIAoJICovCglwdWJsaWMgdm9pZCB1cGRhdGVTdGF0dXNFcnJvcigpIHsKCQlpZiAoc3RhdHVzID09IG51bGwpCgkJCXJldHVybjsKCgkJU3RyaW5nIGVycm9yID0gbnVsbDsKCQlJRWRpdG9yUGFydCBwYXJ0ID0gZ2V0QWN0aXZlRWRpdG9yKCk7CgkJaWYgKHBhcnQgaW5zdGFuY2VvZiBTZXJ2ZXJFZGl0b3JQYXJ0KQoJCQllcnJvciA9ICgoU2VydmVyRWRpdG9yUGFydCkgcGFydCkuZ2V0RXJyb3JNZXNzYWdlKCk7CgkJCgkJSXRlcmF0b3IgaXRlcmF0b3IgPSBzZXJ2ZXJQYWdlcy5pdGVyYXRvcigpOwoJCWludCBjb3VudCA9IDA7CgkJd2hpbGUgKGVycm9yID09IG51bGwgJiYgaXRlcmF0b3IuaGFzTmV4dCgpKSB7CgkJCXBhcnQgPSAoSUVkaXRvclBhcnQpIGl0ZXJhdG9yLm5leHQoKTsKCQkJaWYgKHBhcnQgaW5zdGFuY2VvZiBTZXJ2ZXJFZGl0b3JQYXJ0KSB7CgkJCQllcnJvciA9ICgoU2VydmVyRWRpdG9yUGFydCkgcGFydCkuZ2V0RXJyb3JNZXNzYWdlKCk7CgkJCQlpZiAoZXJyb3IgIT0gbnVsbCkKCQkJCQllcnJvciA9ICJbIiArIGdldFBhZ2VUZXh0KGNvdW50KSArICJdICIgKyBlcnJvcjsKCQkJfQoJCQljb3VudCArKzsKCQl9CgkJc3RhdHVzLnNldEVycm9yTWVzc2FnZShlcnJvcik7Cgl9CgkKCS8qKgoJICogCgkgKi8KCXByb3RlY3RlZCB2b2lkIHBhZ2VDaGFuZ2UoaW50IG5ld1BhZ2VJbmRleCkgewoJCXN1cGVyLnBhZ2VDaGFuZ2UobmV3UGFnZUluZGV4KTsKCQl1cGRhdGVTdGF0dXNFcnJvcigpOwoJfQoJCgkvKioKCSAqIAoJICovCglwdWJsaWMgdm9pZCBzZXRTdGF0dXMoSVN0YXR1c0xpbmVNYW5hZ2VyIHN0YXR1cywgU3RhdHVzTGluZUNvbnRyaWJ1dGlvbkl0ZW0gaXRlbSkgewoJCXRoaXMuc3RhdHVzID0gc3RhdHVzOwoJCXRoaXMuc3RhdHVzSXRlbSA9IGl0ZW07CgkJdXBkYXRlU3RhdHVzRXJyb3IoKTsKCX0KCQoJLyoqCgkgKiBSZWdpc3RlciBmb3Iga2V5IGFuZCB0cmF2ZXJzYWwgZXZlbnRzIHRvIGVuYWJsZS9kaXNhYmxlIHRoZSBjdXQvY29weS9wYXN0ZSBhY3Rpb25zLgoJICovCglwcm90ZWN0ZWQgdm9pZCByZWdpc3RlckV2ZW50cyhDb250cm9sIGNvbnRyb2wpIHsKCQlpZiAoY29udHJvbCA9PSBudWxsKQoJCQlyZXR1cm47CgkJCgkJaWYgKGNvbnRyb2wgaW5zdGFuY2VvZiBUZXh0IHx8IGNvbnRyb2wgaW5zdGFuY2VvZiBDb21ibykgewoJCQkvLyByZWdpc3RlciB0aGUgd29ybGQuLi4gYW55IG9mIHRoZXNlIGFjdGlvbnMgY291bGQgY2F1c2UgdGhlIHN0YXRlIHRvIGNoYW5nZQoJCQljb250cm9sLmFkZFRyYXZlcnNlTGlzdGVuZXIobmV3IFRyYXZlcnNlTGlzdGVuZXIoKSB7CgkJCQlwdWJsaWMgdm9pZCBrZXlUcmF2ZXJzZWQoVHJhdmVyc2VFdmVudCBldmVudCkgewoJCQkJCXVwZGF0ZUFjdGlvbnNJbXBsKCk7CgkJCQl9CgkJCX0pOwoJCQljb250cm9sLmFkZEtleUxpc3RlbmVyKG5ldyBLZXlMaXN0ZW5lcigpIHsKCQkJCXB1YmxpYyB2b2lkIGtleVByZXNzZWQoS2V5RXZlbnQgZXZlbnQpIHsKCQkJCQl1cGRhdGVBY3Rpb25zSW1wbCgpOwoJCQkJfQoJCQkJcHVibGljIHZvaWQga2V5UmVsZWFzZWQoS2V5RXZlbnQgZXZlbnQpIHsKCQkJCQl1cGRhdGVBY3Rpb25zSW1wbCgpOwoJCQkJfQoJCQl9KTsKCQkJY29udHJvbC5hZGRNb3VzZUxpc3RlbmVyKG5ldyBNb3VzZUxpc3RlbmVyKCkgewoJCQkJcHVibGljIHZvaWQgbW91c2VEb3duKE1vdXNlRXZlbnQgZXZlbnQpIHsKCQkJCQkvLyBkbyBub3RoaW5nCgkJCQl9CgkJCQlwdWJsaWMgdm9pZCBtb3VzZVVwKE1vdXNlRXZlbnQgZXZlbnQpIHsKCQkJCQl1cGRhdGVBY3Rpb25zSW1wbCgpOwoJCQkJfQoJCQkJcHVibGljIHZvaWQgbW91c2VEb3VibGVDbGljayhNb3VzZUV2ZW50IGV2ZW50KSB7CgkJCQkJdXBkYXRlQWN0aW9uc0ltcGwoKTsKCQkJCX0KCQkJfSk7CgkJCWNvbnRyb2wuYWRkRm9jdXNMaXN0ZW5lcihuZXcgRm9jdXNMaXN0ZW5lcigpIHsKCQkJCXB1YmxpYyB2b2lkIGZvY3VzR2FpbmVkKEZvY3VzRXZlbnQgZXZlbnQpIHsKCQkJCQl1cGRhdGVBY3Rpb25zSW1wbCgpOwoJCQkJfQoJCQkJcHVibGljIHZvaWQgZm9jdXNMb3N0KEZvY3VzRXZlbnQgZXZlbnQpIHsKCQkJCQl1cGRhdGVBY3Rpb25zSW1wbCgpOwoJCQkJfQoJCQl9KTsKCQkJaWYgKGNvbnRyb2wgaW5zdGFuY2VvZiBUZXh0KSB7CgkJCQlUZXh0IHRleHQgPSAoVGV4dCkgY29udHJvbDsKCQkJCXRleHQuYWRkTW9kaWZ5TGlzdGVuZXIobmV3IE1vZGlmeUxpc3RlbmVyKCkgewoJCQkJCXB1YmxpYyB2b2lkIG1vZGlmeVRleHQoTW9kaWZ5RXZlbnQgZXZlbnQpIHsKCQkJCQkJdXBkYXRlQWN0aW9uc0ltcGwoKTsKCQkJCQl9CgkJCQl9KTsKCQkJCXRleHQuYWRkU2VsZWN0aW9uTGlzdGVuZXIobmV3IFNlbGVjdGlvbkxpc3RlbmVyKCkgewoJCQkJCXB1YmxpYyB2b2lkIHdpZGdldFNlbGVjdGVkKFNlbGVjdGlvbkV2ZW50IGV2ZW50KSB7CgkJCQkJCXVwZGF0ZUFjdGlvbnNJbXBsKCk7CgkJCQkJfQoJCQkJCXB1YmxpYyB2b2lkIHdpZGdldERlZmF1bHRTZWxlY3RlZChTZWxlY3Rpb25FdmVudCBldmVudCkgewoJCQkJCQl1cGRhdGVBY3Rpb25zSW1wbCgpOwoJCQkJCX0KCQkJCX0pOwoJCQl9IGVsc2UgewoJCQkJQ29tYm8gY29tYm8gPSAoQ29tYm8pIGNvbnRyb2w7CgkJCQljb21iby5hZGRNb2RpZnlMaXN0ZW5lcihuZXcgTW9kaWZ5TGlzdGVuZXIoKSB7CgkJCQkJcHVibGljIHZvaWQgbW9kaWZ5VGV4dChNb2RpZnlFdmVudCBldmVudCkgewoJCQkJCQl1cGRhdGVBY3Rpb25zSW1wbCgpOwoJCQkJCX0KCQkJCX0pOwoJCQkJY29tYm8uYWRkU2VsZWN0aW9uTGlzdGVuZXIobmV3IFNlbGVjdGlvbkxpc3RlbmVyKCkgewoJCQkJCXB1YmxpYyB2b2lkIHdpZGdldFNlbGVjdGVkKFNlbGVjdGlvbkV2ZW50IGV2ZW50KSB7CgkJCQkJCXVwZGF0ZUFjdGlvbnNJbXBsKCk7CgkJCQkJfQoJCQkJCXB1YmxpYyB2b2lkIHdpZGdldERlZmF1bHRTZWxlY3RlZChTZWxlY3Rpb25FdmVudCBldmVudCkgewoJCQkJCQl1cGRhdGVBY3Rpb25zSW1wbCgpOwoJCQkJCX0KCQkJCX0pOwoJCQl9CgkJfQoJCQoJCWlmIChjb250cm9sIGluc3RhbmNlb2YgQ29tcG9zaXRlKSB7CgkJCUNvbnRyb2xbXSBjaGlsZHJlbiA9ICgoQ29tcG9zaXRlKWNvbnRyb2wpLmdldENoaWxkcmVuKCk7CgkJCWlmIChjaGlsZHJlbiAhPSBudWxsKSB7CgkJCQlpbnQgc2l6ZSA9IGNoaWxkcmVuLmxlbmd0aDsKCQkJCWZvciAoaW50IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKQoJCQkJCXJlZ2lzdGVyRXZlbnRzKGNoaWxkcmVuW2ldKTsKCQkJfQoJCX0KCX0KCgkvKiAobm9uLUphdmFkb2MpCgkgKiBJbml0aWFsaXplcyB0aGUgZWRpdG9yIHBhcnQgd2l0aCBhIHNpdGUgYW5kIGlucHV0LgoJICogPHA+CgkgKiBTdWJjbGFzc2VzIG9mIDxjb2RlPkVkaXRvclBhcnQ8L2NvZGU+IG11c3QgaW1wbGVtZW50IHRoaXMgbWV0aG9kLiAgV2l0aGluCgkgKiB0aGUgaW1wbGVtZW50YXRpb24gc3ViY2xhc3NlcyBzaG91bGQgdmVyaWZ5IHRoYXQgdGhlIGlucHV0IHR5cGUgaXMgYWNjZXB0YWJsZQoJICogYW5kIHRoZW4gc2F2ZSB0aGUgc2l0ZSBhbmQgaW5wdXQuICBIZXJlIGlzIHNhbXBsZSBjb2RlOgoJICogPC9wPgoJICogPHByZT4KCSAqCQlpZiAoIShpbnB1dCBpbnN0YW5jZW9mIElGaWxlRWRpdG9ySW5wdXQpKQoJICoJCQl0aHJvdyBuZXcgUGFydEluaXRFeGNlcHRpb24oIkludmFsaWQgSW5wdXQ6IE11c3QgYmUgSUZpbGVFZGl0b3JJbnB1dCIpOwoJICoJCXNldFNpdGUoc2l0ZSk7CgkgKgkJc2V0SW5wdXQoZWRpdG9ySW5wdXQpOwoJICogPC9wcmU+CgkgKi8KCXB1YmxpYyB2b2lkIGluaXQoSUVkaXRvclNpdGUgc2l0ZSwgSUVkaXRvcklucHV0IGlucHV0KSB0aHJvd3MgUGFydEluaXRFeGNlcHRpb24gewoJCWNvbW1hbmRNYW5hZ2VyID0gR2xvYmFsQ29tbWFuZE1hbmFnZXIuZ2V0SW5zdGFuY2UoKTsKCQkKCQlzdXBlci5pbml0KHNpdGUsIGlucHV0KTsKCgkJaWYgKGlucHV0IGluc3RhbmNlb2YgSUZpbGVFZGl0b3JJbnB1dCkgewoJCQlJRmlsZUVkaXRvcklucHV0IGZlaSA9IChJRmlsZUVkaXRvcklucHV0KSBpbnB1dDsKCQkJSUZpbGUgZmlsZSA9IGZlaS5nZXRGaWxlKCk7CgkJCWlmIChmaWxlICE9IG51bGwgJiYgZmlsZS5leGlzdHMoKSkgewoJCQkJSVNlcnZlciBzZXJ2ZXIyID0gU2VydmVyVXRpbC5maW5kU2VydmVyKGZpbGUpOwoJCQkJaWYgKHNlcnZlcjIgIT0gbnVsbCkKCQkJCQlzZXJ2ZXJJZCA9IHNlcnZlcjIuZ2V0SWQoKTsKCQkJfQoJCQlpZiAoc2VydmVySWQgPT0gbnVsbCkKCQkJCXRocm93IG5ldyBQYXJ0SW5pdEV4Y2VwdGlvbihTZXJ2ZXJVSVBsdWdpbi5nZXRSZXNvdXJjZSgiJWVycm9yRWRpdG9yIiwgZmlsZS5nZXROYW1lKCkpKTsKCQl9IGVsc2UgaWYgKGlucHV0IGluc3RhbmNlb2YgSVNlcnZlckVkaXRvcklucHV0KSB7CgkJCUlTZXJ2ZXJFZGl0b3JJbnB1dCBzZWkgPSAoSVNlcnZlckVkaXRvcklucHV0KSBpbnB1dDsKCQkJc2VydmVySWQgPSBzZWkuZ2V0U2VydmVySWQoKTsKCQl9CgoJCWlmIChzZXJ2ZXJJZCAhPSBudWxsKSB7CgkJCWNvbW1hbmRNYW5hZ2VyLmdldENvbW1hbmRNYW5hZ2VyKHNlcnZlcklkKTsKCQkJc2VydmVyID0gY29tbWFuZE1hbmFnZXIuZ2V0U2VydmVyUmVzb3VyY2Uoc2VydmVySWQpOwoJCX0KCgkJSUxhYmVsUHJvdmlkZXIgbGFiZWxQcm92aWRlciA9IFNlcnZlclVJQ29yZS5nZXRMYWJlbFByb3ZpZGVyKCk7CgkJaWYgKHNlcnZlciAhPSBudWxsKSB7CgkJCXNldFBhcnROYW1lKGxhYmVsUHJvdmlkZXIuZ2V0VGV4dChzZXJ2ZXIpKTsKCQkJc2V0VGl0bGVJbWFnZShsYWJlbFByb3ZpZGVyLmdldEltYWdlKHNlcnZlcikpOwoJCQlzZXRUaXRsZVRvb2xUaXAoc2VydmVySWQpOwoJCX0gZWxzZQoJCQlzZXRQYXJ0TmFtZSgiLSIpOwoKCQljdXRBY3Rpb24gPSBuZXcgVGV4dEFjdGlvbihzaXRlLmdldFNoZWxsKCkuZ2V0RGlzcGxheSgpLCBUZXh0QWN0aW9uLkNVVF9BQ1RJT04pOwoJCWNvcHlBY3Rpb24gPSBuZXcgVGV4dEFjdGlvbihzaXRlLmdldFNoZWxsKCkuZ2V0RGlzcGxheSgpLCBUZXh0QWN0aW9uLkNPUFlfQUNUSU9OKTsKCQlwYXN0ZUFjdGlvbiA9IG5ldyBUZXh0QWN0aW9uKHNpdGUuZ2V0U2hlbGwoKS5nZXREaXNwbGF5KCksIFRleHRBY3Rpb24uUEFTVEVfQUNUSU9OKTsKCgkJbGlzdGVuZXIgPSBuZXcgUHJvcGVydHlDaGFuZ2VMaXN0ZW5lcigpIHsKCQkJcHVibGljIHZvaWQgcHJvcGVydHlDaGFuZ2UoUHJvcGVydHlDaGFuZ2VFdmVudCBldmVudCkgewoJCQkJaWYgKEdsb2JhbENvbW1hbmRNYW5hZ2VyLlBST1BfRElSVFkuZXF1YWxzKGV2ZW50LmdldFByb3BlcnR5TmFtZSgpKSkgewoJCQkJCU9iamVjdCBvYmogPSBldmVudC5nZXRPbGRWYWx1ZSgpOwoJCQkJCWlmIChvYmogPT0gc2VydmVySWQpCgkJCQkJCWZpcmVQcm9wZXJ0eUNoYW5nZShQUk9QX0RJUlRZKTsKCQkJCX0gZWxzZSBpZiAoR2xvYmFsQ29tbWFuZE1hbmFnZXIuUFJPUF9VTkRPLmVxdWFscyhldmVudC5nZXRQcm9wZXJ0eU5hbWUoKSkpIHsKCQkJCQlPYmplY3Qgb2JqID0gZXZlbnQuZ2V0T2xkVmFsdWUoKTsKCQkJCQlpZiAob2JqID09IHNlcnZlcklkKQoJCQkJCQl1cGRhdGVVbmRvQWN0aW9uKCk7CgkJCQl9IGVsc2UgaWYgKEdsb2JhbENvbW1hbmRNYW5hZ2VyLlBST1BfUkVETy5lcXVhbHMoZXZlbnQuZ2V0UHJvcGVydHlOYW1lKCkpKSB7CgkJCQkJT2JqZWN0IG9iaiA9IGV2ZW50LmdldE9sZFZhbHVlKCk7CgkJCQkJaWYgKG9iaiA9PSBzZXJ2ZXJJZCkKCQkJCQkJdXBkYXRlUmVkb0FjdGlvbigpOwoJCQkJfSBlbHNlIGlmIChHbG9iYWxDb21tYW5kTWFuYWdlci5QUk9QX1JFTE9BRC5lcXVhbHMoZXZlbnQuZ2V0UHJvcGVydHlOYW1lKCkpKSB7CgkJCQkJT2JqZWN0IG9iaiA9IGV2ZW50LmdldE9sZFZhbHVlKCk7CgkJCQkJaWYgKG9iaiA9PSBzZXJ2ZXJJZCkgewoJCQkJCQlzZXJ2ZXIgPSBjb21tYW5kTWFuYWdlci5nZXRTZXJ2ZXJSZXNvdXJjZShzZXJ2ZXJJZCk7CgkJCQkJCXJlZnJlc2goKTsKCQkJCQl9CgkJCQl9CgkJCX0KCQl9OwoJCWlmIChzZXJ2ZXIgIT0gbnVsbCAmJiBjb21tYW5kTWFuYWdlci5pc0RpcnR5KHNlcnZlcklkKSkKCQkJZmlyZVByb3BlcnR5Q2hhbmdlKFBST1BfRElSVFkpOwoKCQljb21tYW5kTWFuYWdlci5hZGRQcm9wZXJ0eUNoYW5nZUxpc3RlbmVyKGxpc3RlbmVyKTsKCQkKCQkvLyBjcmVhdGUgZWRpdG9yIGlucHV0CgkJSUNvbW1hbmRNYW5hZ2VyIHNlcnZlckNvbW1hbmRNYW5hZ2VyID0gbnVsbDsKCQlpZiAoc2VydmVyICE9IG51bGwpCgkJCXNlcnZlckNvbW1hbmRNYW5hZ2VyID0gbmV3IFNlcnZlclJlc291cmNlQ29tbWFuZE1hbmFnZXIodGhpcywgc2VydmVySWQsIGNvbW1hbmRNYW5hZ2VyKTsKCQllZGl0b3JQYXJ0SW5wdXQgPSBjb21tYW5kTWFuYWdlci5nZXRQYXJ0SW5wdXQoc2VydmVySWQsIHNlcnZlckNvbW1hbmRNYW5hZ2VyKTsKCQkKCQljcmVhdGVBY3Rpb25zKCk7CgkJCgkJLy8gYWRkIHJlc291cmNlIGxpc3RlbmVyCgkJcmVzb3VyY2VMaXN0ZW5lciA9IG5ldyBMaWZlY3ljbGVMaXN0ZW5lcigpOwoJCVNlcnZlckNvcmUuYWRkU2VydmVyTGlmZWN5Y2xlTGlzdGVuZXIocmVzb3VyY2VMaXN0ZW5lcik7CgkJCgkJSVdvcmtiZW5jaFdpbmRvdyB3aW5kb3cgPSBnZXRTaXRlKCkuZ2V0V29ya2JlbmNoV2luZG93KCk7CgkJd2luZG93LmdldFBhcnRTZXJ2aWNlKCkuYWRkUGFydExpc3RlbmVyKGFjdGl2YXRpb25MaXN0ZW5lcik7CgkJd2luZG93LmdldFNoZWxsKCkuYWRkU2hlbGxMaXN0ZW5lcihhY3RpdmF0aW9uTGlzdGVuZXIpOwoJfQoKCS8qIChub24tSmF2YWRvYykKCSAqIFJldHVybnMgd2hldGhlciB0aGUgY29udGVudHMgb2YgdGhpcyBlZGl0b3IgaGF2ZSBjaGFuZ2VkIHNpbmNlIHRoZSBsYXN0IHNhdmUKCSAqIG9wZXJhdGlvbi4KCSAqIDxwPgoJICogU3ViY2xhc3NlcyBtdXN0IG92ZXJyaWRlIHRoaXMgbWV0aG9kIHRvIGltcGxlbWVudCB0aGUgb3Blbi1zYXZlLWNsb3NlIGxpZmVjeWNsZQoJICogZm9yIGFuIGVkaXRvci4gIEZvciBncmVhdGVyIGRldGFpbHMsIHNlZSA8Y29kZT5JRWRpdG9yUGFydDwvY29kZT4KCSAqIDwvcD4KCSAqCgkgKiBAc2VlIElFZGl0b3JQYXJ0CgkgKi8KCXB1YmxpYyBib29sZWFuIGlzRGlydHkoKSB7CgkJaWYgKGNvbW1hbmRNYW5hZ2VyICE9IG51bGwpIHsKCQkJaWYgKHNlcnZlciAhPSBudWxsICYmIGNvbW1hbmRNYW5hZ2VyLmlzRGlydHkoc2VydmVySWQpKQoJCQkJcmV0dXJuIHRydWU7CgkJfQoJCXJldHVybiBmYWxzZTsKCX0KCgkvKiAobm9uLUphdmFkb2MpCgkgKiBSZXR1cm5zIHdoZXRoZXIgdGhlICJzYXZlIGFzIiBvcGVyYXRpb24gaXMgc3VwcG9ydGVkIGJ5IHRoaXMgZWRpdG9yLgoJICogPHA+CgkgKiBTdWJjbGFzc2VzIG11c3Qgb3ZlcnJpZGUgdGhpcyBtZXRob2QgdG8gaW1wbGVtZW50IHRoZSBvcGVuLXNhdmUtY2xvc2UgbGlmZWN5Y2xlCgkgKiBmb3IgYW4gZWRpdG9yLiAgRm9yIGdyZWF0ZXIgZGV0YWlscywgc2VlIDxjb2RlPklFZGl0b3JQYXJ0PC9jb2RlPgoJICogPC9wPgoJICoKCSAqIEBzZWUgSUVkaXRvclBhcnQKCSAqLwoJcHVibGljIGJvb2xlYW4gaXNTYXZlQXNBbGxvd2VkKCkgewoJCXJldHVybiBmYWxzZTsKCX0KCgkvKioKCSAqIFVwZGF0ZSB0aGUgdW5kbyBhY3Rpb24uCgkgKi8KCXByb3RlY3RlZCB2b2lkIHVwZGF0ZVVuZG9BY3Rpb24oKSB7CgkJSVRhc2sgY29tbWFuZCA9IGNvbW1hbmRNYW5hZ2VyLmdldFVuZG9Db21tYW5kKHNlcnZlcklkKTsKCQlpZiAoY29tbWFuZCA9PSBudWxsKSB7CgkJCXVuZG9BY3Rpb24uc2V0VGV4dChTZXJ2ZXJVSVBsdWdpbi5nZXRSZXNvdXJjZSgiJWVkaXRvclVuZG9EaXNhYmxlZCIpKTsKCQkJdW5kb0FjdGlvbi5zZXRUb29sVGlwVGV4dCgiIik7CgkJCXVuZG9BY3Rpb24uc2V0RGVzY3JpcHRpb24oIiIpOwoJCQl1bmRvQWN0aW9uLnNldEVuYWJsZWQoZmFsc2UpOwoJCX0gZWxzZSB7CgkJCVN0cmluZyB0ZXh0ID0gU2VydmVyVUlQbHVnaW4uZ2V0UmVzb3VyY2UoIiVlZGl0b3JVbmRvRW5hYmxlZCIsIG5ldyBPYmplY3RbXSB7Y29tbWFuZC5nZXROYW1lKCl9KTsKCQkJdW5kb0FjdGlvbi5zZXRUZXh0KHRleHQpOwoJCQl1bmRvQWN0aW9uLnNldFRvb2xUaXBUZXh0KGNvbW1hbmQuZ2V0RGVzY3JpcHRpb24oKSk7CgkJCXVuZG9BY3Rpb24uc2V0RGVzY3JpcHRpb24oY29tbWFuZC5nZXREZXNjcmlwdGlvbigpKTsKCQkJdW5kb0FjdGlvbi5zZXRFbmFibGVkKHRydWUpOwoJCX0KCX0KCgkvKioKCSAqIFVwZGF0ZSB0aGUgcmVkbyBhY3Rpb24uCgkgKi8KCXByb3RlY3RlZCB2b2lkIHVwZGF0ZVJlZG9BY3Rpb24oKSB7CgkJSVRhc2sgY29tbWFuZCA9IGNvbW1hbmRNYW5hZ2VyLmdldFJlZG9Db21tYW5kKHNlcnZlcklkKTsKCQlpZiAoY29tbWFuZCA9PSBudWxsKSB7CgkJCXJlZG9BY3Rpb24uc2V0VGV4dChTZXJ2ZXJVSVBsdWdpbi5nZXRSZXNvdXJjZSgiJWVkaXRvclJlZG9EaXNhYmxlZCIpKTsKCQkJcmVkb0FjdGlvbi5zZXRUb29sVGlwVGV4dCgiIik7CgkJCXJlZG9BY3Rpb24uc2V0RGVzY3JpcHRpb24oIiIpOwoJCQlyZWRvQWN0aW9uLnNldEVuYWJsZWQoZmFsc2UpOwoJCX0gZWxzZSB7CgkJCVN0cmluZyB0ZXh0ID0gU2VydmVyVUlQbHVnaW4uZ2V0UmVzb3VyY2UoIiVlZGl0b3JSZWRvRW5hYmxlZCIsIG5ldyBPYmplY3RbXSB7Y29tbWFuZC5nZXROYW1lKCl9KTsKCQkJcmVkb0FjdGlvbi5zZXRUZXh0KHRleHQpOwoJCQlyZWRvQWN0aW9uLnNldFRvb2xUaXBUZXh0KGNvbW1hbmQuZ2V0RGVzY3JpcHRpb24oKSk7CgkJCXJlZG9BY3Rpb24uc2V0RGVzY3JpcHRpb24oY29tbWFuZC5nZXREZXNjcmlwdGlvbigpKTsKCQkJcmVkb0FjdGlvbi5zZXRFbmFibGVkKHRydWUpOwoJCX0KCX0KCQoJLyoqCgkgKiBSZXR1cm4gdGhlIGN1dCBhY3Rpb24uCgkgKiAKCSAqIEByZXR1cm4gb3JnLmVjbGlwc2UuamZhY2UuYWN0aW9uLklBY3Rpb24KCSAqLwoJcHVibGljIElBY3Rpb24gZ2V0Q3V0QWN0aW9uKCkgewoJCXJldHVybiBjdXRBY3Rpb247Cgl9CgkKCS8qKgoJICogUmV0dXJuIHRoZSBjb3B5IGFjdGlvbi4KCSAqIAoJICogQHJldHVybiBvcmcuZWNsaXBzZS5qZmFjZS5hY3Rpb24uSUFjdGlvbgoJICovCglwdWJsaWMgSUFjdGlvbiBnZXRDb3B5QWN0aW9uKCkgewoJCXJldHVybiBjb3B5QWN0aW9uOwoJfQoJCgkvKioKCSAqIFJldHVybiB0aGUgcGFzdGUgYWN0aW9uLgoJICogCgkgKiBAcmV0dXJuIG9yZy5lY2xpcHNlLmpmYWNlLmFjdGlvbi5JQWN0aW9uCgkgKi8KCXB1YmxpYyBJQWN0aW9uIGdldFBhc3RlQWN0aW9uKCkgewoJCXJldHVybiBwYXN0ZUFjdGlvbjsKCX0KCQoJLyoqCgkgKiBSZXR1cm5zIHRoZSBlZGl0b3IgYWN0aW9ucy4KCSAqIAoJICogQHJldHVybiBvcmcuZWNsaXBzZS5qZmFjZS5hY3Rpb24uSUFjdGlvbgoJICovCglwdWJsaWMgSUFjdGlvbltdIGdldEVkaXRvckFjdGlvbnMoKSB7CgkJcmV0dXJuIGVkaXRvckFjdGlvbnM7Cgl9CgkKCS8qKgoJICogVXBkYXRlIHRoZSBzZXJ2ZXIgcGFnZXMgd2l0aCBuZXcgaW5wdXQuCgkgKi8KCXByb3RlY3RlZCB2b2lkIHJlZnJlc2goKSB7CgkJLy8gY3JlYXRlIGVkaXRvciBpbnB1dAoJCUlDb21tYW5kTWFuYWdlciBzZXJ2ZXJDb21tYW5kTWFuYWdlciA9IG51bGw7CgkJaWYgKHNlcnZlciAhPSBudWxsKQoJCQlzZXJ2ZXJDb21tYW5kTWFuYWdlciA9IG5ldyBTZXJ2ZXJSZXNvdXJjZUNvbW1hbmRNYW5hZ2VyKHRoaXMsIHNlcnZlcklkLCBjb21tYW5kTWFuYWdlcik7CgkJZWRpdG9yUGFydElucHV0ID0gY29tbWFuZE1hbmFnZXIuZ2V0UGFydElucHV0KHNlcnZlcklkLCBzZXJ2ZXJDb21tYW5kTWFuYWdlcik7CgkJCgkJSXRlcmF0b3IgaXRlcmF0b3IgPSBzZXJ2ZXJQYWdlcy5pdGVyYXRvcigpOwoJCXdoaWxlIChpdGVyYXRvci5oYXNOZXh0KCkpIHsKCQkJSUVkaXRvclBhcnQgcGFydCA9IChJRWRpdG9yUGFydCkgaXRlcmF0b3IubmV4dCgpOwkJCQkJCQoJCQl0cnkgewoJCQkJcGFydC5pbml0KHBhcnQuZ2V0RWRpdG9yU2l0ZSgpLCBlZGl0b3JQYXJ0SW5wdXQpOwoJCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkJVHJhY2UudHJhY2UoIkVycm9yIHJlZnJlc2goKWluZyBlZGl0b3IgcGFydCIsIGUpOwoJCQl9CgkJfQkKCX0KCQoJLyoqCgkgKiAKCSAqLwoJcHJvdGVjdGVkIHZvaWQgcHJvbXB0UmVhZE9ubHlTZXJ2ZXJGaWxlKFN0cmluZyBpZCkgewoJCWNvbW1hbmRNYW5hZ2VyLnNldFJlYWRPbmx5KGlkLCB0cnVlKTsKCQlTdHJpbmcgdGl0bGUgPSBTZXJ2ZXJVSVBsdWdpbi5nZXRSZXNvdXJjZSgiJWVkaXRvclJlc291cmNlTW9kaWZpZWRUaXRsZSIpOwoJCVN0cmluZyBtZXNzYWdlID0gU2VydmVyVUlQbHVnaW4uZ2V0UmVzb3VyY2UoIiVlZGl0b3JSZWFkT25seU1lc3NhZ2UiKTsKCQlNZXNzYWdlRGlhbG9nLm9wZW5JbmZvcm1hdGlvbihnZXRFZGl0b3JTaXRlKCkuZ2V0U2hlbGwoKSwgdGl0bGUsIG1lc3NhZ2UpOwoJfQoKCS8qKgoJICogCgkgKi8KCXByb3RlY3RlZCB2b2lkIHByb21wdFJlbG9hZFNlcnZlckZpbGUoU3RyaW5nIGlkLCBJU2VydmVyV29ya2luZ0NvcHkgd2MpIHsKCQlTdHJpbmcgdGl0bGUgPSBTZXJ2ZXJVSVBsdWdpbi5nZXRSZXNvdXJjZSgiJWVkaXRvclJlc291cmNlTW9kaWZpZWRUaXRsZSIpOwoJCVN0cmluZyBtZXNzYWdlID0gU2VydmVyVUlQbHVnaW4uZ2V0UmVzb3VyY2UoIiVlZGl0b3JTZXJ2ZXJNb2RpZmllZE1lc3NhZ2UiKTsKCgkJaWYgKE1lc3NhZ2VEaWFsb2cub3BlblF1ZXN0aW9uKGdldEVkaXRvclNpdGUoKS5nZXRTaGVsbCgpLCB0aXRsZSwgbWVzc2FnZSkpIHsKCQkJdHJ5IHsKCQkJCS8vd2MucmVmcmVzaExvY2FsKElSZXNvdXJjZS5ERVBUSF9PTkUsIG5ldyBOdWxsUHJvZ3Jlc3NNb25pdG9yKCkpOwoJCQkJLy9UT0RPOiByZWZyZXNoIGxvY2FsIHNlcnZlcgoJCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkJVHJhY2UudHJhY2UoIkVycm9yIHJlZnJlc2hpbmcgc2VydmVyIiwgZSk7CgkJCX0KCQkJY29tbWFuZE1hbmFnZXIucmVsb2FkKGlkLCBuZXcgTnVsbFByb2dyZXNzTW9uaXRvcigpKTsKCQl9Cgl9CgoJLyoqCgkgKiAKCSAqLwoJcHVibGljIHZvaWQgc2V0Rm9jdXMoKSB7CgkJc3VwZXIuc2V0Rm9jdXMoKTsKCX0KCQoJLyoqCgkgKiAKCSAqLwoJcHJvdGVjdGVkIHZvaWQgY2hlY2tSZXNvdXJjZVN0YXRlKCkgewoJCS8vIERvIG5vdCBjaGVjayB0aGUgcmVzb3VyY2Ugc3RhdGUgY2hhbmdlIGlmIHNhdmluZyB0aHJvdWdoIHRoZSBlZGl0b3IuCgkJaWYgKGlzU2F2aW5nKSB7CgkJCS8vIERvIG5vdGhpbmcuCgkJCXJldHVybjsKCQl9CgkJCgkJLy8gY2hlY2sgZm9yIGRlbGV0ZWQgZmlsZXMKCQlpZiAocmVzb3VyY2VEZWxldGVkKSB7CgkJCVN0cmluZyB0aXRsZSA9IFNlcnZlclVJUGx1Z2luLmdldFJlc291cmNlKCIlZWRpdG9yUmVzb3VyY2VEZWxldGVUaXRsZSIpOwoJCQlTdHJpbmcgbWVzc2FnZSA9IG51bGw7CgkJCWlmIChzZXJ2ZXIgIT0gbnVsbCkKCQkJCW1lc3NhZ2UgPSBTZXJ2ZXJVSVBsdWdpbi5nZXRSZXNvdXJjZSgiJWVkaXRvclJlc291cmNlRGVsZXRlU2VydmVyTWVzc2FnZSIsIHNlcnZlci5nZXROYW1lKCkpOwoJCQlTdHJpbmdbXSBsYWJlbHMgPSBuZXcgU3RyaW5nW10ge1NlcnZlclVJUGx1Z2luLmdldFJlc291cmNlKCIlZWRpdG9yUmVzb3VyY2VEZWxldGVTYXZlIiksIElEaWFsb2dDb25zdGFudHMuQ0xPU0VfTEFCRUx9OwoJCQlNZXNzYWdlRGlhbG9nIGRpYWxvZyA9IG5ldyBNZXNzYWdlRGlhbG9nKGdldEVkaXRvclNpdGUoKS5nZXRTaGVsbCgpLCB0aXRsZSwgbnVsbCwgbWVzc2FnZSwgTWVzc2FnZURpYWxvZy5JTkZPUk1BVElPTiwgbGFiZWxzLCAwKTsKCgkJCWlmIChkaWFsb2cub3BlbigpID09IDApCgkJCQlkb1NhdmUobmV3IE51bGxQcm9ncmVzc01vbml0b3IoKSk7CgkJCWVsc2UKCQkJCWNsb3NlRWRpdG9yKCk7CgkJCXJldHVybjsKCQl9CgkJcmVzb3VyY2VEZWxldGVkID0gZmFsc2U7CgoJCS8vIGNoZWNrIGZvciBzZXJ2ZXIgY2hhbmdlcwoJCWlmIChzZXJ2ZXJJZCAhPSBudWxsKSB7CgkJCWlmICghY29tbWFuZE1hbmFnZXIuaXNEaXJ0eShzZXJ2ZXJJZCkpIHsKCQkJCWlmIChjb21tYW5kTWFuYWdlci5oYXNDaGFuZ2VkKHNlcnZlcklkKSkKCQkJCQlwcm9tcHRSZWxvYWRTZXJ2ZXJGaWxlKHNlcnZlcklkLCBzZXJ2ZXIpOwoJCQl9IGVsc2UgewoJCQkJaWYgKGNvbW1hbmRNYW5hZ2VyLmhhc0NoYW5nZWQoc2VydmVySWQpICYmICFjb21tYW5kTWFuYWdlci5hcmVGaWxlc1JlYWRPbmx5KHNlcnZlcklkKSkKCQkJCQlwcm9tcHRSZWxvYWRTZXJ2ZXJGaWxlKHNlcnZlcklkLCBzZXJ2ZXIpOwoJCQkJZWxzZSBpZiAoY29tbWFuZE1hbmFnZXIuYXJlRmlsZXNSZWFkT25seShzZXJ2ZXJJZCkgJiYgIWNvbW1hbmRNYW5hZ2VyLmlzUmVhZE9ubHkoc2VydmVySWQpKQoJCQkJCXByb21wdFJlYWRPbmx5U2VydmVyRmlsZShzZXJ2ZXJJZCk7CgkJCX0KCQkJaWYgKGNvbW1hbmRNYW5hZ2VyLmlzUmVhZE9ubHkoc2VydmVySWQpICYmICFjb21tYW5kTWFuYWdlci5hcmVGaWxlc1JlYWRPbmx5KHNlcnZlcklkKSkKCQkJCWNvbW1hbmRNYW5hZ2VyLnNldFJlYWRPbmx5KHNlcnZlcklkLCBmYWxzZSk7CgkJCWNvbW1hbmRNYW5hZ2VyLnVwZGF0ZVRpbWVzdGFtcHMoc2VydmVySWQpOwoJCX0KCgkJdXBkYXRlU3RhdHVzTGluZSgpOwoJfQoJCgkvKioKCSAqIFNldCB0aGUgdG9vbHRpcC4KCSAqLwoJcHVibGljIFN0cmluZyBnZXRUaXRsZVRvb2xUaXAoKSB7CgkJaWYgKHNlcnZlciAhPSBudWxsICYmIHNlcnZlci5nZXRGaWxlKCkgIT0gbnVsbCkKCQkJcmV0dXJuIHNlcnZlci5nZXRGaWxlKCkuZ2V0RnVsbFBhdGgoKS50b1N0cmluZygpOwoJCWVsc2UgaWYgKHNlcnZlciAhPSBudWxsKQoJCQlyZXR1cm4gc2VydmVyLmdldE5hbWUoKTsKCQllbHNlCgkJCXJldHVybiAiZXJyb3IiOwoJfQp9