LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogQ29weXJpZ2h0IChjKSAyMDAzLCAyMDA0IElCTSBDb3Jwb3JhdGlvbiBhbmQgb3RoZXJzLgogKiBBbGwgcmlnaHRzIHJlc2VydmVkLiBUaGlzIHByb2dyYW0gYW5kIHRoZSBhY2NvbXBhbnlpbmcgbWF0ZXJpYWxzCiAqIGFyZSBtYWRlIGF2YWlsYWJsZSB1bmRlciB0aGUgdGVybXMgb2YgdGhlIENvbW1vbiBQdWJsaWMgTGljZW5zZSB2MS4wCiAqIHdoaWNoIGFjY29tcGFuaWVzIHRoaXMgZGlzdHJpYnV0aW9uLCBhbmQgaXMgYXZhaWxhYmxlIGF0CiAqIGh0dHA6Ly93d3cuZWNsaXBzZS5vcmcvbGVnYWwvY3BsLXYxMC5odG1sCqAqCiAqIENvbnRyaWJ1dG9yczoKICogICAgSUJNIC0gSW5pdGlhbCBBUEkgYW5kIGltcGxlbWVudGF0aW9uCiAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLwpwYWNrYWdlIG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIudWkuaW50ZXJuYWwud2l6YXJkLnBhZ2U7CgppbXBvcnQgamF2YS5sYW5nLnJlZmxlY3QuSW52b2NhdGlvblRhcmdldEV4Y2VwdGlvbjsKCmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS5kaWFsb2dzLkRpYWxvZzsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLmRpYWxvZ3MuSU1lc3NhZ2VQcm92aWRlcjsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLm9wZXJhdGlvbi5JUnVubmFibGVXaXRoUHJvZ3Jlc3M7CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS5yZXNvdXJjZS5KRmFjZVJlc291cmNlczsKCmltcG9ydCBvcmcuZWNsaXBzZS5zd3QuU1dUOwppbXBvcnQgb3JnLmVjbGlwc2Uuc3d0LmN1c3RvbS5TdGFja0xheW91dDsKaW1wb3J0IG9yZy5lY2xpcHNlLnN3dC5ldmVudHMuU2VsZWN0aW9uQWRhcHRlcjsKaW1wb3J0IG9yZy5lY2xpcHNlLnN3dC5ldmVudHMuU2VsZWN0aW9uRXZlbnQ7CmltcG9ydCBvcmcuZWNsaXBzZS5zd3QubGF5b3V0LkdyaWREYXRhOwppbXBvcnQgb3JnLmVjbGlwc2Uuc3d0LmxheW91dC5HcmlkTGF5b3V0OwppbXBvcnQgb3JnLmVjbGlwc2Uuc3d0LndpZGdldHMuQnV0dG9uOwppbXBvcnQgb3JnLmVjbGlwc2Uuc3d0LndpZGdldHMuQ29tcG9zaXRlOwppbXBvcnQgb3JnLmVjbGlwc2Uuc3d0LndpZGdldHMuQ29udHJvbDsKaW1wb3J0IG9yZy5lY2xpcHNlLnN3dC53aWRnZXRzLkxhYmVsOwppbXBvcnQgb3JnLmVjbGlwc2Uuc3d0LndpZGdldHMuVGV4dDsKaW1wb3J0IG9yZy5lY2xpcHNlLnVpLmhlbHAuV29ya2JlbmNoSGVscDsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIuY29yZS5JTW9kdWxlOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNlcnZlci5jb3JlLklNb2R1bGVUeXBlOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNlcnZlci5jb3JlLklSdW50aW1lOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNlcnZlci5jb3JlLklTZXJ2ZXI7CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc2VydmVyLmNvcmUuSVNlcnZlckF0dHJpYnV0ZXM7CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc2VydmVyLmNvcmUuSVNlcnZlclR5cGU7CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc2VydmVyLmNvcmUuSVNlcnZlcldvcmtpbmdDb3B5OwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNlcnZlci5jb3JlLklUYXNrTW9kZWw7CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc2VydmVyLmNvcmUuU2VydmVyQ29yZTsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIuY29yZS5TZXJ2ZXJVdGlsOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNlcnZlci51aS5pbnRlcm5hbC4qOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNlcnZlci51aS5pbnRlcm5hbC52aWV3ZXJzLlNlcnZlckNvbXBvc2l0ZTsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIudWkuaW50ZXJuYWwud2l6YXJkLmZyYWdtZW50Lk5ld1NlcnZlcldpemFyZEZyYWdtZW50OwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNlcnZlci51aS53aXphcmQuSVdpemFyZEhhbmRsZTsKLyoqCiAqIEEgd2l6YXJkIHBhZ2UgdXNlZCB0byBzZWxlY3QgYSBzZXJ2ZXIuCiAqLwpwdWJsaWMgY2xhc3MgTmV3U2VydmVyQ29tcG9zaXRlIGV4dGVuZHMgQ29tcG9zaXRlIHsKCXByb3RlY3RlZCBJV2l6YXJkSGFuZGxlIHdpemFyZDsKCXByb3RlY3RlZCBJVGFza01vZGVsIHRhc2tNb2RlbDsKCXByb3RlY3RlZCBJTW9kdWxlIG1vZHVsZTsKCXByb3RlY3RlZCBTdHJpbmcgbGF1bmNoTW9kZTsKCQoJcHJvdGVjdGVkIHN0YXRpYyBmaW5hbCBieXRlIE1PREVfRVhJU1RJTkcgPSAwOwoJcHJvdGVjdGVkIHN0YXRpYyBmaW5hbCBieXRlIE1PREVfREVURUNUID0gMTsKCXByb3RlY3RlZCBzdGF0aWMgZmluYWwgYnl0ZSBNT0RFX01BTlVBTD0gMjsKCXByb3RlY3RlZCBieXRlIG1vZGU7CgoJcHJvdGVjdGVkIENvbXBvc2l0ZSBkZXRlY3RDb21wMjsKCXByb3RlY3RlZCBOZXdEZXRlY3RTZXJ2ZXJDb21wb3NpdGUgZGV0ZWN0Q29tcDsKCXByb3RlY3RlZCBIb3N0bmFtZUNvbXBvc2l0ZSBkZXRlY3RIb3N0Q29tcDsKCXByb3RlY3RlZCBDb21wb3NpdGUgbWFudWFsQ29tcDI7Cglwcm90ZWN0ZWQgTmV3TWFudWFsU2VydmVyQ29tcG9zaXRlIG1hbnVhbENvbXA7Cglwcm90ZWN0ZWQgSG9zdG5hbWVDb21wb3NpdGUgbWFudWFsSG9zdENvbXA7Cglwcm90ZWN0ZWQgU2VydmVyQ29tcG9zaXRlIGV4aXN0aW5nQ29tcDsKCQoJcHJvdGVjdGVkIENvbXBvc2l0ZSBzdGFjazsKCXByb3RlY3RlZCBTdGFja0xheW91dCBzdGFja0xheW91dDsgCgkKCXByb3RlY3RlZCBTdHJpbmcgbGFzdEhvc3RuYW1lOwoJCglwcm90ZWN0ZWQgQnV0dG9uIHByZWY7Cglwcm90ZWN0ZWQgYm9vbGVhbiBwcmVmZXJyZWQ7CgkKCXByb3RlY3RlZCBJU2VydmVyV29ya2luZ0NvcHkgZXhpc3RpbmdXQzsKCgkvKioKCSAqIENyZWF0ZSBhIG5ldyBOZXdTZXJ2ZXJDb21wb3NpdGUuCgkgKi8KCXB1YmxpYyBOZXdTZXJ2ZXJDb21wb3NpdGUoQ29tcG9zaXRlIHBhcmVudCwgSVdpemFyZEhhbmRsZSB3aXphcmQsIElNb2R1bGUgbW9kdWxlLCBTdHJpbmcgbGF1bmNoTW9kZSkgewoJCXN1cGVyKHBhcmVudCwgU1dULk5PTkUpOwoJCXRoaXMud2l6YXJkID0gd2l6YXJkOwoJCXRoaXMubW9kdWxlID0gbW9kdWxlOwoJCXRoaXMubGF1bmNoTW9kZSA9IGxhdW5jaE1vZGU7CgkKCQl3aXphcmQuc2V0VGl0bGUoU2VydmVyVUlQbHVnaW4uZ2V0UmVzb3VyY2UoIiV3aXpOZXdTZXJ2ZXJUaXRsZSIpKTsKCQl3aXphcmQuc2V0RGVzY3JpcHRpb24oU2VydmVyVUlQbHVnaW4uZ2V0UmVzb3VyY2UoIiV3aXpOZXdTZXJ2ZXJEZXNjcmlwdGlvbiIpKTsKCQl3aXphcmQuc2V0SW1hZ2VEZXNjcmlwdG9yKEltYWdlUmVzb3VyY2UuZ2V0SW1hZ2VEZXNjcmlwdG9yKEltYWdlUmVzb3VyY2UuSU1HX1dJWkJBTl9ORVdfU0VSVkVSKSk7CgkJCgkJY3JlYXRlQ29udHJvbCgpOwoJfQoKCXB1YmxpYyBOZXdTZXJ2ZXJDb21wb3NpdGUoQ29tcG9zaXRlIHBhcmVudCwgSVdpemFyZEhhbmRsZSB3aXphcmQpIHsKCQl0aGlzKHBhcmVudCwgd2l6YXJkLCBudWxsLCBudWxsKTsKCX0KCQoJcHJvdGVjdGVkIExhYmVsIGNyZWF0ZUhlYWRpbmdMYWJlbChDb21wb3NpdGUgcGFyZW50LCBTdHJpbmcgdGV4dCwgaW50IHNwYW4pIHsKCQlMYWJlbCBsYWJlbCA9IGNyZWF0ZUxhYmVsKHBhcmVudCwgdGV4dCwgc3Bhbik7CgkJbGFiZWwuc2V0Rm9udChKRmFjZVJlc291cmNlcy5nZXRCYW5uZXJGb250KCkpOwoJCXJldHVybiBsYWJlbDsKCX0KCQoJcHJvdGVjdGVkIExhYmVsIGNyZWF0ZUxhYmVsKENvbXBvc2l0ZSBwYXJlbnQsIFN0cmluZyB0ZXh0LCBpbnQgc3BhbikgewoJCUxhYmVsIGxhYmVsID0gbmV3IExhYmVsKHBhcmVudCwgU1dULldSQVApOwoJCWxhYmVsLnNldFRleHQodGV4dCk7CgkJR3JpZERhdGEgZGF0YSA9IG5ldyBHcmlkRGF0YShHcmlkRGF0YS5IT1JJWk9OVEFMX0FMSUdOX0ZJTEwgfCBHcmlkRGF0YS5WRVJUSUNBTF9BTElHTl9CRUdJTk5JTkcpOwoJCWRhdGEuaG9yaXpvbnRhbFNwYW4gPSBzcGFuOwoJCWxhYmVsLnNldExheW91dERhdGEoZGF0YSk7CgkJcmV0dXJuIGxhYmVsOwoJfQoJCglwcm90ZWN0ZWQgTGFiZWwgY3JlYXRlTGFiZWwoQ29tcG9zaXRlIHBhcmVudCwgU3RyaW5nIHRleHQpIHsKCQlyZXR1cm4gY3JlYXRlTGFiZWwocGFyZW50LCB0ZXh0LCAxKTsKCX0KCQoJcHJvdGVjdGVkIEJ1dHRvbiBjcmVhdGVSYWRpb0J1dHRvbihDb21wb3NpdGUgcGFyZW50LCBTdHJpbmcgdGV4dCwgaW50IHNwYW4pIHsKCQlCdXR0b24gYnV0dG9uID0gbmV3IEJ1dHRvbihwYXJlbnQsIFNXVC5SQURJTyk7CgkJYnV0dG9uLnNldFRleHQodGV4dCk7CgkJR3JpZERhdGEgZGF0YSA9IG5ldyBHcmlkRGF0YShHcmlkRGF0YS5IT1JJWk9OVEFMX0FMSUdOX0ZJTEwgfCBHcmlkRGF0YS5WRVJUSUNBTF9BTElHTl9CRUdJTk5JTkcpOwoJCWRhdGEuaG9yaXpvbnRhbFNwYW4gPSBzcGFuOwoJCWRhdGEuaG9yaXpvbnRhbEluZGVudCA9IDEwOwoJCWJ1dHRvbi5zZXRMYXlvdXREYXRhKGRhdGEpOwoJCXJldHVybiBidXR0b247Cgl9CgkKCXByb3RlY3RlZCBUZXh0IGNyZWF0ZVRleHQoQ29tcG9zaXRlIHBhcmVudCwgU3RyaW5nIHRleHQyLCBpbnQgc3BhbikgewoJCVRleHQgdGV4dCA9IG5ldyBUZXh0KHBhcmVudCwgU1dULk5PTkUpOwoJCXRleHQuc2V0VGV4dCh0ZXh0Mik7CgkJR3JpZERhdGEgZGF0YSA9IG5ldyBHcmlkRGF0YShHcmlkRGF0YS5IT1JJWk9OVEFMX0FMSUdOX0ZJTEwgfCBHcmlkRGF0YS5WRVJUSUNBTF9BTElHTl9CRUdJTk5JTkcpOwoJCWRhdGEuaG9yaXpvbnRhbFNwYW4gPSBzcGFuOwoJCXRleHQuc2V0TGF5b3V0RGF0YShkYXRhKTsKCQlyZXR1cm4gdGV4dDsKCX0KCgkvKioKCSAqIENyZWF0ZXMgdGhlIFVJIG9mIHRoZSBwYWdlLgoJICoKCSAqIEBwYXJhbSBvcmcuZWNsaXBzZS5zd3Qud2lkZ2V0cy5Db21wb3NpdGUgcGFyZW50CgkgKi8KCXByb3RlY3RlZCB2b2lkIGNyZWF0ZUNvbnRyb2woKSB7CgkJR3JpZExheW91dCBsYXlvdXQgPSBuZXcgR3JpZExheW91dCgpOwoJCWxheW91dC5ob3Jpem9udGFsU3BhY2luZyA9IFNXVFV0aWwuY29udmVydEhvcml6b250YWxETFVzVG9QaXhlbHModGhpcywgNCk7CgkJbGF5b3V0LnZlcnRpY2FsU3BhY2luZyA9IFNXVFV0aWwuY29udmVydFZlcnRpY2FsRExVc1RvUGl4ZWxzKHRoaXMsIDQpOwoJCWxheW91dC5tYXJnaW5XaWR0aCA9IDA7CgkJbGF5b3V0Lm1hcmdpbkhlaWdodCA9IDA7CgkJbGF5b3V0Lm51bUNvbHVtbnMgPSAxOwoJCXNldExheW91dChsYXlvdXQpOwoJCS8vV29ya2JlbmNoSGVscC5zZXRIZWxwKHRoaXMsIENvbnRleHRJZHMuU0VMRUNUX0NMSUVOVF9XSVpBUkQpOwoJCgkJaWYgKG1vZHVsZSAhPSBudWxsKQoJCQljcmVhdGVIZWFkaW5nTGFiZWwodGhpcywgU2VydmVyVUlQbHVnaW4uZ2V0UmVzb3VyY2UoIiV3aXpOZXdTZXJ2ZXJTZWxlY3QiKSwgMSk7CgkJCQoJCUJ1dHRvbiBleGlzdGluZyA9IG51bGw7CgkJaWYgKG1vZHVsZSAhPSBudWxsKSB7CgkJCWZpbmFsIEJ1dHRvbiBwcmVkZWZpbmVkID0gY3JlYXRlUmFkaW9CdXR0b24odGhpcywgU2VydmVyVUlQbHVnaW4uZ2V0UmVzb3VyY2UoIiV3aXpOZXdTZXJ2ZXJFeGlzdGluZyIpLCAxKTsKCQkJcHJlZGVmaW5lZC5hZGRTZWxlY3Rpb25MaXN0ZW5lcihuZXcgU2VsZWN0aW9uQWRhcHRlcigpIHsKCQkJCXB1YmxpYyB2b2lkIHdpZGdldFNlbGVjdGVkKFNlbGVjdGlvbkV2ZW50IGUpIHsKCQkJCQlpZiAocHJlZGVmaW5lZC5nZXRTZWxlY3Rpb24oKSkKCQkJCQkJdG9nZ2xlTW9kZShNT0RFX0VYSVNUSU5HKTsKCQkJCX0KCQkJfSk7CgkJCWV4aXN0aW5nID0gcHJlZGVmaW5lZDsKCQl9CgkJCgkJLypmaW5hbCBCdXR0b24gYXV0byA9IGNyZWF0ZVJhZGlvQnV0dG9uKHRoaXMsIFNlcnZlclVJUGx1Z2luLmdldFJlc291cmNlKCIld2l6TmV3U2VydmVyRGV0ZWN0IiksIDEpOwoJCWF1dG8uc2V0RW5hYmxlZChmYWxzZSk7CgkJYXV0by5hZGRTZWxlY3Rpb25MaXN0ZW5lcihuZXcgU2VsZWN0aW9uQWRhcHRlcigpIHsKCQkJcHVibGljIHZvaWQgd2lkZ2V0U2VsZWN0ZWQoU2VsZWN0aW9uRXZlbnQgZSkgewoJCQkJaWYgKGF1dG8uZ2V0U2VsZWN0aW9uKCkpCgkJCQkJdG9nZ2xlTW9kZShNT0RFX0RFVEVDVCk7CgkJCX0KCQl9KTsqLwoJCgkJQnV0dG9uIG1hbnVhbCA9IG51bGw7CgkJaWYgKG1vZHVsZSAhPSBudWxsKSB7CgkJCWZpbmFsIEJ1dHRvbiBtYW51YWxCdXR0b24gPSBjcmVhdGVSYWRpb0J1dHRvbih0aGlzLCBTZXJ2ZXJVSVBsdWdpbi5nZXRSZXNvdXJjZSgiJXdpek5ld1NlcnZlck1hbnVhbCIpLCAxKTsKCQkJbWFudWFsQnV0dG9uLmFkZFNlbGVjdGlvbkxpc3RlbmVyKG5ldyBTZWxlY3Rpb25BZGFwdGVyKCkgewoJCQkJcHVibGljIHZvaWQgd2lkZ2V0U2VsZWN0ZWQoU2VsZWN0aW9uRXZlbnQgZSkgewoJCQkJCWlmIChtYW51YWxCdXR0b24uZ2V0U2VsZWN0aW9uKCkpCgkJCQkJCXRvZ2dsZU1vZGUoTU9ERV9NQU5VQUwpOwoJCQkJfQoJCQl9KTsKCQkJbWFudWFsID0gbWFudWFsQnV0dG9uOwoJCX0KCQkKCQlzdGFjayA9IG5ldyBDb21wb3NpdGUodGhpcywgU1dULk5PTkUpOwoJCUdyaWREYXRhIGRhdGEgPSBuZXcgR3JpZERhdGEoR3JpZERhdGEuRklMTF9IT1JJWk9OVEFMIHwgR3JpZERhdGEuVkVSVElDQUxfQUxJR05fQkVHSU5OSU5HKTsKCQlzdGFjay5zZXRMYXlvdXREYXRhKGRhdGEpOwoJCXN0YWNrTGF5b3V0ID0gbmV3IFN0YWNrTGF5b3V0KCk7CgkJc3RhY2tMYXlvdXQubWFyZ2luSGVpZ2h0ID0gMDsKCQlzdGFja0xheW91dC5tYXJnaW5XaWR0aCA9IDA7CgkJc3RhY2suc2V0TGF5b3V0KHN0YWNrTGF5b3V0KTsKCQkKCQlpZiAobW9kdWxlICE9IG51bGwpCgkJCWNyZWF0ZUV4aXN0aW5nQ29tcG9zaXRlKHN0YWNrKTsKCQljcmVhdGVBdXRvQ29tcG9zaXRlKHN0YWNrKTsKCQljcmVhdGVNYW51YWxDb21wb3NpdGUoc3RhY2spOwoJCgkJaWYgKGV4aXN0aW5nQ29tcCAhPSBudWxsKSB7CgkJCWlmIChpc0V4aXN0aW5nU2VydmVyKCkpIHsKCQkJCW1vZGUgPSBNT0RFX0VYSVNUSU5HOwoJCQkJc3RhY2tMYXlvdXQudG9wQ29udHJvbCA9IGV4aXN0aW5nQ29tcDsKCQkJCWV4aXN0aW5nLnNldFNlbGVjdGlvbih0cnVlKTsKCQkJfSBlbHNlIHsKCQkJCW1vZGUgPSBNT0RFX01BTlVBTDsKCQkJCXN0YWNrTGF5b3V0LnRvcENvbnRyb2wgPSBtYW51YWxDb21wMjsKCQkJCW1hbnVhbENvbXAuc2V0VmlzaWJsZSh0cnVlKTsKCQkJCWlmIChtYW51YWwgIT0gbnVsbCkKCQkJCQltYW51YWwuc2V0U2VsZWN0aW9uKHRydWUpOwoJCQkJZXhpc3Rpbmcuc2V0RW5hYmxlZChmYWxzZSk7CgkJCQlleGlzdGluZ0NvbXAuc2V0RW5hYmxlZChmYWxzZSk7CgkJCX0KCQl9IGVsc2UgewoJCQltb2RlID0gTU9ERV9NQU5VQUw7CgkJCXN0YWNrTGF5b3V0LnRvcENvbnRyb2wgPSBtYW51YWxDb21wMjsKCQkJbWFudWFsQ29tcC5zZXRWaXNpYmxlKHRydWUpOwoJCQlpZiAobWFudWFsICE9IG51bGwpCgkJCQltYW51YWwuc2V0U2VsZWN0aW9uKHRydWUpOwoJCX0KCQkKCQlpZiAobW9kdWxlICE9IG51bGwpIHsKCQkJLy8gcHJlZmVycmVkIHNlcnZlciBidXR0b24KCQkJcHJlZiA9IG5ldyBCdXR0b24odGhpcywgU1dULkNIRUNLIHwgU1dULldSQVApOwoJCQlwcmVmLnNldFRleHQoU2VydmVyVUlQbHVnaW4uZ2V0UmVzb3VyY2UoIiV3aXpTZWxlY3RTZXJ2ZXJQcmVmZXJyZWQiKSk7CgkJCWRhdGEgPSBuZXcgR3JpZERhdGEoR3JpZERhdGEuSE9SSVpPTlRBTF9BTElHTl9GSUxMIHwgR3JpZERhdGEuVkVSVElDQUxfQUxJR05fRU5EKTsKCQkJLy9wcmVmLnNldFNlbGVjdGlvbih0cnVlKTsKCQkJLy9wcmVmZXJyZWQgPSB0cnVlOwoJCQlkYXRhLmhvcml6b250YWxTcGFuID0gMTsKCQkJcHJlZi5zZXRMYXlvdXREYXRhKGRhdGEpOwoJCQlwcmVmLmFkZFNlbGVjdGlvbkxpc3RlbmVyKG5ldyBTZWxlY3Rpb25BZGFwdGVyKCkgewoJCQkJcHVibGljIHZvaWQgd2lkZ2V0U2VsZWN0ZWQoU2VsZWN0aW9uRXZlbnQgZSkgewoJCQkJCXByZWZlcnJlZCA9IHByZWYuZ2V0U2VsZWN0aW9uKCk7CgkJCQl9CgkJCX0pOwoJCQlXb3JrYmVuY2hIZWxwLnNldEhlbHAocHJlZiwgQ29udGV4dElkcy5TRUxFQ1RfU0VSVkVSX1BSRUZFUkVOQ0UpOwoJCX0KCQkKCQlEaWFsb2cuYXBwbHlEaWFsb2dGb250KHRoaXMpOwoJfQoJCglwcm90ZWN0ZWQgdm9pZCB0b2dnbGVNb2RlKGJ5dGUgbmV3TW9kZSkgewoJCWlmICghaXNWaXNpYmxlKCkpCgkJCXJldHVybjsKCgkJaWYgKG5ld01vZGUgPT0gbW9kZSkKCQkJcmV0dXJuOwoJCQoJCW1vZGUgPSBuZXdNb2RlOwoJCXdpemFyZC5zZXRNZXNzYWdlKG51bGwsIElNZXNzYWdlUHJvdmlkZXIuTk9ORSk7CgkJCgkJaWYgKG1vZGUgPT0gTU9ERV9FWElTVElORykgewoJCQlzdGFja0xheW91dC50b3BDb250cm9sID0gZXhpc3RpbmdDb21wOwoJCQlleGlzdGluZ0NvbXAuc2V0U2VsZWN0aW9uKGV4aXN0aW5nQ29tcC5nZXRTZWxlY3RlZFNlcnZlcigpKTsKCQl9IGVsc2UgaWYgKG1vZGUgPT0gTU9ERV9ERVRFQ1QpIHsKCQkJc3RhY2tMYXlvdXQudG9wQ29udHJvbCA9IGRldGVjdENvbXAyOwoJCQlkZXRlY3RDb21wLnNldFZpc2libGUodHJ1ZSk7CgkJfSBlbHNlIHsKCQkJc3RhY2tMYXlvdXQudG9wQ29udHJvbCA9IG1hbnVhbENvbXAyOwoJCQltYW51YWxDb21wLnNldFZpc2libGUodHJ1ZSk7CgkJfQoJCXN0YWNrLmxheW91dCgpOwoJCWlmICh0YXNrTW9kZWwgIT0gbnVsbCkgewoJCQl0YXNrTW9kZWwucHV0T2JqZWN0KE5ld1NlcnZlcldpemFyZEZyYWdtZW50Lk1PREUsIG5ldyBCeXRlKG1vZGUpKTsKCQkJdXBkYXRlVGFza01vZGVsKCk7CgkJfQoJfQoJCglwcm90ZWN0ZWQgSG9zdG5hbWVDb21wb3NpdGUgY3JlYXRlSG9zdENvbXBvc2l0ZShDb21wb3NpdGUgY29tcCkgewoJCUhvc3RuYW1lQ29tcG9zaXRlIGhvc3RDb21wID0gbmV3IEhvc3RuYW1lQ29tcG9zaXRlKGNvbXAsIG5ldyBIb3N0bmFtZUNvbXBvc2l0ZS5JSG9zdG5hbWVTZWxlY3Rpb25MaXN0ZW5lcigpIHsKCQkJcHVibGljIHZvaWQgaG9zdG5hbWVTZWxlY3RlZChTdHJpbmcgaG9zdCkgewoJCQkJbGFzdEhvc3RuYW1lID0gaG9zdDsKCQkJCWlmIChkZXRlY3RDb21wICE9IG51bGwpCgkJCQkJZGV0ZWN0Q29tcC5zZXRIb3N0KGhvc3QpOwoJCQkJaWYgKG1hbnVhbENvbXAgIT0gbnVsbCkKCQkJCQltYW51YWxDb21wLnNldEhvc3QoaG9zdCk7CgkJCX0KCQl9KTsKCQkKCQlpZiAobGFzdEhvc3RuYW1lICE9IG51bGwpCgkJCWhvc3RDb21wLnNldEhvc3RuYW1lKGxhc3RIb3N0bmFtZSk7CgkJCgkJR3JpZERhdGEgZGF0YSA9IG5ldyBHcmlkRGF0YShHcmlkRGF0YS5GSUxMX0hPUklaT05UQUwpOwoJCWRhdGEuaG9yaXpvbnRhbFNwYW4gPSAzOwoJCWhvc3RDb21wLnNldExheW91dERhdGEoZGF0YSk7CgkJcmV0dXJuIGhvc3RDb21wOwoJfQoJCglwcm90ZWN0ZWQgdm9pZCBjcmVhdGVBdXRvQ29tcG9zaXRlKENvbXBvc2l0ZSBjb21wKSB7CgkJZGV0ZWN0Q29tcDIgPSBuZXcgQ29tcG9zaXRlKGNvbXAsIFNXVC5OT05FKTsKCQlHcmlkTGF5b3V0IGxheW91dCA9IG5ldyBHcmlkTGF5b3V0KCk7CgkJbGF5b3V0Lmhvcml6b250YWxTcGFjaW5nID0gU1dUVXRpbC5jb252ZXJ0SG9yaXpvbnRhbERMVXNUb1BpeGVscyh0aGlzLCA0KTsKCQlsYXlvdXQudmVydGljYWxTcGFjaW5nID0gU1dUVXRpbC5jb252ZXJ0VmVydGljYWxETFVzVG9QaXhlbHModGhpcywgNCk7CgkJbGF5b3V0Lm1hcmdpbldpZHRoID0gMDsKCQlsYXlvdXQubWFyZ2luSGVpZ2h0ID0gMDsKCQlsYXlvdXQubnVtQ29sdW1ucyA9IDE7CgkJZGV0ZWN0Q29tcDIuc2V0TGF5b3V0KGxheW91dCk7CgkJCgkJZGV0ZWN0SG9zdENvbXAgPSBjcmVhdGVIb3N0Q29tcG9zaXRlKGRldGVjdENvbXAyKTsKCQkKCQlkZXRlY3RDb21wID0gbmV3IE5ld0RldGVjdFNlcnZlckNvbXBvc2l0ZShkZXRlY3RDb21wMiwgbmV3IE5ld0RldGVjdFNlcnZlckNvbXBvc2l0ZS5JU2VydmVyU2VsZWN0aW9uTGlzdGVuZXIoKSB7CgkJCXB1YmxpYyB2b2lkIHNlcnZlclNlbGVjdGVkKElTZXJ2ZXJBdHRyaWJ1dGVzIHNlcnZlcikgewoJCQkJLy8gZG8gbm90aGluZwoJCQl9CgkJfSk7CgoJCWlmIChsYXN0SG9zdG5hbWUgIT0gbnVsbCkKCQkJZGV0ZWN0Q29tcC5zZXRIb3N0KGxhc3RIb3N0bmFtZSk7CgkJZWxzZQoJCQlkZXRlY3RDb21wLnNldEhvc3QoImxvY2FsaG9zdCIpOwoJCUdyaWREYXRhIGRhdGEgPSBuZXcgR3JpZERhdGEoR3JpZERhdGEuRklMTF9IT1JJWk9OVEFMIHwgR3JpZERhdGEuVkVSVElDQUxfQUxJR05fRklMTCk7CgkJZGF0YS5ob3Jpem9udGFsU3BhbiA9IDM7CgkJZGF0YS5oZWlnaHRIaW50ID0gMTIwOwoJCWRldGVjdENvbXAuc2V0TGF5b3V0RGF0YShkYXRhKTsKCX0KCglwcm90ZWN0ZWQgdm9pZCBjcmVhdGVFeGlzdGluZ0NvbXBvc2l0ZShDb21wb3NpdGUgY29tcCkgewoJCWV4aXN0aW5nQ29tcCA9IG5ldyBTZXJ2ZXJDb21wb3NpdGUoY29tcCwgU1dULk5PTkUsIG5ldyBTZXJ2ZXJDb21wb3NpdGUuU2VydmVyU2VsZWN0aW9uTGlzdGVuZXIoKSB7CgkJCXB1YmxpYyB2b2lkIHNlcnZlclNlbGVjdGVkKElTZXJ2ZXIgc2VydmVyKSB7CgkJCQl3aXphcmQuc2V0TWVzc2FnZShudWxsLCBJTWVzc2FnZVByb3ZpZGVyLk5PTkUpOwoJCQkJCgkJCQkvLyBjaGVjayBmb3IgY29tcGF0aWJpbGl0eQoJCQkJaWYgKHNlcnZlciAhPSBudWxsICYmIG1vZHVsZSAhPSBudWxsKSB7CgkJCQkJSVNlcnZlclR5cGUgc2VydmVyVHlwZSA9IHNlcnZlci5nZXRTZXJ2ZXJUeXBlKCk7CgkJCQkJSU1vZHVsZVR5cGUgbXQgPSBtb2R1bGUuZ2V0TW9kdWxlVHlwZSgpOwoJCQkJCWlmICghU2VydmVyVXRpbC5pc1N1cHBvcnRlZE1vZHVsZShzZXJ2ZXJUeXBlLmdldFJ1bnRpbWVUeXBlKCkuZ2V0TW9kdWxlVHlwZXMoKSwgbXQpKSB7CgkJCQkJCVN0cmluZyB0eXBlID0gbXQuZ2V0TmFtZSgpOwoJCQkJCQl3aXphcmQuc2V0TWVzc2FnZShTZXJ2ZXJVSVBsdWdpbi5nZXRSZXNvdXJjZSgiJWVycm9yVmVyc2lvbkxldmVsIiwgbmV3IE9iamVjdFtdIHsgdHlwZSwgbXQuZ2V0VmVyc2lvbigpIH0pLCBJTWVzc2FnZVByb3ZpZGVyLkVSUk9SKTsKCQkJCQkJc2VydmVyID0gbnVsbDsKCQkJCQl9CgkJCQl9CgkJCQkKCQkJCWlmIChleGlzdGluZ1dDICE9IG51bGwpIHsKCQkJCQlpZiAoc2VydmVyICE9IG51bGwgJiYgc2VydmVyLmVxdWFscyhleGlzdGluZ1dDLmdldE9yaWdpbmFsKCkpKQoJCQkJCQlyZXR1cm47CgkJCQkJZXhpc3RpbmdXQyA9IG51bGw7CgkJCQl9CgkJCQlpZiAoc2VydmVyICE9IG51bGwpCgkJCQkJZXhpc3RpbmdXQyA9IHNlcnZlci5jcmVhdGVXb3JraW5nQ29weSgpOwoJCQkJdXBkYXRlVGFza01vZGVsKCk7CgkJCX0KCQl9LCBtb2R1bGUsIGxhdW5jaE1vZGUpOwoJCWV4aXN0aW5nQ29tcC5zZXRJbmNsdWRlSW5jb21wYXRpYmxlVmVyc2lvbnModHJ1ZSk7CgkJR3JpZERhdGEgZGF0YSA9IG5ldyBHcmlkRGF0YShHcmlkRGF0YS5GSUxMX0hPUklaT05UQUwgfCBHcmlkRGF0YS5WRVJUSUNBTF9BTElHTl9GSUxMKTsKCQlkYXRhLmhvcml6b250YWxTcGFuID0gMzsKCQlkYXRhLmhlaWdodEhpbnQgPSAxMjA7CgkJZXhpc3RpbmdDb21wLnNldExheW91dERhdGEoZGF0YSk7Cgl9CgkKCXByb3RlY3RlZCBib29sZWFuIGlzRXhpc3RpbmdTZXJ2ZXIoKSB7CgkJaWYgKG1vZHVsZSA9PSBudWxsIHx8IGxhdW5jaE1vZGUgPT0gbnVsbCkKCQkJcmV0dXJuIGZhbHNlOwoJCQoJCUlTZXJ2ZXJbXSBzZXJ2ZXJzID0gU2VydmVyQ29yZS5nZXRTZXJ2ZXJzKCk7CgkJaWYgKHNlcnZlcnMgIT0gbnVsbCkgewoJCQlpbnQgc2l6ZSA9IHNlcnZlcnMubGVuZ3RoOwoJCQlmb3IgKGludCBpID0gMDsgaSA8IHNpemU7IGkrKykgewoJCQkJSU1vZHVsZVR5cGUgbXQgPSBtb2R1bGUuZ2V0TW9kdWxlVHlwZSgpOwoJCQkJaWYgKFNlcnZlclV0aWwuaXNDb21wYXRpYmxlV2l0aExhdW5jaE1vZGUoc2VydmVyc1tpXSwgbGF1bmNoTW9kZSkgJiYKCQkJCQlTZXJ2ZXJVdGlsLmlzU3VwcG9ydGVkTW9kdWxlKHNlcnZlcnNbaV0uZ2V0U2VydmVyVHlwZSgpLmdldFJ1bnRpbWVUeXBlKCkuZ2V0TW9kdWxlVHlwZXMoKSwgbXQpKQoJCQkJCQlyZXR1cm4gdHJ1ZTsKCQkJfQoJCX0KCQlyZXR1cm4gZmFsc2U7Cgl9CgoJcHJvdGVjdGVkIHZvaWQgY3JlYXRlTWFudWFsQ29tcG9zaXRlKENvbXBvc2l0ZSBjb21wKSB7CgkJbWFudWFsQ29tcDIgPSBuZXcgQ29tcG9zaXRlKGNvbXAsIFNXVC5OT05FKTsKCQlHcmlkTGF5b3V0IGxheW91dCA9IG5ldyBHcmlkTGF5b3V0KCk7CgkJbGF5b3V0Lmhvcml6b250YWxTcGFjaW5nID0gU1dUVXRpbC5jb252ZXJ0SG9yaXpvbnRhbERMVXNUb1BpeGVscyh0aGlzLCA0KTsKCQlsYXlvdXQudmVydGljYWxTcGFjaW5nID0gU1dUVXRpbC5jb252ZXJ0VmVydGljYWxETFVzVG9QaXhlbHModGhpcywgNCk7CgkJbGF5b3V0Lm1hcmdpbldpZHRoID0gMDsKCQlsYXlvdXQubWFyZ2luSGVpZ2h0ID0gMDsKCQlsYXlvdXQubnVtQ29sdW1ucyA9IDE7CgkJbWFudWFsQ29tcDIuc2V0TGF5b3V0KGxheW91dCk7CgkJCgkJbWFudWFsSG9zdENvbXAgPSBjcmVhdGVIb3N0Q29tcG9zaXRlKG1hbnVhbENvbXAyKTsKCQlJTW9kdWxlVHlwZSBtdCA9IG51bGw7CgkJaWYgKG1vZHVsZSAhPSBudWxsKQoJCQltdCA9IG1vZHVsZS5nZXRNb2R1bGVUeXBlKCk7CgkJCgkJbWFudWFsQ29tcCA9IG5ldyBOZXdNYW51YWxTZXJ2ZXJDb21wb3NpdGUobWFudWFsQ29tcDIsIG5ldyBOZXdNYW51YWxTZXJ2ZXJDb21wb3NpdGUuSVdpemFyZEhhbmRsZTIoKSB7CgkJCXB1YmxpYyB2b2lkIHJ1bihib29sZWFuIGZvcmssIGJvb2xlYW4gY2FuY2VsYWJsZSwgSVJ1bm5hYmxlV2l0aFByb2dyZXNzIHJ1bm5hYmxlKSB0aHJvd3MgSW50ZXJydXB0ZWRFeGNlcHRpb24sIEludm9jYXRpb25UYXJnZXRFeGNlcHRpb24gewoJCQkJd2l6YXJkLnJ1bihmb3JrLCBjYW5jZWxhYmxlLCBydW5uYWJsZSk7CgkJCX0KCQkJcHVibGljIHZvaWQgdXBkYXRlKCkgewoJCQkJd2l6YXJkLnVwZGF0ZSgpOwoJCQl9CgkJCXB1YmxpYyB2b2lkIHNldE1lc3NhZ2UoU3RyaW5nIG5ld01lc3NhZ2UsIGludCBuZXdUeXBlKSB7CgkJCQl3aXphcmQuc2V0TWVzc2FnZShuZXdNZXNzYWdlLCBuZXdUeXBlKTsKCQkJfQoJCX0sIG10LCBuZXcgTmV3TWFudWFsU2VydmVyQ29tcG9zaXRlLlNlcnZlclNlbGVjdGlvbkxpc3RlbmVyKCkgewoJCQlwdWJsaWMgdm9pZCBzZXJ2ZXJTZWxlY3RlZChJU2VydmVyQXR0cmlidXRlcyBzZXJ2ZXIpIHsKCQkJCXVwZGF0ZVRhc2tNb2RlbCgpOwoJCQl9CgkJfSk7CgkJCgkJaWYgKGxhc3RIb3N0bmFtZSAhPSBudWxsKQoJCQltYW51YWxDb21wLnNldEhvc3QobGFzdEhvc3RuYW1lKTsKCQllbHNlCgkJCW1hbnVhbENvbXAuc2V0SG9zdCgibG9jYWxob3N0Iik7CgoJCUdyaWREYXRhIGRhdGEgPSBuZXcgR3JpZERhdGEoR3JpZERhdGEuRklMTF9IT1JJWk9OVEFMIHwgR3JpZERhdGEuVkVSVElDQUxfQUxJR05fRklMTCk7CgkJZGF0YS5ob3Jpem9udGFsU3BhbiA9IDM7CgkJZGF0YS5oZWlnaHRIaW50ID0gMjUwOwoJCW1hbnVhbENvbXAuc2V0TGF5b3V0RGF0YShkYXRhKTsKCX0KCglwcm90ZWN0ZWQgdm9pZCB1cGRhdGVUYXNrTW9kZWwoKSB7CgkJaWYgKHRhc2tNb2RlbCAhPSBudWxsKSB7CgkJCUlTZXJ2ZXJXb3JraW5nQ29weSBzZXJ2ZXIgPSBnZXRTZXJ2ZXIoKTsKCQkJaWYgKHNlcnZlciAhPSBudWxsKSB7CgkJCQl0YXNrTW9kZWwucHV0T2JqZWN0KElUYXNrTW9kZWwuVEFTS19TRVJWRVIsIHNlcnZlcik7CgkJCQl0YXNrTW9kZWwucHV0T2JqZWN0KElUYXNrTW9kZWwuVEFTS19SVU5USU1FLCBzZXJ2ZXIuZ2V0UnVudGltZSgpKTsKCQkJfSBlbHNlIHsKCQkJCXRhc2tNb2RlbC5wdXRPYmplY3QoSVRhc2tNb2RlbC5UQVNLX1NFUlZFUiwgbnVsbCk7CgkJCQl0YXNrTW9kZWwucHV0T2JqZWN0KElUYXNrTW9kZWwuVEFTS19SVU5USU1FLCBudWxsKTsKCQkJfQoJCQl3aXphcmQudXBkYXRlKCk7CgkJfQoJfQoKCXB1YmxpYyB2b2lkIHNldFRhc2tNb2RlbChJVGFza01vZGVsIG1vZGVsKSB7CgkJdGFza01vZGVsID0gbW9kZWw7CgkJdGFza01vZGVsLnB1dE9iamVjdChOZXdTZXJ2ZXJXaXphcmRGcmFnbWVudC5NT0RFLCBuZXcgQnl0ZShtb2RlKSk7CgkJdXBkYXRlVGFza01vZGVsKCk7Cgl9CgoJcHVibGljIElTZXJ2ZXJXb3JraW5nQ29weSBnZXRTZXJ2ZXIoKSB7CgkJaWYgKG1vZGUgPT0gTU9ERV9FWElTVElORykKCQkJcmV0dXJuIGV4aXN0aW5nV0M7IC8vZXhpc3RpbmdDb21wLmdldFNlbGVjdGVkU2VydmVyKCk7CgkJZWxzZSBpZiAobW9kZSA9PSBNT0RFX0RFVEVDVCkKCQkJcmV0dXJuIGRldGVjdENvbXAuZ2V0U2VydmVyKCk7CgkJZWxzZQoJCQlyZXR1cm4gbWFudWFsQ29tcC5nZXRTZXJ2ZXIoKTsKCX0KCglwdWJsaWMgSVJ1bnRpbWUgZ2V0UnVudGltZSgpIHsKCQlpZiAobW9kZSA9PSBNT0RFX0VYSVNUSU5HKSB7CgkJCUlTZXJ2ZXIgc2VydmVyID0gZXhpc3RpbmdDb21wLmdldFNlbGVjdGVkU2VydmVyKCk7CgkJCWlmIChzZXJ2ZXIgIT0gbnVsbCkKCQkJCXJldHVybiBzZXJ2ZXIuZ2V0UnVudGltZSgpOwoJCQlyZXR1cm4gbnVsbDsKCQl9IGVsc2UgaWYgKG1vZGUgPT0gTU9ERV9ERVRFQ1QpCgkJCXJldHVybiBudWxsOwoJCWVsc2UKCQkJcmV0dXJuIG1hbnVhbENvbXAuZ2V0UnVudGltZSgpOwoJfQoJCgkvKioKCSAqIFJldHVybnMgdHJ1ZSBpZiB0aGlzIHNlcnZlciBzaG91bGQgYmVjb21lIHRoZSBwcmVmZXJyZWQgc2VydmVyLgoJICogCgkgKiBAcmV0dXJuIGJvb2xlYW4KCSAqLwoJcHVibGljIGJvb2xlYW4gaXNQcmVmZXJyZWRTZXJ2ZXIoKSB7CgkJcmV0dXJuIHByZWZlcnJlZDsKCX0KCQoJcHVibGljIHZvaWQgc2V0VmlzaWJsZShib29sZWFuIHZpc2libGUpIHsKCQlzdXBlci5zZXRWaXNpYmxlKHZpc2libGUpOwoJCQoJCUNvbnRyb2xbXSBjID0gZ2V0Q2hpbGRyZW4oKTsKCQlpZiAoYyAhPSBudWxsKSB7CgkJCWludCBzaXplID0gYy5sZW5ndGg7CgkJCWZvciAoaW50IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKQoJCQkJaWYgKGNbaV0gIT0gbnVsbCkKCQkJCQljW2ldLnNldFZpc2libGUodmlzaWJsZSk7CgkJfQoJfQp9