LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogQ29weXJpZ2h0IChjKSAyMDAzLCAyMDA1IElCTSBDb3Jwb3JhdGlvbiBhbmQgb3RoZXJzLgogKiBBbGwgcmlnaHRzIHJlc2VydmVkLiBUaGlzIHByb2dyYW0gYW5kIHRoZSBhY2NvbXBhbnlpbmcgbWF0ZXJpYWxzCiAqIGFyZSBtYWRlIGF2YWlsYWJsZSB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEVjbGlwc2UgUHVibGljIExpY2Vuc2UgdjEuMAogKiB3aGljaCBhY2NvbXBhbmllcyB0aGlzIGRpc3RyaWJ1dGlvbiwgYW5kIGlzIGF2YWlsYWJsZSBhdAogKiBodHRwOi8vd3d3LmVjbGlwc2Uub3JnL2xlZ2FsL2VwbC12MTAuaHRtbAqgKiAKICogQ29udHJpYnV0b3JzOgogKiAgICAgSUJNIENvcnBvcmF0aW9uIC0gSW5pdGlhbCBBUEkgYW5kIGltcGxlbWVudGF0aW9uCiAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLwpwYWNrYWdlIG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIudWkuaW50ZXJuYWwuZWRpdG9yOwoKaW1wb3J0IGphdmEuYmVhbnMuUHJvcGVydHlDaGFuZ2VFdmVudDsKaW1wb3J0IGphdmEuYmVhbnMuUHJvcGVydHlDaGFuZ2VMaXN0ZW5lcjsKaW1wb3J0IGphdmEudXRpbC5BcnJheUxpc3Q7CmltcG9ydCBqYXZhLnV0aWwuTGlzdDsKCmltcG9ydCBvcmcuZWNsaXBzZS5jb3JlLnJlc291cmNlcy5JRm9sZGVyOwppbXBvcnQgb3JnLmVjbGlwc2UuY29yZS5ydW50aW1lLk51bGxQcm9ncmVzc01vbml0b3I7CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS53aW5kb3cuV2luZG93OwppbXBvcnQgb3JnLmVjbGlwc2Uuc3d0LlNXVDsKaW1wb3J0IG9yZy5lY2xpcHNlLnN3dC5ldmVudHMuKjsKaW1wb3J0IG9yZy5lY2xpcHNlLnN3dC5sYXlvdXQuR3JpZERhdGE7CmltcG9ydCBvcmcuZWNsaXBzZS5zd3QubGF5b3V0LkdyaWRMYXlvdXQ7CmltcG9ydCBvcmcuZWNsaXBzZS5zd3Qud2lkZ2V0cy5CdXR0b247CmltcG9ydCBvcmcuZWNsaXBzZS5zd3Qud2lkZ2V0cy5Db21ibzsKaW1wb3J0IG9yZy5lY2xpcHNlLnN3dC53aWRnZXRzLkNvbXBvc2l0ZTsKaW1wb3J0IG9yZy5lY2xpcHNlLnN3dC53aWRnZXRzLkxhYmVsOwppbXBvcnQgb3JnLmVjbGlwc2Uuc3d0LndpZGdldHMuU3Bpbm5lcjsKaW1wb3J0IG9yZy5lY2xpcHNlLnN3dC53aWRnZXRzLlRleHQ7CmltcG9ydCBvcmcuZWNsaXBzZS51aS5JRWRpdG9ySW5wdXQ7CmltcG9ydCBvcmcuZWNsaXBzZS51aS5JRWRpdG9yU2l0ZTsKaW1wb3J0IG9yZy5lY2xpcHNlLnVpLlBsYXRmb3JtVUk7CmltcG9ydCBvcmcuZWNsaXBzZS51aS5mb3Jtcy5Gb3JtQ29sb3JzOwppbXBvcnQgb3JnLmVjbGlwc2UudWkuZm9ybXMuZXZlbnRzLkh5cGVybGlua0V2ZW50OwppbXBvcnQgb3JnLmVjbGlwc2UudWkuZm9ybXMuZXZlbnRzLklIeXBlcmxpbmtMaXN0ZW5lcjsKaW1wb3J0IG9yZy5lY2xpcHNlLnVpLmZvcm1zLndpZGdldHMuKjsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIuY29yZS4qOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNlcnZlci5jb3JlLmludGVybmFsLlNlcnZlcjsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIuY29yZS51dGlsLlNvY2tldFV0aWw7CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc2VydmVyLnVpLmVkaXRvci4qOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNlcnZlci51aS5pbnRlcm5hbC5Db250ZXh0SWRzOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNlcnZlci51aS5pbnRlcm5hbC5TZXJ2ZXJVSVBsdWdpbjsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIudWkuaW50ZXJuYWwuY29tbWFuZC4qOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNlcnZlci51aS5pbnRlcm5hbC50YXNrLkZpbmlzaFdpemFyZEZyYWdtZW50OwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNlcnZlci51aS5pbnRlcm5hbC50YXNrLlNhdmVSdW50aW1lVGFzazsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIudWkuaW50ZXJuYWwud2l6YXJkLkNsb3NhYmxlV2l6YXJkRGlhbG9nOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNlcnZlci51aS53aXphcmQuVGFza1dpemFyZDsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIudWkud2l6YXJkLldpemFyZEZyYWdtZW50OwovKioKICogU2VydmVyIGdlbmVyYWwgZWRpdG9yIHBhZ2UuCiAqLwpwdWJsaWMgY2xhc3MgT3ZlcnZpZXdFZGl0b3JQYXJ0IGV4dGVuZHMgU2VydmVyRWRpdG9yUGFydCB7Cglwcm90ZWN0ZWQgVGV4dCBzZXJ2ZXJOYW1lOwoJcHJvdGVjdGVkIExhYmVsIHNlcnZlckNvbmZpZ3VyYXRpb25OYW1lOwoJcHJvdGVjdGVkIFRleHQgaG9zdG5hbWU7Cglwcm90ZWN0ZWQgQ29tYm8gcnVudGltZUNvbWJvOwoJcHJvdGVjdGVkIEJ1dHRvbiBhdXRvUHVibGlzaERlZmF1bHQ7Cglwcm90ZWN0ZWQgQnV0dG9uIGF1dG9QdWJsaXNoT3ZlcnJpZGU7Cglwcm90ZWN0ZWQgU3Bpbm5lciBhdXRvUHVibGlzaFRpbWU7CgoJcHJvdGVjdGVkIGJvb2xlYW4gdXBkYXRpbmc7CgoJcHJvdGVjdGVkIElSdW50aW1lW10gcnVudGltZXM7CgoJcHJvdGVjdGVkIFByb3BlcnR5Q2hhbmdlTGlzdGVuZXIgbGlzdGVuZXI7CgoJLyoqCgkgKiBPdmVydmlld0VkaXRvclBhcnQgY29uc3RydWN0b3IgY29tbWVudC4KCSAqLwoJcHJvdGVjdGVkIE92ZXJ2aWV3RWRpdG9yUGFydCgpIHsKCQlzdXBlcigpOwoJfQoKCXByb3RlY3RlZCBJQ29tbWFuZE1hbmFnZXIgZ2V0Q29tbWFuZE1hbmFnZXIoKSB7CgkJcmV0dXJuIGNvbW1hbmRNYW5hZ2VyOwoJfQoKCS8qKgoJICogCgkgKi8KCXByb3RlY3RlZCB2b2lkIGFkZENoYW5nZUxpc3RlbmVyKCkgewoJCWxpc3RlbmVyID0gbmV3IFByb3BlcnR5Q2hhbmdlTGlzdGVuZXIoKSB7CgkJCXB1YmxpYyB2b2lkIHByb3BlcnR5Q2hhbmdlKFByb3BlcnR5Q2hhbmdlRXZlbnQgZXZlbnQpIHsKCQkJCWlmICh1cGRhdGluZykKCQkJCQlyZXR1cm47CgkJCQl1cGRhdGluZyA9IHRydWU7CgkJCQlpZiAoZXZlbnQuZ2V0UHJvcGVydHlOYW1lKCkuZXF1YWxzKCJuYW1lIikpCgkJCQkJdXBkYXRlTmFtZXMoKTsKCQkJCWVsc2UgaWYgKGV2ZW50LmdldFByb3BlcnR5TmFtZSgpLmVxdWFscygiaG9zdG5hbWUiKSAmJiBob3N0bmFtZSAhPSBudWxsKSB7CgkJCQkJaG9zdG5hbWUuc2V0VGV4dCgoU3RyaW5nKSBldmVudC5nZXROZXdWYWx1ZSgpKTsKCQkJCX0gZWxzZSBpZiAoZXZlbnQuZ2V0UHJvcGVydHlOYW1lKCkuZXF1YWxzKCJydW50aW1lLWlkIikpIHsKCQkJCQlTdHJpbmcgcnVudGltZUlkID0gKFN0cmluZykgZXZlbnQuZ2V0TmV3VmFsdWUoKTsKCQkJCQlJUnVudGltZSBydW50aW1lID0gbnVsbDsKCQkJCQlpZiAocnVudGltZUlkICE9IG51bGwpCgkJCQkJCXJ1bnRpbWUgPSBTZXJ2ZXJDb3JlLmZpbmRSdW50aW1lKHJ1bnRpbWVJZCk7CgkJCQkJaW50IHNpemUgPSBydW50aW1lcy5sZW5ndGg7CgkJCQkJZm9yIChpbnQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHsKCQkJCQkJaWYgKHJ1bnRpbWVzW2ldLmVxdWFscyhydW50aW1lKSkKCQkJCQkJCXJ1bnRpbWVDb21iby5zZWxlY3QoaSk7CgkJCQkJfQoJCQkJfQoJCQkJdXBkYXRpbmcgPSBmYWxzZTsKCQkJfQoJCX07CgkJaWYgKHNlcnZlciAhPSBudWxsKQoJCQlzZXJ2ZXIuYWRkUHJvcGVydHlDaGFuZ2VMaXN0ZW5lcihsaXN0ZW5lcik7Cgl9CgoJcHJvdGVjdGVkIHZvaWQgdXBkYXRlTmFtZXMoKSB7CgkJaWYgKHNlcnZlck5hbWUgIT0gbnVsbCkKCQkJc2VydmVyTmFtZS5zZXRUZXh0KHNlcnZlci5nZXROYW1lKCkpOwoJfQoKCS8qKgoJICogQ3JlYXRlcyB0aGUgU1dUIGNvbnRyb2xzIGZvciB0aGlzIHdvcmtiZW5jaCBwYXJ0LgoJICoKCSAqIEBwYXJhbSBwYXJlbnQgdGhlIHBhcmVudCBjb250cm9sCgkgKi8KCXB1YmxpYyBmaW5hbCB2b2lkIGNyZWF0ZVBhcnRDb250cm9sKENvbXBvc2l0ZSBwYXJlbnQpIHsKCQlGb3JtVG9vbGtpdCB0b29sa2l0ID0gZ2V0Rm9ybVRvb2xraXQocGFyZW50LmdldERpc3BsYXkoKSk7CgkJCgkJU2Nyb2xsZWRGb3JtIGZvcm0gPSB0b29sa2l0LmNyZWF0ZVNjcm9sbGVkRm9ybShwYXJlbnQpOwoJCWZvcm0uc2V0VGV4dChTZXJ2ZXJVSVBsdWdpbi5nZXRSZXNvdXJjZSgiJXNlcnZlckVkaXRvck92ZXJ2aWV3UGFnZVRpdGxlIikpOwoJCWZvcm0uZ2V0Qm9keSgpLnNldExheW91dChuZXcgR3JpZExheW91dCgpKTsKCQkKCQlDb21wb3NpdGUgY29sdW1uQ29tcCA9IHRvb2xraXQuY3JlYXRlQ29tcG9zaXRlKGZvcm0uZ2V0Qm9keSgpKTsKCQlHcmlkTGF5b3V0IGxheW91dCA9IG5ldyBHcmlkTGF5b3V0KCk7CgkJbGF5b3V0Lm51bUNvbHVtbnMgPSAyOwoJCS8vbGF5b3V0Lm1hcmdpbkhlaWdodCA9IDEwOwoJCS8vbGF5b3V0Lm1hcmdpbldpZHRoID0gMTA7CgkJbGF5b3V0LnZlcnRpY2FsU3BhY2luZyA9IDA7CgkJbGF5b3V0Lmhvcml6b250YWxTcGFjaW5nID0gMTA7CgkJY29sdW1uQ29tcC5zZXRMYXlvdXQobGF5b3V0KTsKCQljb2x1bW5Db21wLnNldExheW91dERhdGEobmV3IEdyaWREYXRhKEdyaWREYXRhLkZJTExfSE9SSVpPTlRBTCB8IEdyaWREYXRhLlZFUlRJQ0FMX0FMSUdOX0ZJTEwpKTsKCQkKCQkvLyBsZWZ0IGNvbHVtbgoJCUNvbXBvc2l0ZSBsZWZ0Q29sdW1uQ29tcCA9IHRvb2xraXQuY3JlYXRlQ29tcG9zaXRlKGNvbHVtbkNvbXApOwoJCWxheW91dCA9IG5ldyBHcmlkTGF5b3V0KCk7CgkJbGF5b3V0Lm1hcmdpbkhlaWdodCA9IDA7CgkJbGF5b3V0Lm1hcmdpbldpZHRoID0gMDsKCQlsYXlvdXQudmVydGljYWxTcGFjaW5nID0gMTA7CgkJbGF5b3V0Lmhvcml6b250YWxTcGFjaW5nID0gMDsKCQlsZWZ0Q29sdW1uQ29tcC5zZXRMYXlvdXQobGF5b3V0KTsKCQlsZWZ0Q29sdW1uQ29tcC5zZXRMYXlvdXREYXRhKG5ldyBHcmlkRGF0YShHcmlkRGF0YS5GSUxMX0hPUklaT05UQUwgfCBHcmlkRGF0YS5WRVJUSUNBTF9BTElHTl9GSUxMKSk7CgkJCgkJU2VjdGlvbiBzZWN0aW9uID0gdG9vbGtpdC5jcmVhdGVTZWN0aW9uKGxlZnRDb2x1bW5Db21wLCBFeHBhbmRhYmxlQ29tcG9zaXRlLlRXSVNUSUV8RXhwYW5kYWJsZUNvbXBvc2l0ZS5FWFBBTkRFRCB8IEV4cGFuZGFibGVDb21wb3NpdGUuVElUTEVfQkFSIHwgU2VjdGlvbi5ERVNDUklQVElPTiB8IEV4cGFuZGFibGVDb21wb3NpdGUuRk9DVVNfVElUTEUpOwoJCXNlY3Rpb24uc2V0VGV4dChTZXJ2ZXJVSVBsdWdpbi5nZXRSZXNvdXJjZSgiJXNlcnZlckVkaXRvck92ZXJ2aWV3U2VjdGlvbiIpKTsKCQlzZWN0aW9uLnNldERlc2NyaXB0aW9uKFNlcnZlclVJUGx1Z2luLmdldFJlc291cmNlKCIlc2VydmVyRWRpdG9yT3ZlcnZpZXdEZXNjcmlwdGlvbiIpKTsKCQlzZWN0aW9uLnNldExheW91dERhdGEobmV3IEdyaWREYXRhKEdyaWREYXRhLkZJTExfSE9SSVpPTlRBTCB8IEdyaWREYXRhLlZFUlRJQ0FMX0FMSUdOX0ZJTEwpKTsKCgkJQ29tcG9zaXRlIGNvbXBvc2l0ZSA9IHRvb2xraXQuY3JlYXRlQ29tcG9zaXRlKHNlY3Rpb24pOwoJCWxheW91dCA9IG5ldyBHcmlkTGF5b3V0KCk7CgkJbGF5b3V0Lm51bUNvbHVtbnMgPSAyOwoJCWxheW91dC5tYXJnaW5IZWlnaHQgPSA1OwoJCWxheW91dC5tYXJnaW5XaWR0aCA9IDEwOwoJCWxheW91dC52ZXJ0aWNhbFNwYWNpbmcgPSA1OwoJCWxheW91dC5ob3Jpem9udGFsU3BhY2luZyA9IDE1OwoJCWNvbXBvc2l0ZS5zZXRMYXlvdXQobGF5b3V0KTsKCQljb21wb3NpdGUuc2V0TGF5b3V0RGF0YShuZXcgR3JpZERhdGEoR3JpZERhdGEuRklMTF9IT1JJWk9OVEFMIHwgR3JpZERhdGEuVkVSVElDQUxfQUxJR05fRklMTCkpOwoJCVBsYXRmb3JtVUkuZ2V0V29ya2JlbmNoKCkuZ2V0SGVscFN5c3RlbSgpLnNldEhlbHAoY29tcG9zaXRlLCBDb250ZXh0SWRzLkVESVRPUl9PVkVSVklFV19QQUdFKTsKCQl0b29sa2l0LnBhaW50Qm9yZGVyc0Zvcihjb21wb3NpdGUpOwoJCXNlY3Rpb24uc2V0Q2xpZW50KGNvbXBvc2l0ZSk7CgoJCS8vIHNlcnZlciBuYW1lCgkJaWYgKHNlcnZlciAhPSBudWxsKSB7CgkJCWNyZWF0ZUxhYmVsKHRvb2xraXQsIGNvbXBvc2l0ZSwgU2VydmVyVUlQbHVnaW4uZ2V0UmVzb3VyY2UoIiVzZXJ2ZXJFZGl0b3JPdmVydmlld1NlcnZlck5hbWUiKSk7CgkJCQoJCQlzZXJ2ZXJOYW1lID0gdG9vbGtpdC5jcmVhdGVUZXh0KGNvbXBvc2l0ZSwgc2VydmVyLmdldE5hbWUoKSk7CgkJCUdyaWREYXRhIGRhdGEgPSBuZXcgR3JpZERhdGEoR3JpZERhdGEuRklMTF9IT1JJWk9OVEFMKTsKCQkJc2VydmVyTmFtZS5zZXRMYXlvdXREYXRhKGRhdGEpOwoJCQlzZXJ2ZXJOYW1lLmFkZE1vZGlmeUxpc3RlbmVyKG5ldyBNb2RpZnlMaXN0ZW5lcigpIHsKCQkJCXB1YmxpYyB2b2lkIG1vZGlmeVRleHQoTW9kaWZ5RXZlbnQgZSkgewoJCQkJCWlmICh1cGRhdGluZykKCQkJCQkJcmV0dXJuOwoJCQkJCXVwZGF0aW5nID0gdHJ1ZTsKCQkJCQlnZXRDb21tYW5kTWFuYWdlcigpLmV4ZWN1dGVDb21tYW5kKG5ldyBTZXRTZXJ2ZXJOYW1lQ29tbWFuZChnZXRTZXJ2ZXIoKSwgc2VydmVyTmFtZS5nZXRUZXh0KCkpKTsKCQkJCQl1cGRhdGluZyA9IGZhbHNlOwoJCQkJfQoJCQl9KTsKCQl9CgkJCgkJLy8gaG9zdG5hbWUKCQlpZiAoc2VydmVyICE9IG51bGwpIHsKCQkJY3JlYXRlTGFiZWwodG9vbGtpdCwgY29tcG9zaXRlLCBTZXJ2ZXJVSVBsdWdpbi5nZXRSZXNvdXJjZSgiJXNlcnZlckVkaXRvck92ZXJ2aWV3U2VydmVySG9zdG5hbWUiKSk7CgkJCQoJCQlob3N0bmFtZSA9IHRvb2xraXQuY3JlYXRlVGV4dChjb21wb3NpdGUsIHNlcnZlci5nZXRIb3N0KCkpOwoJCQlHcmlkRGF0YSBkYXRhID0gbmV3IEdyaWREYXRhKEdyaWREYXRhLkZJTExfSE9SSVpPTlRBTCk7CgkJCWhvc3RuYW1lLnNldExheW91dERhdGEoZGF0YSk7CgkJCWhvc3RuYW1lLmFkZE1vZGlmeUxpc3RlbmVyKG5ldyBNb2RpZnlMaXN0ZW5lcigpIHsKCQkJCXB1YmxpYyB2b2lkIG1vZGlmeVRleHQoTW9kaWZ5RXZlbnQgZSkgewoJCQkJCWlmICh1cGRhdGluZykKCQkJCQkJcmV0dXJuOwoJCQkJCXVwZGF0aW5nID0gdHJ1ZTsKCQkJCQlnZXRDb21tYW5kTWFuYWdlcigpLmV4ZWN1dGVDb21tYW5kKG5ldyBTZXRTZXJ2ZXJIb3N0bmFtZUNvbW1hbmQoZ2V0U2VydmVyKCksIGhvc3RuYW1lLmdldFRleHQoKSkpOwoJCQkJCXVwZGF0aW5nID0gZmFsc2U7CgkJCQl9CgkJCX0pOwoJCX0KCQkKCQkvLyBydW50aW1lCgkJaWYgKHNlcnZlciAhPSBudWxsICYmIHNlcnZlci5nZXRTZXJ2ZXJUeXBlKCkgIT0gbnVsbCAmJiBzZXJ2ZXIuZ2V0U2VydmVyVHlwZSgpLmhhc1J1bnRpbWUoKSkgewoJCQlmaW5hbCBJUnVudGltZSBydW50aW1lID0gc2VydmVyLmdldFJ1bnRpbWUoKTsKCQkJY3JlYXRlTGFiZWwodG9vbGtpdCwgY29tcG9zaXRlLCBTZXJ2ZXJVSVBsdWdpbi5nZXRSZXNvdXJjZSgiJXNlcnZlckVkaXRvck92ZXJ2aWV3UnVudGltZSIpKTsKCQkJCgkJCUlSdW50aW1lVHlwZSBydW50aW1lVHlwZSA9IHNlcnZlci5nZXRTZXJ2ZXJUeXBlKCkuZ2V0UnVudGltZVR5cGUoKTsKCQkJcnVudGltZXMgPSBTZXJ2ZXJVSVBsdWdpbi5nZXRSdW50aW1lcyhydW50aW1lVHlwZSk7CgkJCQoJCQlpZiAocnVudGltZXMgPT0gbnVsbCB8fCBydW50aW1lcy5sZW5ndGggPT0gMCkKCQkJCXRvb2xraXQuY3JlYXRlTGFiZWwoY29tcG9zaXRlLCAiIik7CgkJCWVsc2UgaWYgKHJ1bnRpbWVzLmxlbmd0aCA9PSAxKQoJCQkJdG9vbGtpdC5jcmVhdGVMYWJlbChjb21wb3NpdGUsIHJ1bnRpbWUuZ2V0TmFtZSgpKTsKCQkJZWxzZSB7CgkJCQlydW50aW1lQ29tYm8gPSBuZXcgQ29tYm8oY29tcG9zaXRlLCBTV1QuUkVBRF9PTkxZKTsKCQkJCUdyaWREYXRhIGRhdGEgPSBuZXcgR3JpZERhdGEoR3JpZERhdGEuRklMTF9IT1JJWk9OVEFMKTsKCQkJCXJ1bnRpbWVDb21iby5zZXRMYXlvdXREYXRhKGRhdGEpOwoJCQkJdXBkYXRlUnVudGltZUNvbWJvKCk7CgkJCQkKCQkJCWludCBzaXplID0gcnVudGltZXMubGVuZ3RoOwoJCQkJZm9yIChpbnQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHsKCQkJCQlpZiAocnVudGltZXNbaV0uZXF1YWxzKHJ1bnRpbWUpKQoJCQkJCQlydW50aW1lQ29tYm8uc2VsZWN0KGkpOwoJCQkJfQoJCQkJCgkJCQlydW50aW1lQ29tYm8uYWRkU2VsZWN0aW9uTGlzdGVuZXIobmV3IFNlbGVjdGlvbkxpc3RlbmVyKCkgewoJCQkJCXB1YmxpYyB2b2lkIHdpZGdldFNlbGVjdGVkKFNlbGVjdGlvbkV2ZW50IGUpIHsKCQkJCQkJdHJ5IHsKCQkJCQkJCWlmICh1cGRhdGluZykKCQkJCQkJCQlyZXR1cm47CgkJCQkJCQl1cGRhdGluZyA9IHRydWU7CgkJCQkJCQlJUnVudGltZSBuZXdSdW50aW1lID0gcnVudGltZXNbcnVudGltZUNvbWJvLmdldFNlbGVjdGlvbkluZGV4KCldOwoJCQkJCQkJZ2V0Q29tbWFuZE1hbmFnZXIoKS5leGVjdXRlQ29tbWFuZChuZXcgU2V0U2VydmVyUnVudGltZUNvbW1hbmQoZ2V0U2VydmVyKCksIG5ld1J1bnRpbWUpKTsKCQkJCQkJCXVwZGF0aW5nID0gZmFsc2U7CgkJCQkJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBleCkgewoJCQkJCQkJLy8gaWdub3JlCgkJCQkJCX0KCQkJCQl9CgkJCQkJcHVibGljIHZvaWQgd2lkZ2V0RGVmYXVsdFNlbGVjdGVkKFNlbGVjdGlvbkV2ZW50IGUpIHsKCQkJCQkJd2lkZ2V0U2VsZWN0ZWQoZSk7CgkJCQkJfQoJCQkJfSk7CgkJCX0KCQkJCgkJCWNyZWF0ZUxhYmVsKHRvb2xraXQsIGNvbXBvc2l0ZSwgIiIpOwoJCQlIeXBlcmxpbmsgbGluayA9IHRvb2xraXQuY3JlYXRlSHlwZXJsaW5rKGNvbXBvc2l0ZSwgIkVkaXQgcnVudGltZSIsIFNXVC5OT05FKTsgLy8gVE9ETzogdHJhbnNsYXRlCgkJCS8vR3JpZERhdGEgZGF0YSA9IG5ldyBHcmlkRGF0YShHcmlkRGF0YS5IT1JJWk9OVEFMX0FMSUdOX0ZJTEwpOwoJCQkvL2xpbmsuc2V0TGF5b3V0RGF0YShkYXRhKTsKCQkJbGluay5hZGRIeXBlcmxpbmtMaXN0ZW5lcihuZXcgSUh5cGVybGlua0xpc3RlbmVyKCkgewoJCQkJcHVibGljIHZvaWQgbGlua0VudGVyZWQoSHlwZXJsaW5rRXZlbnQgZSkgewoJCQkJCS8vIGlnbm9yZQoJCQkJfQoKCQkJCXB1YmxpYyB2b2lkIGxpbmtFeGl0ZWQoSHlwZXJsaW5rRXZlbnQgZSkgewoJCQkJCS8vIGlnbm9yZQoJCQkJfQoKCQkJCXB1YmxpYyB2b2lkIGxpbmtBY3RpdmF0ZWQoSHlwZXJsaW5rRXZlbnQgZSkgewoJCQkJCWVkaXRSdW50aW1lKHJ1bnRpbWUpOwoJCQkJfQoJCQkJCgkJCX0pOwoJCX0KCQkKCQkvLyBzZXJ2ZXIgY29uZmlndXJhdGlvbiBwYXRoCgkJaWYgKHNlcnZlciAhPSBudWxsICYmIHNlcnZlci5nZXRTZXJ2ZXJUeXBlKCkuaGFzU2VydmVyQ29uZmlndXJhdGlvbigpKSB7CgkJCWNyZWF0ZUxhYmVsKHRvb2xraXQsIGNvbXBvc2l0ZSwgU2VydmVyVUlQbHVnaW4uZ2V0UmVzb3VyY2UoIiVzZXJ2ZXJFZGl0b3JPdmVydmlld1NlcnZlckNvbmZpZ3VyYXRpb25QYXRoIikpOwoJCQkKCQkJSUZvbGRlciBmb2xkZXIgPSBzZXJ2ZXIuZ2V0U2VydmVyQ29uZmlndXJhdGlvbigpOwoJCQlpZiAoZm9sZGVyID09IG51bGwpCgkJCQlzZXJ2ZXJDb25maWd1cmF0aW9uTmFtZSA9IHRvb2xraXQuY3JlYXRlTGFiZWwoY29tcG9zaXRlLCBTZXJ2ZXJVSVBsdWdpbi5nZXRSZXNvdXJjZSgiJWVsZW1lbnRVbmtub3duTmFtZSIpKTsKCQkJZWxzZQoJCQkJc2VydmVyQ29uZmlndXJhdGlvbk5hbWUgPSB0b29sa2l0LmNyZWF0ZUxhYmVsKGNvbXBvc2l0ZSwgIiIgKyBzZXJ2ZXIuZ2V0U2VydmVyQ29uZmlndXJhdGlvbigpLmdldEZ1bGxQYXRoKCkpOwoJCQlHcmlkRGF0YSBkYXRhID0gbmV3IEdyaWREYXRhKEdyaWREYXRhLkZJTExfSE9SSVpPTlRBTCk7CgkJCXNlcnZlckNvbmZpZ3VyYXRpb25OYW1lLnNldExheW91dERhdGEoZGF0YSk7CgkJfQoJCQoJCS8vIGF1dG8tcHVibGlzaAoJCWlmIChzZXJ2ZXIgIT0gbnVsbCkgewoJCQkvL0xhYmVsIGxhYmVsID0gY3JlYXRlTGFiZWwodG9vbGtpdCwgY29tcG9zaXRlLCBTZXJ2ZXJVSVBsdWdpbi5nZXRSZXNvdXJjZSgiJXNlcnZlckVkaXRvck92ZXJ2aWV3U2VydmVySG9zdG5hbWUiKSk7CgkJCS8vbGFiZWwuCgkJCQoJCQlhdXRvUHVibGlzaERlZmF1bHQgPSB0b29sa2l0LmNyZWF0ZUJ1dHRvbihjb21wb3NpdGUsIFNlcnZlclVJUGx1Z2luLmdldFJlc291cmNlKCIlc2VydmVyRWRpdG9yT3ZlcnZpZXdBdXRvUHVibGlzaERlZmF1bHQiKSwgU1dULlJBRElPKTsKCQkJR3JpZERhdGEgZGF0YSA9IG5ldyBHcmlkRGF0YShHcmlkRGF0YS5GSUxMX0hPUklaT05UQUwpOwoJCQlkYXRhLmhvcml6b250YWxTcGFuID0gMjsKCQkJYXV0b1B1Ymxpc2hEZWZhdWx0LnNldExheW91dERhdGEoZGF0YSk7CgkJCVNlcnZlciBzdnIgPSAoU2VydmVyKSBzZXJ2ZXI7CgkJCWF1dG9QdWJsaXNoRGVmYXVsdC5zZXRTZWxlY3Rpb24oc3ZyLmdldEF1dG9QdWJsaXNoRGVmYXVsdCgpKTsKCQkJCgkJCWF1dG9QdWJsaXNoT3ZlcnJpZGUgPSB0b29sa2l0LmNyZWF0ZUJ1dHRvbihjb21wb3NpdGUsIFNlcnZlclVJUGx1Z2luLmdldFJlc291cmNlKCIlc2VydmVyRWRpdG9yT3ZlcnZpZXdBdXRvUHVibGlzaE92ZXJyaWRlIiksIFNXVC5SQURJTyk7CgkJCWF1dG9QdWJsaXNoT3ZlcnJpZGUuc2V0U2VsZWN0aW9uKCFzdnIuZ2V0QXV0b1B1Ymxpc2hEZWZhdWx0KCkpOwoJCQkKCQkJYXV0b1B1Ymxpc2hPdmVycmlkZS5hZGRTZWxlY3Rpb25MaXN0ZW5lcihuZXcgU2VsZWN0aW9uQWRhcHRlcigpIHsKCQkJCXB1YmxpYyB2b2lkIHdpZGdldFNlbGVjdGVkKFNlbGVjdGlvbkV2ZW50IGUpIHsKCQkJCQlpZiAodXBkYXRpbmcpCgkJCQkJCXJldHVybjsKCQkJCQl1cGRhdGluZyA9IHRydWU7CgkJCQkJZ2V0Q29tbWFuZE1hbmFnZXIoKS5leGVjdXRlQ29tbWFuZChuZXcgU2V0U2VydmVyQXV0b1B1Ymxpc2hEZWZhdWx0Q29tbWFuZChnZXRTZXJ2ZXIoKSwgYXV0b1B1Ymxpc2hEZWZhdWx0LmdldFNlbGVjdGlvbigpKSk7CgkJCQkJdXBkYXRpbmcgPSBmYWxzZTsKCQkJCQlhdXRvUHVibGlzaFRpbWUuc2V0RW5hYmxlZChhdXRvUHVibGlzaE92ZXJyaWRlLmdldFNlbGVjdGlvbigpKTsKCQkJCX0KCQkJfSk7CgkJCQoJCQkvL2F1dG9QdWJsaXNoVGltZSA9IHRvb2xraXQuY3JlYXRlVGV4dChjb21wb3NpdGUsIHN2ci5nZXRBdXRvUHVibGlzaFRpbWUoKSArICIiKTsKCQkJYXV0b1B1Ymxpc2hUaW1lID0gbmV3IFNwaW5uZXIoY29tcG9zaXRlLCBTV1QuQk9SREVSKTsKCQkJYXV0b1B1Ymxpc2hUaW1lLnNldE1pbmltdW0oMCk7CgkJCWF1dG9QdWJsaXNoVGltZS5zZXRNYXhpbXVtKDEyMCk7CgkJCWF1dG9QdWJsaXNoVGltZS5zZXRTZWxlY3Rpb24oc3ZyLmdldEF1dG9QdWJsaXNoVGltZSgpKTsKCQkJZGF0YSA9IG5ldyBHcmlkRGF0YShHcmlkRGF0YS5GSUxMX0hPUklaT05UQUwpOwoJCQlhdXRvUHVibGlzaFRpbWUuc2V0TGF5b3V0RGF0YShkYXRhKTsKCQkJYXV0b1B1Ymxpc2hUaW1lLnNldEVuYWJsZWQoYXV0b1B1Ymxpc2hPdmVycmlkZS5nZXRTZWxlY3Rpb24oKSk7CgkJCWF1dG9QdWJsaXNoVGltZS5hZGRNb2RpZnlMaXN0ZW5lcihuZXcgTW9kaWZ5TGlzdGVuZXIoKSB7CgkJCQlwdWJsaWMgdm9pZCBtb2RpZnlUZXh0KE1vZGlmeUV2ZW50IGUpIHsKCQkJCQlpZiAodXBkYXRpbmcpCgkJCQkJCXJldHVybjsKCQkJCQl1cGRhdGluZyA9IHRydWU7CgkJCQkJdHJ5IHsKCQkJCQkJZ2V0Q29tbWFuZE1hbmFnZXIoKS5leGVjdXRlQ29tbWFuZChuZXcgU2V0U2VydmVyQXV0b1B1Ymxpc2hUaW1lQ29tbWFuZChnZXRTZXJ2ZXIoKSwgYXV0b1B1Ymxpc2hUaW1lLmdldFNlbGVjdGlvbigpKSk7CgkJCQkJfSBjYXRjaCAoRXhjZXB0aW9uIGV4KSB7CgkJCQkJCS8vIGlnbm9yZQoJCQkJCX0KCQkJCQl1cGRhdGluZyA9IGZhbHNlOwoJCQkJfQoJCQl9KTsKCQl9CgkJCgkJaW5zZXJ0U2VjdGlvbnMobGVmdENvbHVtbkNvbXAsICJvcmcuZWNsaXBzZS53c3Quc2VydmVyLmVkaXRvci5vdmVydmlldy5sZWZ0Iik7CgkJCgkJLy8gcmlnaHQgY29sdW1uCgkJQ29tcG9zaXRlIHJpZ2h0Q29sdW1uQ29tcCA9IHRvb2xraXQuY3JlYXRlQ29tcG9zaXRlKGNvbHVtbkNvbXApOwoJCWxheW91dCA9IG5ldyBHcmlkTGF5b3V0KCk7CgkJbGF5b3V0Lm1hcmdpbkhlaWdodCA9IDA7CgkJbGF5b3V0Lm1hcmdpbldpZHRoID0gMDsKCQlsYXlvdXQudmVydGljYWxTcGFjaW5nID0gMTA7CgkJbGF5b3V0Lmhvcml6b250YWxTcGFjaW5nID0gMDsKCQlyaWdodENvbHVtbkNvbXAuc2V0TGF5b3V0KGxheW91dCk7CgkJcmlnaHRDb2x1bW5Db21wLnNldExheW91dERhdGEobmV3IEdyaWREYXRhKEdyaWREYXRhLkZJTExfSE9SSVpPTlRBTCB8IEdyaWREYXRhLlZFUlRJQ0FMX0FMSUdOX0ZJTEwpKTsKCQkKCQlpbnNlcnRTZWN0aW9ucyhyaWdodENvbHVtbkNvbXAsICJvcmcuZWNsaXBzZS53c3Quc2VydmVyLmVkaXRvci5vdmVydmlldy5yaWdodCIpOwoJCQoJCWZvcm0uc2V0Q29udGVudChjb2x1bW5Db21wKTsKCQlmb3JtLnJlZmxvdyh0cnVlKTsKCgkJaW5pdGlhbGl6ZSgpOwoJfQoJCglwcm90ZWN0ZWQgdm9pZCBlZGl0UnVudGltZShJUnVudGltZSBydW50aW1lKSB7CgkJSVJ1bnRpbWVXb3JraW5nQ29weSBydW50aW1lV29ya2luZ0NvcHkgPSBydW50aW1lLmNyZWF0ZVdvcmtpbmdDb3B5KCk7CgkJaWYgKHNob3dXaXphcmQocnVudGltZVdvcmtpbmdDb3B5KSAhPSBXaW5kb3cuQ0FOQ0VMKSB7CgkJCXRyeSB7CgkJCQlydW50aW1lV29ya2luZ0NvcHkuc2F2ZShmYWxzZSwgbmV3IE51bGxQcm9ncmVzc01vbml0b3IoKSk7CgkJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBleCkgewoJCQkJLy8gaWdub3JlCgkJCX0KCQl9Cgl9CgkKCXByb3RlY3RlZCBpbnQgc2hvd1dpemFyZChmaW5hbCBJUnVudGltZVdvcmtpbmdDb3B5IHJ1bnRpbWVXb3JraW5nQ29weSkgewoJCVN0cmluZyB0aXRsZSA9IFNlcnZlclVJUGx1Z2luLmdldFJlc291cmNlKCIld2l6RWRpdFJ1bnRpbWVXaXphcmRUaXRsZSIpOwoJCWZpbmFsIFdpemFyZEZyYWdtZW50IGZyYWdtZW50MiA9IFNlcnZlclVJUGx1Z2luLmdldFdpemFyZEZyYWdtZW50KHJ1bnRpbWVXb3JraW5nQ29weS5nZXRSdW50aW1lVHlwZSgpLmdldElkKCkpOwoJCWlmIChmcmFnbWVudDIgPT0gbnVsbCkKCQkJcmV0dXJuIFdpbmRvdy5DQU5DRUw7CgkJCgkJV2l6YXJkRnJhZ21lbnQgZnJhZ21lbnQgPSBuZXcgV2l6YXJkRnJhZ21lbnQoKSB7CgkJCXByb3RlY3RlZCB2b2lkIGNyZWF0ZUNoaWxkRnJhZ21lbnRzKExpc3QgbGlzdCkgewoJCQkJbGlzdC5hZGQobmV3IFdpemFyZEZyYWdtZW50KCkgewoJCQkJCXB1YmxpYyB2b2lkIGVudGVyKCkgewoJCQkJCQlnZXRUYXNrTW9kZWwoKS5wdXRPYmplY3QoVGFza01vZGVsLlRBU0tfUlVOVElNRSwgcnVudGltZVdvcmtpbmdDb3B5KTsKCQkJCQl9CgkJCQl9KTsKCQkJCWxpc3QuYWRkKGZyYWdtZW50Mik7CgkJCQlsaXN0LmFkZChuZXcgRmluaXNoV2l6YXJkRnJhZ21lbnQobmV3IFNhdmVSdW50aW1lVGFzaygpKSk7CgkJCX0KCQl9OwoJCQoJCVRhc2tXaXphcmQgd2l6YXJkID0gbmV3IFRhc2tXaXphcmQodGl0bGUsIGZyYWdtZW50KTsKCQl3aXphcmQuc2V0Rm9yY2VQcmV2aW91c0FuZE5leHRCdXR0b25zKHRydWUpOwoJCUNsb3NhYmxlV2l6YXJkRGlhbG9nIGRpYWxvZyA9IG5ldyBDbG9zYWJsZVdpemFyZERpYWxvZyhnZXRFZGl0b3JTaXRlKCkuZ2V0U2hlbGwoKSwgd2l6YXJkKTsKCQlyZXR1cm4gZGlhbG9nLm9wZW4oKTsKCX0KCQoJcHJvdGVjdGVkIHZvaWQgdXBkYXRlUnVudGltZUNvbWJvKCkgewoJCUlSdW50aW1lVHlwZSBydW50aW1lVHlwZSA9IHNlcnZlci5nZXRTZXJ2ZXJUeXBlKCkuZ2V0UnVudGltZVR5cGUoKTsKCQlydW50aW1lcyA9IFNlcnZlclVJUGx1Z2luLmdldFJ1bnRpbWVzKHJ1bnRpbWVUeXBlKTsKCQkKCQlpZiAoU29ja2V0VXRpbC5pc0xvY2FsaG9zdChzZXJ2ZXIuZ2V0SG9zdCgpKSAmJiBydW50aW1lcyAhPSBudWxsKSB7CgkJCUxpc3QgcnVudGltZXMyID0gbmV3IEFycmF5TGlzdCgpOwoJCQlpbnQgc2l6ZSA9IHJ1bnRpbWVzLmxlbmd0aDsKCQkJZm9yIChpbnQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHsKCQkJCUlSdW50aW1lIHJ1bnRpbWUyID0gcnVudGltZXNbaV07CgkJCQlpZiAoIXJ1bnRpbWUyLmlzU3R1YigpKQoJCQkJCXJ1bnRpbWVzMi5hZGQocnVudGltZTIpOwoJCQl9CgkJCXJ1bnRpbWVzID0gbmV3IElSdW50aW1lW3J1bnRpbWVzMi5zaXplKCldOwoJCQlydW50aW1lczIudG9BcnJheShydW50aW1lcyk7CgkJfQoJCQoJCWludCBzaXplID0gcnVudGltZXMubGVuZ3RoOwoJCVN0cmluZ1tdIGl0ZW1zID0gbmV3IFN0cmluZ1tzaXplXTsKCQlmb3IgKGludCBpID0gMDsgaSA8IHNpemU7IGkrKykKCQkJaXRlbXNbaV0gPSBydW50aW1lc1tpXS5nZXROYW1lKCk7CgkJCgkJcnVudGltZUNvbWJvLnNldEl0ZW1zKGl0ZW1zKTsKCX0KCglwcm90ZWN0ZWQgTGFiZWwgY3JlYXRlTGFiZWwoRm9ybVRvb2xraXQgdG9vbGtpdCwgQ29tcG9zaXRlIHBhcmVudCwgU3RyaW5nIHRleHQpIHsKCQlMYWJlbCBsYWJlbCA9IHRvb2xraXQuY3JlYXRlTGFiZWwocGFyZW50LCB0ZXh0KTsKCQlsYWJlbC5zZXRGb3JlZ3JvdW5kKHRvb2xraXQuZ2V0Q29sb3JzKCkuZ2V0Q29sb3IoRm9ybUNvbG9ycy5USVRMRSkpOwoJCXJldHVybiBsYWJlbDsKCX0KCQoJcHVibGljIHZvaWQgZGlzcG9zZSgpIHsKCQlzdXBlci5kaXNwb3NlKCk7CgkJCgkJaWYgKHNlcnZlciAhPSBudWxsKQoJCQlzZXJ2ZXIucmVtb3ZlUHJvcGVydHlDaGFuZ2VMaXN0ZW5lcihsaXN0ZW5lcik7Cgl9CgkKCS8qIChub24tSmF2YWRvYykKCSAqIEluaXRpYWxpemVzIHRoZSBlZGl0b3IgcGFydCB3aXRoIGEgc2l0ZSBhbmQgaW5wdXQuCgkgKi8KCXB1YmxpYyB2b2lkIGluaXQoSUVkaXRvclNpdGUgc2l0ZSwgSUVkaXRvcklucHV0IGlucHV0KSB7CgkJc3VwZXIuaW5pdChzaXRlLCBpbnB1dCk7CgkJCgkJYWRkQ2hhbmdlTGlzdGVuZXIoKTsKCQlpbml0aWFsaXplKCk7Cgl9CgkKCS8qKgoJICogSW5pdGlhbGl6ZSB0aGUgZmllbGRzIGluIHRoaXMgZWRpdG9yLgoJICovCglwcm90ZWN0ZWQgdm9pZCBpbml0aWFsaXplKCkgewoJCWlmIChzZXJ2ZXJOYW1lID09IG51bGwpCgkJCXJldHVybjsKCQl1cGRhdGluZyA9IHRydWU7CgkJCgkJaWYgKHNlcnZlciAhPSBudWxsKSB7CgkJCXNlcnZlck5hbWUuc2V0VGV4dChzZXJ2ZXIuZ2V0TmFtZSgpKTsKCQkJaWYgKHJlYWRPbmx5KQoJCQkJc2VydmVyTmFtZS5zZXRFZGl0YWJsZShmYWxzZSk7CgkJCWVsc2UKCQkJCXNlcnZlck5hbWUuc2V0RWRpdGFibGUodHJ1ZSk7CgkJfQoJCQoJCXVwZGF0aW5nID0gZmFsc2U7Cgl9CgkKCS8vcHJvdGVjdGVkIHZvaWQgdmFsaWRhdGUoKSB7IH0KCgkvKgoJICogQHNlZSBJV29ya2JlbmNoUGFydCNzZXRGb2N1cygpCgkgKi8KCXB1YmxpYyB2b2lkIHNldEZvY3VzKCkgewoJCWlmIChzZXJ2ZXJOYW1lICE9IG51bGwpCgkJCXNlcnZlck5hbWUuc2V0Rm9jdXMoKTsKCQllbHNlIGlmIChzZXJ2ZXJDb25maWd1cmF0aW9uTmFtZSAhPSBudWxsKQoJCQlzZXJ2ZXJDb25maWd1cmF0aW9uTmFtZS5zZXRGb2N1cygpOwoJfQp9