LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogQ29weXJpZ2h0IChjKSAyMDAzLCAyMDA1IElCTSBDb3Jwb3JhdGlvbiBhbmQgb3RoZXJzLgogKiBBbGwgcmlnaHRzIHJlc2VydmVkLiBUaGlzIHByb2dyYW0gYW5kIHRoZSBhY2NvbXBhbnlpbmcgbWF0ZXJpYWxzCiAqIGFyZSBtYWRlIGF2YWlsYWJsZSB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEVjbGlwc2UgUHVibGljIExpY2Vuc2UgdjEuMAogKiB3aGljaCBhY2NvbXBhbmllcyB0aGlzIGRpc3RyaWJ1dGlvbiwgYW5kIGlzIGF2YWlsYWJsZSBhdAogKiBodHRwOi8vd3d3LmVjbGlwc2Uub3JnL2xlZ2FsL2VwbC12MTAuaHRtbAqgKgogKiBDb250cmlidXRvcnM6CiAqICAgIElCTSBDb3Jwb3JhdGlvbiAtIEluaXRpYWwgQVBJIGFuZCBpbXBsZW1lbnRhdGlvbgogKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KcGFja2FnZSBvcmcuZWNsaXBzZS5qc3Quc2VydmVyLnRvbWNhdC51aS5pbnRlcm5hbC5lZGl0b3I7CgppbXBvcnQgamF2YS5iZWFucy4qOwppbXBvcnQgamF2YS51dGlsLkhhc2hNYXA7CmltcG9ydCBqYXZhLnV0aWwuTGlzdDsKaW1wb3J0IGphdmEudXRpbC5NYXA7CgppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNlcnZlci51aS5lZGl0b3IuKjsKaW1wb3J0IG9yZy5lY2xpcHNlLnN3dC5TV1Q7CmltcG9ydCBvcmcuZWNsaXBzZS5zd3QuZXZlbnRzLio7CmltcG9ydCBvcmcuZWNsaXBzZS5zd3QubGF5b3V0Lio7CmltcG9ydCBvcmcuZWNsaXBzZS5zd3Qud2lkZ2V0cy5CdXR0b247CmltcG9ydCBvcmcuZWNsaXBzZS5zd3Qud2lkZ2V0cy5Db21wb3NpdGU7CmltcG9ydCBvcmcuZWNsaXBzZS5zd3Qud2lkZ2V0cy5UcmVlOwppbXBvcnQgb3JnLmVjbGlwc2Uuc3d0LndpZGdldHMuVHJlZUl0ZW07CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS5kaWFsb2dzLklEaWFsb2dDb25zdGFudHM7CmltcG9ydCBvcmcuZWNsaXBzZS5qc3Quc2VydmVyLnRvbWNhdC5jb3JlLmludGVybmFsLk1pbWVNYXBwaW5nOwppbXBvcnQgb3JnLmVjbGlwc2UuanN0LnNlcnZlci50b21jYXQuY29yZS5pbnRlcm5hbC5Ub21jYXRDb25maWd1cmF0aW9uOwppbXBvcnQgb3JnLmVjbGlwc2UuanN0LnNlcnZlci50b21jYXQuY29yZS5pbnRlcm5hbC5Ub21jYXRTZXJ2ZXI7CmltcG9ydCBvcmcuZWNsaXBzZS5qc3Quc2VydmVyLnRvbWNhdC5jb3JlLmludGVybmFsLmNvbW1hbmQuKjsKaW1wb3J0IG9yZy5lY2xpcHNlLmpzdC5zZXJ2ZXIudG9tY2F0LnVpLmludGVybmFsLkNvbnRleHRJZHM7CmltcG9ydCBvcmcuZWNsaXBzZS5qc3Quc2VydmVyLnRvbWNhdC51aS5pbnRlcm5hbC5NZXNzYWdlczsKaW1wb3J0IG9yZy5lY2xpcHNlLmpzdC5zZXJ2ZXIudG9tY2F0LnVpLmludGVybmFsLlRvbWNhdFVJUGx1Z2luOwppbXBvcnQgb3JnLmVjbGlwc2UudWkuKjsKaW1wb3J0IG9yZy5lY2xpcHNlLnVpLmZvcm1zLndpZGdldHMuRXhwYW5kYWJsZUNvbXBvc2l0ZTsKaW1wb3J0IG9yZy5lY2xpcHNlLnVpLmZvcm1zLndpZGdldHMuRm9ybVRvb2xraXQ7CmltcG9ydCBvcmcuZWNsaXBzZS51aS5mb3Jtcy53aWRnZXRzLlNlY3Rpb247CmltcG9ydCBvcmcuZWNsaXBzZS51aS5oZWxwLklXb3JrYmVuY2hIZWxwU3lzdGVtOwovKioKICogVG9tY2F0IGNvbmZpZ3VyYXRpb24gbWltZSBlZGl0b3Igc2VjdGlvbi4KICovCnB1YmxpYyBjbGFzcyBDb25maWd1cmF0aW9uTWltZUVkaXRvclNlY3Rpb24gZXh0ZW5kcyBTZXJ2ZXJFZGl0b3JTZWN0aW9uIHsKCXByb3RlY3RlZCBUb21jYXRDb25maWd1cmF0aW9uIHRvbWNhdENvbmZpZ3VyYXRpb247CgoJcHJvdGVjdGVkIGJvb2xlYW4gdXBkYXRpbmc7CgoJcHJvdGVjdGVkIFByb3BlcnR5Q2hhbmdlTGlzdGVuZXIgbGlzdGVuZXI7CgkKCXByb3RlY3RlZCBUcmVlIG1pbWVUeXBlczsKCXByb3RlY3RlZCBpbnQgaW5kZXggPSAtMTsKCXByb3RlY3RlZCBMaXN0IG1hcHBpbmdzOwoJcHJvdGVjdGVkIEJ1dHRvbiBhZGQ7Cglwcm90ZWN0ZWQgQnV0dG9uIHJlbW92ZTsKCXByb3RlY3RlZCBCdXR0b24gZWRpdDsKCgkvKioKCSAqIENvbmZpZ3VyYXRpb25NaW1lRWRpdG9yU2VjdGlvbiBjb25zdHJ1Y3RvciBjb21tZW50LgoJICovCglwdWJsaWMgQ29uZmlndXJhdGlvbk1pbWVFZGl0b3JTZWN0aW9uKCkgewoJCXN1cGVyKCk7Cgl9CgoJLyoqCgkgKiAKCSAqLwoJcHJvdGVjdGVkIHZvaWQgYWRkQ2hhbmdlTGlzdGVuZXIoKSB7CgkJbGlzdGVuZXIgPSBuZXcgUHJvcGVydHlDaGFuZ2VMaXN0ZW5lcigpIHsKCQkJcHVibGljIHZvaWQgcHJvcGVydHlDaGFuZ2UoUHJvcGVydHlDaGFuZ2VFdmVudCBldmVudCkgewoJCQkJaWYgKFRvbWNhdENvbmZpZ3VyYXRpb24uQUREX01BUFBJTkdfUFJPUEVSVFkuZXF1YWxzKGV2ZW50LmdldFByb3BlcnR5TmFtZSgpKSkgewoJCQkJCUludGVnZXIgaW4gPSAoSW50ZWdlcikgZXZlbnQuZ2V0T2xkVmFsdWUoKTsKCQkJCQlNaW1lTWFwcGluZyBtYXBwaW5nID0gKE1pbWVNYXBwaW5nKSBldmVudC5nZXROZXdWYWx1ZSgpOwoJCQkJCWFkZE1pbWVNYXBwaW5nKGluLmludFZhbHVlKCksIG1hcHBpbmcpOwoJCQkJfSBlbHNlIGlmIChUb21jYXRDb25maWd1cmF0aW9uLlJFTU9WRV9NQVBQSU5HX1BST1BFUlRZLmVxdWFscyhldmVudC5nZXRQcm9wZXJ0eU5hbWUoKSkpIHsKCQkJCQlJbnRlZ2VyIGluID0gKEludGVnZXIpIGV2ZW50LmdldE5ld1ZhbHVlKCk7CgkJCQkJcmVtb3ZlTWltZU1hcHBpbmcoaW4uaW50VmFsdWUoKSk7CgkJCQl9IGVsc2UgaWYgKFRvbWNhdENvbmZpZ3VyYXRpb24uTU9ESUZZX01BUFBJTkdfUFJPUEVSVFkuZXF1YWxzKGV2ZW50LmdldFByb3BlcnR5TmFtZSgpKSkgewoJCQkJCUludGVnZXIgaW4gPSAoSW50ZWdlcikgZXZlbnQuZ2V0T2xkVmFsdWUoKTsKCQkJCQlNaW1lTWFwcGluZyBtYXBwaW5nID0gKE1pbWVNYXBwaW5nKSBldmVudC5nZXROZXdWYWx1ZSgpOwoJCQkJCW1vZGlmeU1pbWVNYXBwaW5nKGluLmludFZhbHVlKCksIG1hcHBpbmcpOwoJCQkJfQoJCQl9CgkJfTsKCQl0b21jYXRDb25maWd1cmF0aW9uLmFkZFByb3BlcnR5Q2hhbmdlTGlzdGVuZXIobGlzdGVuZXIpOwoJfQoKCXB1YmxpYyB2b2lkIGNyZWF0ZVNlY3Rpb24oQ29tcG9zaXRlIHBhcmVudCkgewoJCXN1cGVyLmNyZWF0ZVNlY3Rpb24ocGFyZW50KTsKCQkKCQlGb3JtVG9vbGtpdCB0b29sa2l0ID0gZ2V0Rm9ybVRvb2xraXQocGFyZW50LmdldERpc3BsYXkoKSk7CgkJCgkJU2VjdGlvbiBzZWN0aW9uID0gdG9vbGtpdC5jcmVhdGVTZWN0aW9uKHBhcmVudCwgRXhwYW5kYWJsZUNvbXBvc2l0ZS5UV0lTVElFIHwgRXhwYW5kYWJsZUNvbXBvc2l0ZS5USVRMRV9CQVIKCQkJfCBTZWN0aW9uLkRFU0NSSVBUSU9OIHwgRXhwYW5kYWJsZUNvbXBvc2l0ZS5GT0NVU19USVRMRSk7CgkJc2VjdGlvbi5zZXRUZXh0KE1lc3NhZ2VzLmNvbmZpZ3VyYXRpb25FZGl0b3JNaW1lTWFwcGluZ3NTZWN0aW9uKTsKCQlzZWN0aW9uLnNldERlc2NyaXB0aW9uKE1lc3NhZ2VzLmNvbmZpZ3VyYXRpb25FZGl0b3JNaW1lTWFwcGluZ3NEZXNjcmlwdGlvbik7CgkJc2VjdGlvbi5zZXRMYXlvdXREYXRhKG5ldyBHcmlkRGF0YShHcmlkRGF0YS5GSUxMX0hPUklaT05UQUwgfCBHcmlkRGF0YS5WRVJUSUNBTF9BTElHTl9GSUxMKSk7CgkJCgkJQ29tcG9zaXRlIGNvbXBvc2l0ZSA9IHRvb2xraXQuY3JlYXRlQ29tcG9zaXRlKHNlY3Rpb24pOwoJCUdyaWRMYXlvdXQgbGF5b3V0ID0gbmV3IEdyaWRMYXlvdXQoKTsKCQlsYXlvdXQubnVtQ29sdW1ucyA9IDI7CgkJbGF5b3V0Lm1hcmdpbkhlaWdodCA9IDU7CgkJbGF5b3V0Lm1hcmdpbldpZHRoID0gMTA7CgkJbGF5b3V0LnZlcnRpY2FsU3BhY2luZyA9IDU7CgkJbGF5b3V0Lmhvcml6b250YWxTcGFjaW5nID0gMTU7CgkJY29tcG9zaXRlLnNldExheW91dChsYXlvdXQpOwoJCUdyaWREYXRhIGRhdGEgPSBuZXcgR3JpZERhdGEoR3JpZERhdGEuRklMTF9CT1RIKTsKCQljb21wb3NpdGUuc2V0TGF5b3V0RGF0YShkYXRhKTsKCQlJV29ya2JlbmNoSGVscFN5c3RlbSB3aHMgPSBQbGF0Zm9ybVVJLmdldFdvcmtiZW5jaCgpLmdldEhlbHBTeXN0ZW0oKTsKCQl3aHMuc2V0SGVscChjb21wb3NpdGUsIENvbnRleHRJZHMuQ09ORklHVVJBVElPTl9FRElUT1JfTUFQUElOR1MpOwoJCXRvb2xraXQucGFpbnRCb3JkZXJzRm9yKGNvbXBvc2l0ZSk7CgkJc2VjdGlvbi5zZXRDbGllbnQoY29tcG9zaXRlKTsKCQkKCQltaW1lVHlwZXMgPSB0b29sa2l0LmNyZWF0ZVRyZWUoY29tcG9zaXRlLCBTV1QuVl9TQ1JPTEwgfCBTV1QuU0lOR0xFIHwgU1dULkhfU0NST0xMKTsKCQlkYXRhID0gbmV3IEdyaWREYXRhKEdyaWREYXRhLkhPUklaT05UQUxfQUxJR05fRklMTCB8IEdyaWREYXRhLlZFUlRJQ0FMX0FMSUdOX0ZJTEwpOwoJCWRhdGEud2lkdGhIaW50ID0gMjIwOwoJCWRhdGEuaGVpZ2h0SGludCA9IDIwMDsKCQltaW1lVHlwZXMuc2V0TGF5b3V0RGF0YShkYXRhKTsKCQl3aHMuc2V0SGVscChtaW1lVHlwZXMsIENvbnRleHRJZHMuQ09ORklHVVJBVElPTl9FRElUT1JfTUFQUElOR1NfTElTVCk7CgkJCgkJLy8gYWRkIGxpc3RlbmVyIHRvIHRoZSB0YWJsZQoJCW1pbWVUeXBlcy5hZGRTZWxlY3Rpb25MaXN0ZW5lcihuZXcgU2VsZWN0aW9uQWRhcHRlcigpIHsKCQkJcHVibGljIHZvaWQgd2lkZ2V0U2VsZWN0ZWQoU2VsZWN0aW9uRXZlbnQgZSkgewoJCQkJc2VsZWN0TWltZU1hcHBpbmcoKTsKCQkJfQoJCX0pOwoJCQoJCUNvbXBvc2l0ZSBidXR0b25Db21wID0gdG9vbGtpdC5jcmVhdGVDb21wb3NpdGUoY29tcG9zaXRlKTsKCQlsYXlvdXQgPSBuZXcgR3JpZExheW91dCgpOwoJCWxheW91dC5tYXJnaW5IZWlnaHQgPSAwOwoJCWxheW91dC5tYXJnaW5XaWR0aCA9IDA7CgkJYnV0dG9uQ29tcC5zZXRMYXlvdXQobGF5b3V0KTsKCQlidXR0b25Db21wLnNldExheW91dERhdGEobmV3IEdyaWREYXRhKEdyaWREYXRhLlZFUlRJQ0FMX0FMSUdOX0JFR0lOTklORyB8IEdyaWREYXRhLkhPUklaT05UQUxfQUxJR05fQkVHSU5OSU5HKSk7CgkJCgkJYWRkID0gdG9vbGtpdC5jcmVhdGVCdXR0b24oYnV0dG9uQ29tcCwgTWVzc2FnZXMuZWRpdG9yQWRkLCBTV1QuUFVTSCk7CgkJZGF0YSA9IG5ldyBHcmlkRGF0YShHcmlkRGF0YS5IT1JJWk9OVEFMX0FMSUdOX0ZJTEwpOwoJCWRhdGEud2lkdGhIaW50ID0gNzU7CgkJYWRkLnNldExheW91dERhdGEoZGF0YSk7CgkJCgkJYWRkLmFkZFNlbGVjdGlvbkxpc3RlbmVyKG5ldyBTZWxlY3Rpb25BZGFwdGVyKCkgewoJCQlwdWJsaWMgdm9pZCB3aWRnZXRTZWxlY3RlZChTZWxlY3Rpb25FdmVudCBlKSB7CgkJCQlNaW1lTWFwcGluZ0RpYWxvZyBkaWFsb2cgPSBuZXcgTWltZU1hcHBpbmdEaWFsb2coZ2V0U2hlbGwoKSk7CgkJCQlkaWFsb2cub3BlbigpOwoJCQkJaWYgKGRpYWxvZy5nZXRSZXR1cm5Db2RlKCkgPT0gSURpYWxvZ0NvbnN0YW50cy5PS19JRCkgewoJCQkJCWV4ZWN1dGUobmV3IEFkZE1pbWVNYXBwaW5nQ29tbWFuZCh0b21jYXRDb25maWd1cmF0aW9uLCBkaWFsb2cuZ2V0TWltZU1hcHBpbmcoKSkpOwoJCQkJfQoJCQl9CgkJfSk7CgkJd2hzLnNldEhlbHAoYWRkLCBDb250ZXh0SWRzLkNPTkZJR1VSQVRJT05fRURJVE9SX01BUFBJTkdTX0FERCk7CgkJCgkJZWRpdCA9IHRvb2xraXQuY3JlYXRlQnV0dG9uKGJ1dHRvbkNvbXAsIE1lc3NhZ2VzLmVkaXRvckVkaXQsIFNXVC5QVVNIKTsKCQlkYXRhID0gbmV3IEdyaWREYXRhKEdyaWREYXRhLkhPUklaT05UQUxfQUxJR05fRklMTCk7CgkJZGF0YS53aWR0aEhpbnQgPSA3NTsKCQllZGl0LnNldExheW91dERhdGEoZGF0YSk7CgkJZWRpdC5zZXRFbmFibGVkKGZhbHNlKTsKCQkKCQllZGl0LmFkZFNlbGVjdGlvbkxpc3RlbmVyKG5ldyBTZWxlY3Rpb25BZGFwdGVyKCkgewoJCQlwdWJsaWMgdm9pZCB3aWRnZXRTZWxlY3RlZChTZWxlY3Rpb25FdmVudCBlKSB7CgkJCQlpZiAoaW5kZXggPCAwKQoJCQkJCXJldHVybjsKCQkJCU1pbWVNYXBwaW5nRGlhbG9nIGRpYWxvZyA9IG5ldyBNaW1lTWFwcGluZ0RpYWxvZyhnZXRTaGVsbCgpLCAoTWltZU1hcHBpbmcpIHRvbWNhdENvbmZpZ3VyYXRpb24uZ2V0TWltZU1hcHBpbmdzKCkuZ2V0KGluZGV4KSk7CgkJCQlkaWFsb2cub3BlbigpOwoJCQkJaWYgKGRpYWxvZy5nZXRSZXR1cm5Db2RlKCkgPT0gSURpYWxvZ0NvbnN0YW50cy5PS19JRCkgewoJCQkJCWV4ZWN1dGUobmV3IE1vZGlmeU1pbWVNYXBwaW5nQ29tbWFuZCh0b21jYXRDb25maWd1cmF0aW9uLCBpbmRleCwgZGlhbG9nLmdldE1pbWVNYXBwaW5nKCkpKTsKCQkJCX0KCQkJfQoJCX0pOwoJCXdocy5zZXRIZWxwKGVkaXQsIENvbnRleHRJZHMuQ09ORklHVVJBVElPTl9FRElUT1JfTUFQUElOR1NfRURJVCk7CgkJCgkJcmVtb3ZlID0gdG9vbGtpdC5jcmVhdGVCdXR0b24oYnV0dG9uQ29tcCwgTWVzc2FnZXMuZWRpdG9yUmVtb3ZlLCBTV1QuUFVTSCk7CgkJZGF0YSA9IG5ldyBHcmlkRGF0YShHcmlkRGF0YS5IT1JJWk9OVEFMX0FMSUdOX0ZJTEwpOwoJCWRhdGEud2lkdGhIaW50ID0gNzU7CgkJcmVtb3ZlLnNldExheW91dERhdGEoZGF0YSk7CgkJcmVtb3ZlLnNldEVuYWJsZWQoZmFsc2UpOwoJCQoJCXJlbW92ZS5hZGRTZWxlY3Rpb25MaXN0ZW5lcihuZXcgU2VsZWN0aW9uQWRhcHRlcigpIHsKCQkJcHVibGljIHZvaWQgd2lkZ2V0U2VsZWN0ZWQoU2VsZWN0aW9uRXZlbnQgZSkgewoJCQkJaWYgKGluZGV4IDwgMCkKCQkJCQlyZXR1cm47CgkJCQlleGVjdXRlKG5ldyBSZW1vdmVNaW1lTWFwcGluZ0NvbW1hbmQodG9tY2F0Q29uZmlndXJhdGlvbiwgaW5kZXgpKTsKCQkJCWluZGV4ID0gLTE7CgkJCQllZGl0LnNldEVuYWJsZWQoZmFsc2UpOwoJCQkJcmVtb3ZlLnNldEVuYWJsZWQoZmFsc2UpOwoJCQl9CgkJfSk7CgkJd2hzLnNldEhlbHAocmVtb3ZlLCBDb250ZXh0SWRzLkNPTkZJR1VSQVRJT05fRURJVE9SX01BUFBJTkdTX1JFTU9WRSk7CgkJCgkJaW5pdGlhbGl6ZSgpOwoJfQoJCglwdWJsaWMgdm9pZCBkaXNwb3NlKCkgewoJCWlmICh0b21jYXRDb25maWd1cmF0aW9uICE9IG51bGwpCgkJCXRvbWNhdENvbmZpZ3VyYXRpb24ucmVtb3ZlUHJvcGVydHlDaGFuZ2VMaXN0ZW5lcihsaXN0ZW5lcik7Cgl9CgoJcHVibGljIHZvaWQgaW5pdChJRWRpdG9yU2l0ZSBzaXRlLCBJRWRpdG9ySW5wdXQgaW5wdXQpIHsKCQlzdXBlci5pbml0KHNpdGUsIGlucHV0KTsKCQkKCQlUb21jYXRTZXJ2ZXIgdHMgPSAoVG9tY2F0U2VydmVyKSBzZXJ2ZXIuZ2V0QWRhcHRlcihUb21jYXRTZXJ2ZXIuY2xhc3MpOwoJCXRyeSB7CgkJCXRvbWNhdENvbmZpZ3VyYXRpb24gPSB0cy5nZXRUb21jYXRDb25maWd1cmF0aW9uKCk7CgkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJLy8gaWdub3JlCgkJfQoJCWFkZENoYW5nZUxpc3RlbmVyKCk7CgkJaW5pdGlhbGl6ZSgpOwoJfQoKCS8qKgoJICogSW5pdGlhbGl6ZSB0aGUgZmllbGRzIGluIHRoaXMgZWRpdG9yLgoJICovCglwcm90ZWN0ZWQgdm9pZCBpbml0aWFsaXplKCkgewoJCWlmIChtaW1lVHlwZXMgPT0gbnVsbCkKCQkJcmV0dXJuOwoKCQltaW1lVHlwZXMucmVtb3ZlQWxsKCk7CgkJCgkJbWFwcGluZ3MgPSB0b21jYXRDb25maWd1cmF0aW9uLmdldE1pbWVNYXBwaW5ncygpOwoJCQoJCS8vIHNvcnQgbWFwcGluZ3MKCQlpbnQgc2l6ZSA9IG1hcHBpbmdzLnNpemUoKTsKCQlpbnRbXSBtYXAgPSBuZXcgaW50W3NpemVdOwoJCWZvciAoaW50IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKQoJCQltYXBbaV0gPSBpOwoJCQoJCWZvciAoaW50IGkgPSAwOyBpIDwgc2l6ZSAtIDE7IGkrKykgewoJCQlmb3IgKGludCBqID0gaSArIDE7IGogPCBzaXplOyBqKyspIHsKCQkJCU1pbWVNYXBwaW5nIG1hcHBpbmdBID0gKE1pbWVNYXBwaW5nKSBtYXBwaW5ncy5nZXQobWFwW2ldKTsKCQkJCU1pbWVNYXBwaW5nIG1hcHBpbmdCID0gKE1pbWVNYXBwaW5nKSBtYXBwaW5ncy5nZXQobWFwW2pdKTsKCQkJCWlmIChtYXBwaW5nQS5nZXRNaW1lVHlwZSgpLmNvbXBhcmVUbyhtYXBwaW5nQi5nZXRNaW1lVHlwZSgpKSA+IDAgfHwKCQkJCQkJKChtYXBwaW5nQS5nZXRNaW1lVHlwZSgpLmVxdWFscyhtYXBwaW5nQi5nZXRNaW1lVHlwZSgpKSkgJiYKCQkJCQkJCQltYXBwaW5nQS5nZXRFeHRlbnNpb24oKS5jb21wYXJlVG8obWFwcGluZ0IuZ2V0RXh0ZW5zaW9uKCkpID4gMCkpIHsKCQkJCQlpbnQgdGVtcCA9IG1hcFtpXTsKCQkJCQltYXBbaV0gPSBtYXBbal07CgkJCQkJbWFwW2pdID0gdGVtcDsKCQkJCX0KCQkJfQoJCX0KCQkKCQkvLyBkaXNwbGF5IHRoZW0KCQlNYXAgaGFzaCA9IG5ldyBIYXNoTWFwKCk7CgkJCgkJZm9yIChpbnQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHsKCQkJTWltZU1hcHBpbmcgbWFwcGluZyA9IChNaW1lTWFwcGluZykgbWFwcGluZ3MuZ2V0KG1hcFtpXSk7CgkJCS8vIGdldCBwYXJlbnQgbm9kZQoJCQlUcmVlSXRlbSBwYXJlbnQgPSAoVHJlZUl0ZW0pIGhhc2guZ2V0KG1hcHBpbmcuZ2V0TWltZVR5cGUoKSk7CgkJCWlmIChwYXJlbnQgPT0gbnVsbCkgewoJCQkJcGFyZW50ID0gbmV3IFRyZWVJdGVtKG1pbWVUeXBlcywgU1dULk5PTkUpOwoJCQkJcGFyZW50LnNldFRleHQobWFwcGluZy5nZXRNaW1lVHlwZSgpKTsKCQkJCXBhcmVudC5zZXRJbWFnZShUb21jYXRVSVBsdWdpbi5nZXRJbWFnZShUb21jYXRVSVBsdWdpbi5JTUdfTUlNRV9NQVBQSU5HKSk7CgkJCQloYXNoLnB1dChtYXBwaW5nLmdldE1pbWVUeXBlKCksIHBhcmVudCk7CgkJCX0KCQkJCgkJCS8vIGFkZCBub2RlCgkJCVRyZWVJdGVtIGl0ZW0gPSBuZXcgVHJlZUl0ZW0ocGFyZW50LCBTV1QuTk9ORSk7CgkJCWl0ZW0uc2V0VGV4dChtYXBwaW5nLmdldEV4dGVuc2lvbigpKTsKCQkJaXRlbS5zZXRJbWFnZShUb21jYXRVSVBsdWdpbi5nZXRJbWFnZShUb21jYXRVSVBsdWdpbi5JTUdfTUlNRV9FWFRFTlNJT04pKTsKCQkJaXRlbS5zZXREYXRhKG5ldyBJbnRlZ2VyKG1hcFtpXSkpOwoJCX0KCQkKCQlpZiAocmVhZE9ubHkpIHsKCQkJYWRkLnNldEVuYWJsZWQoZmFsc2UpOwoJCQllZGl0LnNldEVuYWJsZWQoZmFsc2UpOwoJCQlyZW1vdmUuc2V0RW5hYmxlZChmYWxzZSk7CgkJfSBlbHNlIHsKCQkJYWRkLnNldEVuYWJsZWQodHJ1ZSk7CgkJCXNlbGVjdE1pbWVNYXBwaW5nKCk7CgkJfQoJfQoJCgkvKioKCSAqIEFkZCBhIG1pbWUgbWFwcGluZy4KCSAqIAoJICogQHBhcmFtIGluZGV4MgoJICogQHBhcmFtIG1hcAoJICovCglwcm90ZWN0ZWQgdm9pZCBhZGRNaW1lTWFwcGluZyhpbnQgaW5kZXgyLCBNaW1lTWFwcGluZyBtYXApIHsKCQltYXBwaW5ncy5hZGQoaW5kZXgyLCBtYXApOwoJCQoJCS8vIGNvcnJlY3QgYWxsIGluZGV4IG51bWJlcnMKCQlpbnQgc2l6ZSA9IG1pbWVUeXBlcy5nZXRJdGVtQ291bnQoKTsKCQlUcmVlSXRlbVtdIHBhcmVudHMgPSBtaW1lVHlwZXMuZ2V0SXRlbXMoKTsKCQlmb3IgKGludCBpID0gMDsgaSA8IHNpemU7IGkrKykgewoJCQlUcmVlSXRlbSBwYXJlbnQgPSBwYXJlbnRzW2ldOwoJCQkKCQkJaW50IHNpemUyID0gcGFyZW50LmdldEl0ZW1Db3VudCgpOwoJCQlUcmVlSXRlbVtdIGNoaWxkcmVuID0gcGFyZW50LmdldEl0ZW1zKCk7CgkJCWZvciAoaW50IGogPSAwOyBqIDwgc2l6ZTI7IGorKykgewoJCQkJSW50ZWdlciBpbiA9IChJbnRlZ2VyKSBjaGlsZHJlbltqXS5nZXREYXRhKCk7CgkJCQlpZiAoaW4uaW50VmFsdWUoKSA+PSBpbmRleDIpCgkJCQkJY2hpbGRyZW5bal0uc2V0RGF0YShuZXcgSW50ZWdlcihpbi5pbnRWYWx1ZSgpICsgMSkpOwoJCQl9CgkJfQoJCQoJCS8vIGNoZWNrIGlmIHRoZXJlIGlzIGEgcGFyZW50LiBJZiBzbywganVzdCBhZGQgYSBuZXcgY2hpbGQKCQlmb3IgKGludCBpID0gMDsgaSA8IHNpemU7IGkrKykgewoJCQlUcmVlSXRlbSBwYXJlbnQgPSBwYXJlbnRzW2ldOwoJCQlpZiAocGFyZW50LmdldFRleHQoKS5lcXVhbHMobWFwLmdldE1pbWVUeXBlKCkpKSB7CgkJCQlUcmVlSXRlbSBpdGVtID0gbmV3IFRyZWVJdGVtKHBhcmVudCwgU1dULk5PTkUpOwoJCQkJaXRlbS5zZXRUZXh0KG1hcC5nZXRFeHRlbnNpb24oKSk7CgkJCQlpdGVtLnNldEltYWdlKFRvbWNhdFVJUGx1Z2luLmdldEltYWdlKFRvbWNhdFVJUGx1Z2luLklNR19NSU1FX0VYVEVOU0lPTikpOwoJCQkJaXRlbS5zZXREYXRhKG5ldyBJbnRlZ2VyKGluZGV4MikpOwoJCQkJbWltZVR5cGVzLnNob3dJdGVtKGl0ZW0pOwoJCQkJcmV0dXJuOwoJCQl9CgkJfQoJCQoJCS8vIGlmIG5vdCwgYWRkIGEgbmV3IHBhcmVudCBhbmQgY2hpbGQgdG8gdGhlIGVuZAoJCVRyZWVJdGVtIHBhcmVudCA9IG5ldyBUcmVlSXRlbShtaW1lVHlwZXMsIFNXVC5OT05FKTsKCQlwYXJlbnQuc2V0VGV4dChtYXAuZ2V0TWltZVR5cGUoKSk7CgkJcGFyZW50LnNldEltYWdlKFRvbWNhdFVJUGx1Z2luLmdldEltYWdlKFRvbWNhdFVJUGx1Z2luLklNR19NSU1FX01BUFBJTkcpKTsKCQkKCQlUcmVlSXRlbSBpdGVtID0gbmV3IFRyZWVJdGVtKHBhcmVudCwgU1dULk5PTkUpOwoJCWl0ZW0uc2V0VGV4dChtYXAuZ2V0RXh0ZW5zaW9uKCkpOwoJCWl0ZW0uc2V0SW1hZ2UoVG9tY2F0VUlQbHVnaW4uZ2V0SW1hZ2UoVG9tY2F0VUlQbHVnaW4uSU1HX01JTUVfRVhURU5TSU9OKSk7CgkJaXRlbS5zZXREYXRhKG5ldyBJbnRlZ2VyKGluZGV4MikpOwoJCW1pbWVUeXBlcy5zaG93SXRlbShpdGVtKTsKCX0KCQoJLyoqCgkgKiAKCSAqIEBwYXJhbSBpbmRleDIKCSAqIEBwYXJhbSBtYXAKCSAqLwoJcHJvdGVjdGVkIHZvaWQgbW9kaWZ5TWltZU1hcHBpbmcoaW50IGluZGV4MiwgTWltZU1hcHBpbmcgbWFwKSB7CgkJTWltZU1hcHBpbmcgb2xkTWFwID0gKE1pbWVNYXBwaW5nKSBtYXBwaW5ncy5nZXQoaW5kZXgyKTsKCQltYXBwaW5ncy5zZXQoaW5kZXgyLCBtYXApOwoJCQoJCWludCBzaXplID0gbWltZVR5cGVzLmdldEl0ZW1Db3VudCgpOwoJCVRyZWVJdGVtW10gcGFyZW50cyA9IG1pbWVUeXBlcy5nZXRJdGVtcygpOwoJCQoJCWlmIChvbGRNYXAuZ2V0TWltZVR5cGUoKS5lcXVhbHMobWFwLmdldE1pbWVUeXBlKCkpKSB7CgkJCWZvciAoaW50IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKSB7CgkJCQlUcmVlSXRlbSBwYXJlbnQgPSBwYXJlbnRzW2ldOwoJCQkJCgkJCQlpZiAocGFyZW50LmdldFRleHQoKS5lcXVhbHMobWFwLmdldE1pbWVUeXBlKCkpKSB7CgkJCQkJaW50IHNpemUyID0gcGFyZW50LmdldEl0ZW1Db3VudCgpOwoJCQkJCVRyZWVJdGVtW10gY2hpbGRyZW4gPSBwYXJlbnQuZ2V0SXRlbXMoKTsKCQkJCQlmb3IgKGludCBqID0gMDsgaiA8IHNpemUyOyBqKyspIHsKCQkJCQkJSW50ZWdlciBpbiA9IChJbnRlZ2VyKSBjaGlsZHJlbltqXS5nZXREYXRhKCk7CgkJCQkJCWlmIChpbi5pbnRWYWx1ZSgpID09IGluZGV4MikgewoJCQkJCQkJY2hpbGRyZW5bal0uc2V0VGV4dChtYXAuZ2V0RXh0ZW5zaW9uKCkpOwoJCQkJCQkJY2hpbGRyZW5bal0uc2V0RGF0YShuZXcgSW50ZWdlcihpbmRleDIpKTsKCQkJCQkJCW1pbWVUeXBlcy5zaG93SXRlbShjaGlsZHJlbltqXSk7CgkJCQkJCQlyZXR1cm47CgkJCQkJCX0KCQkJCQl9CgkJCQl9CgkJCX0KCQkJcmV0dXJuOwoJCX0KCQkKCQkvLyBvdGhlcndpc2UsIGxldCdzIHRyeSBhIHJlbW92ZSBhbmQgYW4gYWRkCgkJcmVtb3ZlTWltZU1hcHBpbmcoaW5kZXgyKTsKCQlhZGRNaW1lTWFwcGluZyhpbmRleDIsIG1hcCk7Cgl9CgkKCS8qKgoJICogUmVtb3ZlIHRoZSBtaW1lIG1hcHBpbmcgYXQgdGhlIGdpdmVuIGluZGV4LgoJICogCgkgKiBAcGFyYW0gaW5kZXgyCgkgKi8KCXByb3RlY3RlZCB2b2lkIHJlbW92ZU1pbWVNYXBwaW5nKGludCBpbmRleDIpIHsKCQltYXBwaW5ncy5yZW1vdmUoaW5kZXgyKTsKCQkKCQkvLyByZW1vdmUgaXRlbQoJCWludCBzaXplID0gbWltZVR5cGVzLmdldEl0ZW1Db3VudCgpOwoJCVRyZWVJdGVtW10gcGFyZW50cyA9IG1pbWVUeXBlcy5nZXRJdGVtcygpOwoJCWZvciAoaW50IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKSB7CgkJCVRyZWVJdGVtIHBhcmVudCA9IHBhcmVudHNbaV07CgkJCQoJCQlpbnQgc2l6ZTIgPSBwYXJlbnQuZ2V0SXRlbUNvdW50KCk7CgkJCVRyZWVJdGVtW10gY2hpbGRyZW4gPSBwYXJlbnQuZ2V0SXRlbXMoKTsKCQkJZm9yIChpbnQgaiA9IDA7IGogPCBzaXplMjsgaisrKSB7CgkJCQlJbnRlZ2VyIGluID0gKEludGVnZXIpIGNoaWxkcmVuW2pdLmdldERhdGEoKTsKCQkJCWlmIChpbi5pbnRWYWx1ZSgpID09IGluZGV4MikgewoJCQkJCWNoaWxkcmVuW2pdLmRpc3Bvc2UoKTsKCQkJCQlpZiAoc2l6ZTIgPT0gMSkKCQkJCQkJcGFyZW50LmRpc3Bvc2UoKTsKCQkJCQlpICs9IHNpemU7CgkJCQkJaiArPSBzaXplMjsKCQkJCX0KCQkJfQoJCX0KCQkKCQkvLyBjb3JyZWN0IGFsbCBpbmRleCBudW1iZXJzCgkJc2l6ZSA9IG1pbWVUeXBlcy5nZXRJdGVtQ291bnQoKTsKCQlwYXJlbnRzID0gbWltZVR5cGVzLmdldEl0ZW1zKCk7CgkJZm9yIChpbnQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHsKCQkJVHJlZUl0ZW0gcGFyZW50ID0gcGFyZW50c1tpXTsKCQkJCgkJCWludCBzaXplMiA9IHBhcmVudC5nZXRJdGVtQ291bnQoKTsKCQkJVHJlZUl0ZW1bXSBjaGlsZHJlbiA9IHBhcmVudC5nZXRJdGVtcygpOwoJCQlmb3IgKGludCBqID0gMDsgaiA8IHNpemUyOyBqKyspIHsKCQkJCUludGVnZXIgaW4gPSAoSW50ZWdlcikgY2hpbGRyZW5bal0uZ2V0RGF0YSgpOwoJCQkJaWYgKGluLmludFZhbHVlKCkgPiBpbmRleDIpCgkJCQkJY2hpbGRyZW5bal0uc2V0RGF0YShuZXcgSW50ZWdlcihpbi5pbnRWYWx1ZSgpIC0gMSkpOwoJCQl9CgkJfQoJfQoKCS8qKgoJICogCgkgKi8KCXByb3RlY3RlZCB2b2lkIHNlbGVjdE1pbWVNYXBwaW5nKCkgewoJCWlmIChyZWFkT25seSkKCQkJcmV0dXJuOwoKCQl0cnkgewoJCQlUcmVlSXRlbSBpdGVtID0gbWltZVR5cGVzLmdldFNlbGVjdGlvbigpWzBdOwoJCQlJbnRlZ2VyIGluID0gKEludGVnZXIpIGl0ZW0uZ2V0RGF0YSgpOwoJCQlpZiAoaW4gPT0gbnVsbCkgewoJCQkJaW5kZXggPSAtMTsKCQkJCXJlbW92ZS5zZXRFbmFibGVkKGZhbHNlKTsKCQkJCWVkaXQuc2V0RW5hYmxlZChmYWxzZSk7CgkJCQlyZXR1cm47CgkJCX0KCQkJaW5kZXggPSBpbi5pbnRWYWx1ZSgpOwoJCQkKCQkJcmVtb3ZlLnNldEVuYWJsZWQodHJ1ZSk7CgkJCWVkaXQuc2V0RW5hYmxlZCh0cnVlKTsKCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQlpbmRleCA9IC0xOwoJCQlyZW1vdmUuc2V0RW5hYmxlZChmYWxzZSk7CgkJCWVkaXQuc2V0RW5hYmxlZChmYWxzZSk7CgkJfQoJfQp9