LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogQ29weXJpZ2h0IChjKSAyMDAzLCAyMDA1IElCTSBDb3Jwb3JhdGlvbiBhbmQgb3RoZXJzLgogKiBBbGwgcmlnaHRzIHJlc2VydmVkLiBUaGlzIHByb2dyYW0gYW5kIHRoZSBhY2NvbXBhbnlpbmcgbWF0ZXJpYWxzCiAqIGFyZSBtYWRlIGF2YWlsYWJsZSB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEVjbGlwc2UgUHVibGljIExpY2Vuc2UgdjEuMAogKiB3aGljaCBhY2NvbXBhbmllcyB0aGlzIGRpc3RyaWJ1dGlvbiwgYW5kIGlzIGF2YWlsYWJsZSBhdAogKiBodHRwOi8vd3d3LmVjbGlwc2Uub3JnL2xlZ2FsL2VwbC12MTAuaHRtbAqgKgogKiBDb250cmlidXRvcnM6CiAqICAgIElCTSBDb3Jwb3JhdGlvbiAtIEluaXRpYWwgQVBJIGFuZCBpbXBsZW1lbnRhdGlvbgogKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KcGFja2FnZSBvcmcuZWNsaXBzZS5qc3Quc2VydmVyLnRvbWNhdC5jb3JlLmludGVybmFsOwoKaW1wb3J0IGphdmEuaW8uRmlsZTsKaW1wb3J0IGphdmEuaW8uRmlsZUlucHV0U3RyZWFtOwppbXBvcnQgamF2YS5pby5GaWxlT3V0cHV0U3RyZWFtOwppbXBvcnQgamF2YS51dGlsLkFycmF5TGlzdDsKaW1wb3J0IGphdmEudXRpbC5JdGVyYXRvcjsKaW1wb3J0IGphdmEudXRpbC5MaXN0OwppbXBvcnQgamF2YS51dGlsLlByb3BlcnRpZXM7CgppbXBvcnQgb3JnLmVjbGlwc2UuY29yZS5ydW50aW1lLio7CmltcG9ydCBvcmcuZWNsaXBzZS5kZWJ1Zy5jb3JlLio7CmltcG9ydCBvcmcuZWNsaXBzZS5kZWJ1Zy5jb3JlLm1vZGVsLklQcm9jZXNzOwppbXBvcnQgb3JnLmVjbGlwc2UuamR0LmxhdW5jaGluZy5JSmF2YUxhdW5jaENvbmZpZ3VyYXRpb25Db25zdGFudHM7CmltcG9ydCBvcmcuZWNsaXBzZS5qZHQubGF1bmNoaW5nLklSdW50aW1lQ2xhc3NwYXRoRW50cnk7CmltcG9ydCBvcmcuZWNsaXBzZS5qZHQubGF1bmNoaW5nLklWTUluc3RhbGw7CmltcG9ydCBvcmcuZWNsaXBzZS5qZHQubGF1bmNoaW5nLkphdmFSdW50aW1lOwppbXBvcnQgb3JnLmVjbGlwc2UuanN0LnNlcnZlci5jb3JlLklXZWJNb2R1bGU7CmltcG9ydCBvcmcuZWNsaXBzZS5vc2dpLnV0aWwuTkxTOwoKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIuY29yZS4qOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNlcnZlci5jb3JlLmludGVybmFsLlNlcnZlcjsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIuY29yZS5tb2RlbC4qOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNlcnZlci5jb3JlLnV0aWwuU29ja2V0VXRpbDsKLyoqCiAqIEdlbmVyaWMgVG9tY2F0IHNlcnZlci4KICovCnB1YmxpYyBjbGFzcyBUb21jYXRTZXJ2ZXJCZWhhdmlvdXIgZXh0ZW5kcyBTZXJ2ZXJCZWhhdmlvdXJEZWxlZ2F0ZSBpbXBsZW1lbnRzIElUb21jYXRTZXJ2ZXJCZWhhdmlvdXIgewoJcHJpdmF0ZSBzdGF0aWMgZmluYWwgU3RyaW5nIEFUVFJfU1RPUCA9ICJzdG9wLXNlcnZlciI7CgoJLy8gdGhlIHRocmVhZCB1c2VkIHRvIHBpbmcgdGhlIHNlcnZlciB0byBjaGVjayBmb3Igc3RhcnR1cAoJcHJvdGVjdGVkIHRyYW5zaWVudCBQaW5nVGhyZWFkIHBpbmcgPSBudWxsOwoJcHJvdGVjdGVkIHRyYW5zaWVudCBJUHJvY2VzcyBwcm9jZXNzOwoJcHJvdGVjdGVkIHRyYW5zaWVudCBJRGVidWdFdmVudFNldExpc3RlbmVyIHByb2Nlc3NMaXN0ZW5lcjsKCgkvKioKCSAqIFRvbWNhdFNlcnZlci4KCSAqLwoJcHVibGljIFRvbWNhdFNlcnZlckJlaGF2aW91cigpIHsKCQlzdXBlcigpOwoJfQoKCXB1YmxpYyB2b2lkIGluaXRpYWxpemUoSVByb2dyZXNzTW9uaXRvciBtb25pdG9yKSB7CgkJLy8gZG8gbm90aGluZwoJfQoKCXB1YmxpYyBUb21jYXRSdW50aW1lIGdldFRvbWNhdFJ1bnRpbWUoKSB7CgkJaWYgKGdldFNlcnZlcigpLmdldFJ1bnRpbWUoKSA9PSBudWxsKQoJCQlyZXR1cm4gbnVsbDsKCQkKCQlyZXR1cm4gKFRvbWNhdFJ1bnRpbWUpIGdldFNlcnZlcigpLmdldFJ1bnRpbWUoKS5sb2FkQWRhcHRlcihUb21jYXRSdW50aW1lLmNsYXNzLCBudWxsKTsKCX0KCQoJcHVibGljIElUb21jYXRWZXJzaW9uSGFuZGxlciBnZXRUb21jYXRWZXJzaW9uSGFuZGxlcigpIHsKCQlpZiAoZ2V0U2VydmVyKCkuZ2V0UnVudGltZSgpID09IG51bGwgfHwgZ2V0VG9tY2F0UnVudGltZSgpID09IG51bGwpCgkJCXJldHVybiBudWxsOwoKCQlyZXR1cm4gZ2V0VG9tY2F0UnVudGltZSgpLmdldFZlcnNpb25IYW5kbGVyKCk7Cgl9CgkKCXB1YmxpYyBUb21jYXRDb25maWd1cmF0aW9uIGdldFRvbWNhdENvbmZpZ3VyYXRpb24oKSB0aHJvd3MgQ29yZUV4Y2VwdGlvbiB7CgkJcmV0dXJuIGdldFRvbWNhdFNlcnZlcigpLmdldFRvbWNhdENvbmZpZ3VyYXRpb24oKTsKCX0KCglwdWJsaWMgVG9tY2F0U2VydmVyIGdldFRvbWNhdFNlcnZlcigpIHsKCQlyZXR1cm4gKFRvbWNhdFNlcnZlcikgZ2V0U2VydmVyKCkuZ2V0QWRhcHRlcihUb21jYXRTZXJ2ZXIuY2xhc3MpOwoJfQoKCS8qKgoJICogUmV0dXJuIHRoZSBydW50aW1lIGNsYXNzIG5hbWUuCgkgKgoJICogQHJldHVybiB0aGUgY2xhc3MgbmFtZQoJICovCglwdWJsaWMgU3RyaW5nIGdldFJ1bnRpbWVDbGFzcygpIHsKCQlyZXR1cm4gZ2V0VG9tY2F0VmVyc2lvbkhhbmRsZXIoKS5nZXRSdW50aW1lQ2xhc3MoKTsKCX0KCQoJLyoqCgkgKiBSZXR1cm5zIHRoZSBydW50aW1lIGJhc2UgcGF0aCBmb3IgcmVsYXRpdmUgcGF0aHMgaW4gdGhlIHNlcnZlcgoJICogY29uZmlndXJhdGlvbi4KCSAqIAoJICogQHJldHVybiB0aGUgYmFzZSBwYXRoCgkgKi8KCXB1YmxpYyBJUGF0aCBnZXRSdW50aW1lQmFzZURpcmVjdG9yeSgpIHsKCQlyZXR1cm4gZ2V0VG9tY2F0VmVyc2lvbkhhbmRsZXIoKS5nZXRSdW50aW1lQmFzZURpcmVjdG9yeSh0aGlzKTsKCX0KCgkvKioKCSAqIFJldHVybiB0aGUgcHJvZ3JhbSdzIHJ1bnRpbWUgYXJndW1lbnRzIHRvIHN0YXJ0IG9yIHN0b3AuCgkgKgoJICogQHBhcmFtIHN0YXJ0aW5nIHRydWUgaWYgc3RhcnRpbmcKCSAqIEByZXR1cm4gYW4gYXJyYXkgb2YgcnVudGltZSBwcm9ncmFtIGFyZ3VtZW50cwoJICovCglwcm90ZWN0ZWQgU3RyaW5nW10gZ2V0UnVudGltZVByb2dyYW1Bcmd1bWVudHMoYm9vbGVhbiBzdGFydGluZykgewoJCUlQYXRoIGNvbmZpZ1BhdGggPSBudWxsOwoJCWlmIChnZXRUb21jYXRTZXJ2ZXIoKS5pc1Rlc3RFbnZpcm9ubWVudCgpKQoJCQljb25maWdQYXRoID0gZ2V0VGVtcERpcmVjdG9yeSgpOwoJCXJldHVybiBnZXRUb21jYXRWZXJzaW9uSGFuZGxlcigpLmdldFJ1bnRpbWVQcm9ncmFtQXJndW1lbnRzKGNvbmZpZ1BhdGgsIGdldFRvbWNhdFNlcnZlcigpLmlzRGVidWcoKSwgc3RhcnRpbmcpOwoJfQoKCS8qKgoJICogUmV0dXJuIHRoZSBydW50aW1lIChWTSkgYXJndW1lbnRzLgoJICoKCSAqIEByZXR1cm4gYW4gYXJyYXkgb2YgcnVudGltZSBhcmd1bWVudHMKCSAqLwoJcHJvdGVjdGVkIFN0cmluZ1tdIGdldFJ1bnRpbWVWTUFyZ3VtZW50cygpIHsKCQlJUGF0aCBpbnN0YWxsUGF0aCA9IGdldFNlcnZlcigpLmdldFJ1bnRpbWUoKS5nZXRMb2NhdGlvbigpOwoJCUlQYXRoIGNvbmZpZ1BhdGggPSBudWxsOwoJCWlmIChnZXRUb21jYXRTZXJ2ZXIoKS5pc1Rlc3RFbnZpcm9ubWVudCgpKQoJCQljb25maWdQYXRoID0gZ2V0VGVtcERpcmVjdG9yeSgpOwoJCWVsc2UKCQkJY29uZmlnUGF0aCA9IGluc3RhbGxQYXRoOwoJCXJldHVybiBnZXRUb21jYXRWZXJzaW9uSGFuZGxlcigpLmdldFJ1bnRpbWVWTUFyZ3VtZW50cyhpbnN0YWxsUGF0aCwgY29uZmlnUGF0aCwKCQkJCWdldFRvbWNhdFNlcnZlcigpLmlzVGVzdEVudmlyb25tZW50KCksIGdldFRvbWNhdFNlcnZlcigpLmlzU2VjdXJlKCkpOwoJfQoJCglwcm90ZWN0ZWQgc3RhdGljIFN0cmluZyByZW5kZXJDb21tYW5kTGluZShTdHJpbmdbXSBjb21tYW5kTGluZSwgU3RyaW5nIHNlcGFyYXRvcikgewoJCWlmIChjb21tYW5kTGluZSA9PSBudWxsIHx8IGNvbW1hbmRMaW5lLmxlbmd0aCA8IDEpCgkJCXJldHVybiAiIjsKCQlTdHJpbmdCdWZmZXIgYnVmPSBuZXcgU3RyaW5nQnVmZmVyKGNvbW1hbmRMaW5lWzBdKTsKCQlmb3IgKGludCBpID0gMTsgaSA8IGNvbW1hbmRMaW5lLmxlbmd0aDsgaSsrKSB7CgkJCWJ1Zi5hcHBlbmQoc2VwYXJhdG9yKTsKCQkJYnVmLmFwcGVuZChjb21tYW5kTGluZVtpXSk7CgkJfQkKCQlyZXR1cm4gYnVmLnRvU3RyaW5nKCk7Cgl9CgoJcHVibGljIHZvaWQgc2V0UHJvY2VzcyhmaW5hbCBJUHJvY2VzcyBuZXdQcm9jZXNzKSB7CgkJaWYgKHByb2Nlc3MgIT0gbnVsbCkKCQkJcmV0dXJuOwoKCQlwcm9jZXNzID0gbmV3UHJvY2VzczsKCQlpZiAocHJvY2Vzc0xpc3RlbmVyICE9IG51bGwpCgkJCURlYnVnUGx1Z2luLmdldERlZmF1bHQoKS5yZW1vdmVEZWJ1Z0V2ZW50TGlzdGVuZXIocHJvY2Vzc0xpc3RlbmVyKTsKCQlpZiAobmV3UHJvY2VzcyA9PSBudWxsKQoJCQlyZXR1cm47CgkJCgkJcHJvY2Vzc0xpc3RlbmVyID0gbmV3IElEZWJ1Z0V2ZW50U2V0TGlzdGVuZXIoKSB7CgkJCXB1YmxpYyB2b2lkIGhhbmRsZURlYnVnRXZlbnRzKERlYnVnRXZlbnRbXSBldmVudHMpIHsKCQkJCWlmIChldmVudHMgIT0gbnVsbCkgewoJCQkJCWludCBzaXplID0gZXZlbnRzLmxlbmd0aDsKCQkJCQlmb3IgKGludCBpID0gMDsgaSA8IHNpemU7IGkrKykgewoJCQkJCQlpZiAocHJvY2VzcyAhPSBudWxsICYmIHByb2Nlc3MuZXF1YWxzKGV2ZW50c1tpXS5nZXRTb3VyY2UoKSkgJiYgZXZlbnRzW2ldLmdldEtpbmQoKSA9PSBEZWJ1Z0V2ZW50LlRFUk1JTkFURSkgewoJCQkJCQkJRGVidWdQbHVnaW4uZ2V0RGVmYXVsdCgpLnJlbW92ZURlYnVnRXZlbnRMaXN0ZW5lcih0aGlzKTsKCQkJCQkJCXN0b3BJbXBsKCk7CgkJCQkJCX0KCQkJCQl9CgkJCQl9CgkJCX0KCQl9OwoJCURlYnVnUGx1Z2luLmdldERlZmF1bHQoKS5hZGREZWJ1Z0V2ZW50TGlzdGVuZXIocHJvY2Vzc0xpc3RlbmVyKTsKCX0KCQoJcHJvdGVjdGVkIHZvaWQgc2V0U2VydmVyU3RhcnRlZCgpIHsKCQlzZXRTZXJ2ZXJTdGF0ZShJU2VydmVyLlNUQVRFX1NUQVJURUQpOwoJfQoKCXByb3RlY3RlZCB2b2lkIHN0b3BJbXBsKCkgewoJCWlmIChwaW5nICE9IG51bGwpIHsKCQkJcGluZy5zdG9wKCk7CgkJCXBpbmcgPSBudWxsOwoJCX0KCQlpZiAocHJvY2VzcyAhPSBudWxsKSB7CgkJCXByb2Nlc3MgPSBudWxsOwoJCQlEZWJ1Z1BsdWdpbi5nZXREZWZhdWx0KCkucmVtb3ZlRGVidWdFdmVudExpc3RlbmVyKHByb2Nlc3NMaXN0ZW5lcik7CgkJCXByb2Nlc3NMaXN0ZW5lciA9IG51bGw7CgkJfQoJCXNldFNlcnZlclN0YXRlKElTZXJ2ZXIuU1RBVEVfU1RPUFBFRCk7Cgl9CgoJcHJvdGVjdGVkIHZvaWQgcHVibGlzaFNlcnZlcihpbnQga2luZCwgSVByb2dyZXNzTW9uaXRvciBtb25pdG9yKSB0aHJvd3MgQ29yZUV4Y2VwdGlvbiB7CgkJSVBhdGggaW5zdGFsbERpciA9IGdldFNlcnZlcigpLmdldFJ1bnRpbWUoKS5nZXRMb2NhdGlvbigpOwoJCUlQYXRoIGNvbmZEaXIgPSBudWxsOwoJCWlmIChnZXRUb21jYXRTZXJ2ZXIoKS5pc1Rlc3RFbnZpcm9ubWVudCgpKSB7CgkJCWNvbmZEaXIgPSBnZXRUZW1wRGlyZWN0b3J5KCk7CgkJCUlTdGF0dXMgc3RhdHVzID0gZ2V0VG9tY2F0Q29uZmlndXJhdGlvbigpLnByZXBhcmVSdW50aW1lRGlyZWN0b3J5KGNvbmZEaXIpOwoJCQlpZiAoc3RhdHVzICE9IG51bGwgJiYgIXN0YXR1cy5pc09LKCkpCgkJCQl0aHJvdyBuZXcgQ29yZUV4Y2VwdGlvbihzdGF0dXMpOwovKgkJCUZpbGUgdGVtcCA9IGNvbmZEaXIuYXBwZW5kKCJjb25mIikudG9GaWxlKCk7CgkJCWlmICghdGVtcC5leGlzdHMoKSkKCQkJCXRlbXAubWtkaXJzKCk7Ki8KCQl9IGVsc2UKCQkJY29uZkRpciA9IGluc3RhbGxEaXI7CgoJCW1vbml0b3IgPSBQcm9ncmVzc1V0aWwuZ2V0TW9uaXRvckZvcihtb25pdG9yKTsKCQltb25pdG9yLmJlZ2luVGFzayhNZXNzYWdlcy5wdWJsaXNoU2VydmVyVGFzaywgNTAwKTsKCQkKCQlJU3RhdHVzIHN0YXR1cyA9IGdldFRvbWNhdENvbmZpZ3VyYXRpb24oKS5jbGVhbnVwU2VydmVyKGNvbmZEaXIsIGluc3RhbGxEaXIsIFByb2dyZXNzVXRpbC5nZXRTdWJNb25pdG9yRm9yKG1vbml0b3IsIDEwMCkpOwoJCWlmIChzdGF0dXMgIT0gbnVsbCAmJiAhc3RhdHVzLmlzT0soKSkKCQkJdGhyb3cgbmV3IENvcmVFeGNlcHRpb24oc3RhdHVzKTsKCQkKCQlzdGF0dXMgPSBnZXRUb21jYXRDb25maWd1cmF0aW9uKCkuYmFja3VwQW5kUHVibGlzaChjb25mRGlyLCAhZ2V0VG9tY2F0U2VydmVyKCkuaXNUZXN0RW52aXJvbm1lbnQoKSwgUHJvZ3Jlc3NVdGlsLmdldFN1Yk1vbml0b3JGb3IobW9uaXRvciwgNDAwKSk7CgkJaWYgKHN0YXR1cyAhPSBudWxsICYmICFzdGF0dXMuaXNPSygpKQoJCQl0aHJvdyBuZXcgQ29yZUV4Y2VwdGlvbihzdGF0dXMpOwoJCQoJCW1vbml0b3IuZG9uZSgpOwoJCQoJCXNldFNlcnZlclB1Ymxpc2hTdGF0ZShJU2VydmVyLlBVQkxJU0hfU1RBVEVfTk9ORSk7Cgl9CgoJLyoKCSAqIFB1Ymxpc2hlcyB0aGUgZ2l2ZW4gbW9kdWxlIHRvIHRoZSBzZXJ2ZXIuCgkgKi8KCXByb3RlY3RlZCB2b2lkIHB1Ymxpc2hNb2R1bGUoaW50IGtpbmQsIGludCBkZWx0YUtpbmQsIElNb2R1bGVbXSBtb2R1bGVUcmVlLCBJUHJvZ3Jlc3NNb25pdG9yIG1vbml0b3IpIHRocm93cyBDb3JlRXhjZXB0aW9uIHsKCQlpZiAoZ2V0VG9tY2F0U2VydmVyKCkuaXNUZXN0RW52aXJvbm1lbnQoKSkKCQkJcmV0dXJuOwoKCQlJUGF0aCBwYXRoID0gZ2V0VGVtcERpcmVjdG9yeSgpLmFwcGVuZCgicHVibGlzaC50eHQiKTsKCQlQcm9wZXJ0aWVzIHAgPSBuZXcgUHJvcGVydGllcygpOwoJCXRyeSB7CgkJCXAubG9hZChuZXcgRmlsZUlucHV0U3RyZWFtKHBhdGgudG9GaWxlKCkpKTsKCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkvLyBpZ25vcmUKCQl9CgkJCgkJSU1vZHVsZSBtb2R1bGUgPSBtb2R1bGVUcmVlWzBdOwoJCQoJCWlmIChkZWx0YUtpbmQgPT0gUkVNT1ZFRCkgewoJCQl0cnkgewoJCQkJU3RyaW5nIHB1Ymxpc2hQYXRoID0gKFN0cmluZykgcC5nZXQobW9kdWxlLmdldElkKCkpOwoJCQkJRmlsZVV0aWwuZGVsZXRlRGlyZWN0b3J5KG5ldyBGaWxlKHB1Ymxpc2hQYXRoKSwgbW9uaXRvcik7CgkJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCQl0aHJvdyBuZXcgQ29yZUV4Y2VwdGlvbihuZXcgU3RhdHVzKElTdGF0dXMuV0FSTklORywgVG9tY2F0UGx1Z2luLlBMVUdJTl9JRCwgMCwgIkNvdWxkIG5vdCByZW1vdmUgbW9kdWxlIiwgZSkpOwoJCQl9CgkJfSBlbHNlIHsKCQkJSVdlYk1vZHVsZSB3ZWJNb2R1bGUgPSAoSVdlYk1vZHVsZSkgbW9kdWxlLmxvYWRBZGFwdGVyKElXZWJNb2R1bGUuY2xhc3MsIG51bGwpOwoJCQlJUGF0aCBmcm9tID0gd2ViTW9kdWxlLmdldExvY2F0aW9uKCk7CgkJCUlQYXRoIHRvID0gZ2V0U2VydmVyKCkuZ2V0UnVudGltZSgpLmdldExvY2F0aW9uKCkuYXBwZW5kKCJ3ZWJhcHBzIikuYXBwZW5kKHdlYk1vZHVsZS5nZXRDb250ZXh0Um9vdCgpKTsKCQkJRmlsZVV0aWwuc21hcnRDb3B5RGlyZWN0b3J5KGZyb20udG9PU1N0cmluZygpLCB0by50b09TU3RyaW5nKCksIG1vbml0b3IpOwoJCQlwLnB1dChtb2R1bGUuZ2V0SWQoKSwgdG8udG9PU1N0cmluZygpKTsKCQkJc2V0TW9kdWxlUHVibGlzaFN0YXRlKG1vZHVsZVRyZWUsIElTZXJ2ZXIuUFVCTElTSF9TVEFURV9OT05FKTsKCQl9CgkJCgkJdHJ5IHsKCQkJcC5zdG9yZShuZXcgRmlsZU91dHB1dFN0cmVhbShwYXRoLnRvRmlsZSgpKSwgIlRvbWNhdCBwdWJsaXNoIGRhdGEiKTsKCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkvLyBpZ25vcmUKCQl9Cgl9CgoJLyoqCgkgKiBTZXR1cCBmb3Igc3RhcnRpbmcgdGhlIHNlcnZlci4KCSAqIAoJICogQHBhcmFtIGxhdW5jaCBJTGF1bmNoCgkgKiBAcGFyYW0gbGF1bmNoTW9kZSBTdHJpbmcKCSAqIEBwYXJhbSBtb25pdG9yIElQcm9ncmVzc01vbml0b3IKCSAqIEB0aHJvd3MgQ29yZUV4Y2VwdGlvbiBpZiBhbnl0aGluZyBnb2VzIHdyb25nCgkgKi8KCXB1YmxpYyB2b2lkIHNldHVwTGF1bmNoKElMYXVuY2ggbGF1bmNoLCBTdHJpbmcgbGF1bmNoTW9kZSwgSVByb2dyZXNzTW9uaXRvciBtb25pdG9yKSB0aHJvd3MgQ29yZUV4Y2VwdGlvbiB7CgkJaWYgKCJ0cnVlIi5lcXVhbHMobGF1bmNoLmdldExhdW5jaENvbmZpZ3VyYXRpb24oKS5nZXRBdHRyaWJ1dGUoQVRUUl9TVE9QLCAiZmFsc2UiKSkpCgkJCXJldHVybjsKCQkvL2lmIChnZXRUb21jYXRSdW50aW1lKCkgPT0gbnVsbCkKCQkvLwl0aHJvdyBuZXcgQ29yZUV4Y2VwdGlvbigpOwoJCQoJCUlTdGF0dXMgc3RhdHVzID0gZ2V0VG9tY2F0UnVudGltZSgpLnZhbGlkYXRlKCk7CgkJaWYgKHN0YXR1cyAhPSBudWxsICYmIHN0YXR1cy5nZXRTZXZlcml0eSgpID09IElTdGF0dXMuRVJST1IpCgkJCXRocm93IG5ldyBDb3JlRXhjZXB0aW9uKHN0YXR1cyk7CgoJCS8vc2V0UmVzdGFydE5lZWRlZChmYWxzZSk7CgkJVG9tY2F0Q29uZmlndXJhdGlvbiBjb25maWd1cmF0aW9uID0gZ2V0VG9tY2F0Q29uZmlndXJhdGlvbigpOwoJCgkJLy8gY2hlY2sgdGhhdCBwb3J0cyBhcmUgZnJlZQoJCUl0ZXJhdG9yIGl0ZXJhdG9yID0gY29uZmlndXJhdGlvbi5nZXRTZXJ2ZXJQb3J0cygpLml0ZXJhdG9yKCk7CgkJTGlzdCB1c2VkUG9ydHMgPSBuZXcgQXJyYXlMaXN0KCk7CgkJd2hpbGUgKGl0ZXJhdG9yLmhhc05leHQoKSkgewoJCQlTZXJ2ZXJQb3J0IHNwID0gKFNlcnZlclBvcnQpIGl0ZXJhdG9yLm5leHQoKTsKCQkJaWYgKHNwLmdldFBvcnQoKSA8IDApCgkJCQl0aHJvdyBuZXcgQ29yZUV4Y2VwdGlvbihuZXcgU3RhdHVzKElTdGF0dXMuRVJST1IsIFRvbWNhdFBsdWdpbi5QTFVHSU5fSUQsIDAsIE1lc3NhZ2VzLmVycm9yUG9ydEludmFsaWQsIG51bGwpKTsKCQkJaWYgKFNvY2tldFV0aWwuaXNQb3J0SW5Vc2Uoc3AuZ2V0UG9ydCgpLCA1KSkgewoJCQkJdXNlZFBvcnRzLmFkZChzcCk7CgkJCX0KCQl9CgkJaWYgKHVzZWRQb3J0cy5zaXplKCkgPT0gMSkgewoJCQlTZXJ2ZXJQb3J0IHBvcnQgPSAoU2VydmVyUG9ydCkgdXNlZFBvcnRzLmdldCgwKTsKCQkJdGhyb3cgbmV3IENvcmVFeGNlcHRpb24obmV3IFN0YXR1cyhJU3RhdHVzLkVSUk9SLCBUb21jYXRQbHVnaW4uUExVR0lOX0lELCAwLCBOTFMuYmluZChNZXNzYWdlcy5lcnJvclBvcnRJblVzZSwgbmV3IFN0cmluZ1tdIHtwb3J0LmdldFBvcnQoKSArICIiLCBnZXRTZXJ2ZXIoKS5nZXROYW1lKCl9KSwgbnVsbCkpOwoJCX0gZWxzZSBpZiAodXNlZFBvcnRzLnNpemUoKSA+IDEpIHsKCQkJU3RyaW5nIHBvcnRTdHIgPSAiIjsKCQkJaXRlcmF0b3IgPSB1c2VkUG9ydHMuaXRlcmF0b3IoKTsKCQkJYm9vbGVhbiBmaXJzdCA9IHRydWU7CgkJCXdoaWxlIChpdGVyYXRvci5oYXNOZXh0KCkpIHsKCQkJCWlmICghZmlyc3QpCgkJCQkJcG9ydFN0ciArPSAiLCAiOwoJCQkJZmlyc3QgPSBmYWxzZTsKCQkJCVNlcnZlclBvcnQgc3AgPSAoU2VydmVyUG9ydCkgaXRlcmF0b3IubmV4dCgpOwoJCQkJcG9ydFN0ciArPSAiIiArIHNwLmdldFBvcnQoKTsKCQkJfQoJCQl0aHJvdyBuZXcgQ29yZUV4Y2VwdGlvbihuZXcgU3RhdHVzKElTdGF0dXMuRVJST1IsIFRvbWNhdFBsdWdpbi5QTFVHSU5fSUQsIDAsIE5MUy5iaW5kKE1lc3NhZ2VzLmVycm9yUG9ydHNJblVzZSwgbmV3IFN0cmluZ1tdIHtwb3J0U3RyLCBnZXRTZXJ2ZXIoKS5nZXROYW1lKCl9KSwgbnVsbCkpOwoJCX0KCQkKCQkvLyBjaGVjayB0aGF0IHRoZXJlIGlzIG9ubHkgb25lIGFwcCBmb3IgZWFjaCBjb250ZXh0IHJvb3QKCQlpdGVyYXRvciA9IGNvbmZpZ3VyYXRpb24uZ2V0V2ViTW9kdWxlcygpLml0ZXJhdG9yKCk7CgkJTGlzdCBjb250ZXh0Um9vdHMgPSBuZXcgQXJyYXlMaXN0KCk7CgkJd2hpbGUgKGl0ZXJhdG9yLmhhc05leHQoKSkgewoJCQlXZWJNb2R1bGUgbW9kdWxlID0gKFdlYk1vZHVsZSkgaXRlcmF0b3IubmV4dCgpOwoJCQlTdHJpbmcgY29udGV4dFJvb3QgPSBtb2R1bGUuZ2V0UGF0aCgpOwoJCQlpZiAoY29udGV4dFJvb3RzLmNvbnRhaW5zKGNvbnRleHRSb290KSkKCQkJCXRocm93IG5ldyBDb3JlRXhjZXB0aW9uKG5ldyBTdGF0dXMoSVN0YXR1cy5FUlJPUiwgVG9tY2F0UGx1Z2luLlBMVUdJTl9JRCwgMCwgTkxTLmJpbmQoTWVzc2FnZXMuZXJyb3JEdXBsaWNhdGVDb250ZXh0Um9vdCwgbmV3IFN0cmluZ1tdIHsgY29udGV4dFJvb3QgfSksIG51bGwpKTsKCQkJCgkJCWNvbnRleHRSb290cy5hZGQoY29udGV4dFJvb3QpOwoJCX0KCQkKCQlzZXRTZXJ2ZXJTdGF0ZShJU2VydmVyLlNUQVRFX1NUQVJUSU5HKTsKCQlzZXRNb2RlKGxhdW5jaE1vZGUpOwoJCgkJLy8gcGluZyBzZXJ2ZXIgdG8gY2hlY2sgZm9yIHN0YXJ0dXAKCQl0cnkgewoJCQlTdHJpbmcgdXJsID0gImh0dHA6Ly9sb2NhbGhvc3QiOwoJCQlpbnQgcG9ydCA9IGNvbmZpZ3VyYXRpb24uZ2V0TWFpblBvcnQoKS5nZXRQb3J0KCk7CgkJCWlmIChwb3J0ICE9IDgwKQoJCQkJdXJsICs9ICI6IiArIHBvcnQ7CgkJCXBpbmcgPSBuZXcgUGluZ1RocmVhZChnZXRTZXJ2ZXIoKSwgdXJsLCA1MCwgdGhpcyk7CgkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiQ2FuJ3QgcGluZyBmb3IgVG9tY2F0IHN0YXJ0dXAuIik7CgkJfQoJfQoKCS8qKgoJICogQ2xlYW5seSBzaHV0cyBkb3duIGFuZCB0ZXJtaW5hdGVzIHRoZSBzZXJ2ZXIuCgkgKiAKCSAqIEBwYXJhbSBmb3JjZSA8Y29kZT50cnVlPC9jb2RlPiB0byBraWxsIHRoZSBzZXJ2ZXIKCSAqLwoJcHVibGljIHZvaWQgc3RvcChib29sZWFuIGZvcmNlKSB7CgkJaWYgKGZvcmNlKSB7CgkJCXRlcm1pbmF0ZSgpOwoJCQlyZXR1cm47CgkJfQoJCWludCBzdGF0ZSA9IGdldFNlcnZlcigpLmdldFNlcnZlclN0YXRlKCk7CgkJaWYgKHN0YXRlID09IElTZXJ2ZXIuU1RBVEVfU1RPUFBFRCkKCQkJcmV0dXJuOwoJCWVsc2UgaWYgKHN0YXRlID09IElTZXJ2ZXIuU1RBVEVfU1RBUlRJTkcgfHwgc3RhdGUgPT0gSVNlcnZlci5TVEFURV9TVE9QUElORykgewoJCQl0ZXJtaW5hdGUoKTsKCQkJcmV0dXJuOwoJCX0KCgkJdHJ5IHsKCQkJVHJhY2UudHJhY2UoVHJhY2UuRklORVIsICJTdG9wcGluZyBUb21jYXQiKTsKCQkJaWYgKHN0YXRlICE9IElTZXJ2ZXIuU1RBVEVfU1RPUFBFRCkKCQkJCXNldFNlcnZlclN0YXRlKElTZXJ2ZXIuU1RBVEVfU1RPUFBJTkcpOwoJCgkJCUlMYXVuY2hDb25maWd1cmF0aW9uIGxhdW5jaENvbmZpZyA9ICgoU2VydmVyKWdldFNlcnZlcigpKS5nZXRMYXVuY2hDb25maWd1cmF0aW9uKHRydWUsIG51bGwpOwoJCQlJTGF1bmNoQ29uZmlndXJhdGlvbldvcmtpbmdDb3B5IHdjID0gbGF1bmNoQ29uZmlnLmdldFdvcmtpbmdDb3B5KCk7CgkJCQoJCQlTdHJpbmcgYXJncyA9IHJlbmRlckNvbW1hbmRMaW5lKGdldFJ1bnRpbWVQcm9ncmFtQXJndW1lbnRzKGZhbHNlKSwgIiAiKTsKCQkJd2Muc2V0QXR0cmlidXRlKElKYXZhTGF1bmNoQ29uZmlndXJhdGlvbkNvbnN0YW50cy5BVFRSX1BST0dSQU1fQVJHVU1FTlRTLCBhcmdzKTsKCQkJd2Muc2V0QXR0cmlidXRlKEFUVFJfU1RPUCwgInRydWUiKTsKCQkJd2MubGF1bmNoKElMYXVuY2hNYW5hZ2VyLlJVTl9NT0RFLCBuZXcgTnVsbFByb2dyZXNzTW9uaXRvcigpKTsKCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQlUcmFjZS50cmFjZShUcmFjZS5TRVZFUkUsICJFcnJvciBzdG9wcGluZyBUb21jYXQiLCBlKTsKCQl9Cgl9CgoJLyoqCgkgKiBUZXJtaW5hdGVzIHRoZSBzZXJ2ZXIuCgkgKi8KCXByb3RlY3RlZCB2b2lkIHRlcm1pbmF0ZSgpIHsKCQlpZiAoZ2V0U2VydmVyKCkuZ2V0U2VydmVyU3RhdGUoKSA9PSBJU2VydmVyLlNUQVRFX1NUT1BQRUQpCgkJCXJldHVybjsKCgkJdHJ5IHsKCQkJc2V0U2VydmVyU3RhdGUoSVNlcnZlci5TVEFURV9TVE9QUElORyk7CgkJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVSLCAiS2lsbGluZyB0aGUgVG9tY2F0IHByb2Nlc3MiKTsKCQkJaWYgKHByb2Nlc3MgIT0gbnVsbCAmJiAhcHJvY2Vzcy5pc1Rlcm1pbmF0ZWQoKSkgewoJCQkJcHJvY2Vzcy50ZXJtaW5hdGUoKTsKCQkJCXN0b3BJbXBsKCk7CgkJCX0KCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQlUcmFjZS50cmFjZShUcmFjZS5TRVZFUkUsICJFcnJvciBraWxsaW5nIHRoZSBwcm9jZXNzIiwgZSk7CgkJfQoJfQoKCXB1YmxpYyBJUGF0aCBnZXRUZW1wRGlyZWN0b3J5KCkgewoJCXJldHVybiBzdXBlci5nZXRUZW1wRGlyZWN0b3J5KCk7Cgl9CgoJLyoqCgkgKiBSZXR1cm4gYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhpcyBvYmplY3QuCgkgKiBAcmV0dXJuIGphdmEubGFuZy5TdHJpbmcKCSAqLwoJcHVibGljIFN0cmluZyB0b1N0cmluZygpIHsKCQlyZXR1cm4gIlRvbWNhdFNlcnZlciI7Cgl9CgkKCXByb3RlY3RlZCBzdGF0aWMgaW50IGdldE5leHRUb2tlbihTdHJpbmcgcywgaW50IHN0YXJ0KSB7CgkJaW50IGkgPSBzdGFydDsKCQlpbnQgbGVuZ3RoID0gcy5sZW5ndGgoKTsKCQljaGFyIGxvb2tGb3IgPSAnICc7CgkJCgkJd2hpbGUgKGkgPCBsZW5ndGgpIHsKCQkJY2hhciBjID0gcy5jaGFyQXQoaSk7CgkJCWlmIChsb29rRm9yID09IGMpIHsKCQkJCWlmIChsb29rRm9yID09ICciJykKCQkJCQlyZXR1cm4gaSsxOwoJCQkJcmV0dXJuIGk7CgkJCX0KCQkJaWYgKGMgPT0gJyInKQoJCQkJbG9va0ZvciA9ICciJzsKCQkJaSsrOwoJCX0KCQlyZXR1cm4gLTE7Cgl9CgkKCS8qKgoJICogTWVyZ2UgdGhlIGdpdmVuIGFyZ3VtZW50cyBpbnRvIHRoZSBvcmlnaW5hbCBhcmd1bWVudCBzdHJpbmcsIHJlcGxhY2luZwoJICogaW52YWxpZCB2YWx1ZXMgaWYgdGhleSBoYXZlIGJlZW4gY2hhbmdlZC4KCSAqIAoJICogQHBhcmFtIG9yaWdpbmFsQXJnCgkgKiBAcGFyYW0gdm1BcmdzCgkgKiBAcmV0dXJuIG1lcmdlZCBhcmd1bWVudCBzdHJpbmcKCSAqLwoJcHVibGljIHN0YXRpYyBTdHJpbmcgbWVyZ2VBcmd1bWVudHMoU3RyaW5nIG9yaWdpbmFsQXJnLCBTdHJpbmdbXSB2bUFyZ3MpIHsKCQlpZiAodm1BcmdzID09IG51bGwpCgkJCXJldHVybiBvcmlnaW5hbEFyZzsKCQkKCQlpZiAob3JpZ2luYWxBcmcgPT0gbnVsbCkKCQkJb3JpZ2luYWxBcmcgPSAiIjsKCQkKCQkvLyByZXBsYWNlIGFuZCBudWxsIG91dCBhbGwgdm1hcmdzIHRoYXQgYWxyZWFkeSBleGlzdAoJCWludCBzaXplID0gdm1BcmdzLmxlbmd0aDsKCQlmb3IgKGludCBpID0gMDsgaSA8IHNpemU7IGkrKykgewoJCQlpbnQgaW5kID0gdm1BcmdzW2ldLmluZGV4T2YoIiAiKTsKCQkJaW50IGluZDIgPSB2bUFyZ3NbaV0uaW5kZXhPZigiPSIpOwoJCQlpZiAoaW5kID49IDAgJiYgKGluZDIgPT0gLTEgfHwgaW5kIDwgaW5kMikpIHsgLy8gLWEgYmMgc3R5bGUKCQkJCWludCBpbmRleCA9IG9yaWdpbmFsQXJnLmluZGV4T2Yodm1BcmdzW2ldLnN1YnN0cmluZygwLCBpbmQgKyAxKSk7CgkJCQlpZiAoaW5kZXggPT0gMCB8fCAoaW5kZXggPiAwICYmIG9yaWdpbmFsQXJnLmNoYXJBdChpbmRleCAtIDEpID09ICcgJykpIHsKCQkJCQkvLyByZXBsYWNlCgkJCQkJU3RyaW5nIHMgPSBvcmlnaW5hbEFyZy5zdWJzdHJpbmcoMCwgaW5kZXgpOwoJCQkJCWludCBpbmRleDIgPSBnZXROZXh0VG9rZW4ob3JpZ2luYWxBcmcsIGluZGV4ICsgaW5kICsgMSk7CgkJCQkJaWYgKGluZGV4MiA+PSAwKQoJCQkJCQlvcmlnaW5hbEFyZyA9IHMgKyB2bUFyZ3NbaV0gKyBvcmlnaW5hbEFyZy5zdWJzdHJpbmcoaW5kZXgyKTsKCQkJCQllbHNlCgkJCQkJCW9yaWdpbmFsQXJnID0gcyArIHZtQXJnc1tpXTsKCQkJCQl2bUFyZ3NbaV0gPSBudWxsOwoJCQkJfQoJCQl9IGVsc2UgaWYgKGluZDIgPj0gMCkgeyAvLyBhPWIgc3R5bGUKCQkJCWludCBpbmRleCA9IG9yaWdpbmFsQXJnLmluZGV4T2Yodm1BcmdzW2ldLnN1YnN0cmluZygwLCBpbmQyICsgMSkpOwoJCQkJaWYgKGluZGV4ID09IDAgfHwgKGluZGV4ID4gMCAmJiBvcmlnaW5hbEFyZy5jaGFyQXQoaW5kZXggLSAxKSA9PSAnICcpKSB7CgkJCQkJLy8gcmVwbGFjZQoJCQkJCVN0cmluZyBzID0gb3JpZ2luYWxBcmcuc3Vic3RyaW5nKDAsIGluZGV4KTsKCQkJCQlpbnQgaW5kZXgyID0gZ2V0TmV4dFRva2VuKG9yaWdpbmFsQXJnLCBpbmRleCk7CgkJCQkJaWYgKGluZGV4MiA+PSAwKQoJCQkJCQlvcmlnaW5hbEFyZyA9IHMgKyB2bUFyZ3NbaV0gKyBvcmlnaW5hbEFyZy5zdWJzdHJpbmcoaW5kZXgyKTsKCQkJCQllbHNlCgkJCQkJCW9yaWdpbmFsQXJnID0gcyArIHZtQXJnc1tpXTsKCQkJCQl2bUFyZ3NbaV0gPSBudWxsOwoJCQkJfQoJCQl9IGVsc2UgeyAvLyBhYmMgc3R5bGUKCQkJCWludCBpbmRleCA9IG9yaWdpbmFsQXJnLmluZGV4T2Yodm1BcmdzW2ldKTsKCQkJCWlmIChpbmRleCA9PSAwIHx8IChpbmRleCA+IDAgJiYgb3JpZ2luYWxBcmcuY2hhckF0KGluZGV4LTEpID09ICcgJykpIHsKCQkJCQkvLyByZXBsYWNlCgkJCQkJU3RyaW5nIHMgPSBvcmlnaW5hbEFyZy5zdWJzdHJpbmcoMCwgaW5kZXgpOwoJCQkJCWludCBpbmRleDIgPSBnZXROZXh0VG9rZW4ob3JpZ2luYWxBcmcsIGluZGV4KTsKCQkJCQlpZiAoaW5kZXgyID49IDApCgkJCQkJCW9yaWdpbmFsQXJnID0gcyArIHZtQXJnc1tpXSArIG9yaWdpbmFsQXJnLnN1YnN0cmluZyhpbmRleDIpOwoJCQkJCWVsc2UKCQkJCQkJb3JpZ2luYWxBcmcgPSBzICsgdm1BcmdzW2ldOwoJCQkJCXZtQXJnc1tpXSA9IG51bGw7CgkJCQl9CgkJCX0KCQl9CgkJCgkJLy8gYWRkIHJlbWFpbmluZyB2bWFyZ3MgdG8gdGhlIGVuZAoJCWZvciAoaW50IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKSB7CgkJCWlmICh2bUFyZ3NbaV0gIT0gbnVsbCkgewoJCQkJaWYgKG9yaWdpbmFsQXJnLmxlbmd0aCgpID4gMCAmJiAhb3JpZ2luYWxBcmcuZW5kc1dpdGgoIiAiKSkKCQkJCQlvcmlnaW5hbEFyZyArPSAiICI7CgkJCQlvcmlnaW5hbEFyZyArPSB2bUFyZ3NbaV07CgkJCX0KCQl9CgkJCgkJcmV0dXJuIG9yaWdpbmFsQXJnOwoJfQoKCS8qKgoJICogUmVwbGFjZSB0aGUgY3VycmVudCBKUkUgY29udGFpbmVyIGNsYXNzcGF0aCB3aXRoIHRoZSBnaXZlbiBlbnRyeS4KCSAqIAoJICogQHBhcmFtIGNwCgkgKiBAcGFyYW0gZW50cnkKCSAqLwoJcHVibGljIHN0YXRpYyB2b2lkIHJlcGxhY2VKUkVDb250YWluZXIoTGlzdCBjcCwgSVJ1bnRpbWVDbGFzc3BhdGhFbnRyeSBlbnRyeSkgewoJCWludCBzaXplID0gY3Auc2l6ZSgpOwoJCWZvciAoaW50IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKSB7CgkJCUlSdW50aW1lQ2xhc3NwYXRoRW50cnkgZW50cnkyID0gKElSdW50aW1lQ2xhc3NwYXRoRW50cnkpIGNwLmdldChpKTsKCQkJaWYgKGVudHJ5Mi5nZXRQYXRoKCkudXB0b1NlZ21lbnQoMikuaXNQcmVmaXhPZihlbnRyeS5nZXRQYXRoKCkpKSB7CgkJCQljcC5zZXQoaSwgZW50cnkpOwoJCQkJcmV0dXJuOwoJCQl9CgkJfQoJCQoJCWNwLmFkZCgwLCBlbnRyeSk7Cgl9CgoJLyoqCgkgKiBNZXJnZSBhIHNpbmdsZSBjbGFzc3BhdGggZW50cnkgaW50byB0aGUgY2xhc3NwYXRoIGxpc3QuCgkgKiAKCSAqIEBwYXJhbSBjcAoJICogQHBhcmFtIGVudHJ5CgkgKi8KCXB1YmxpYyBzdGF0aWMgdm9pZCBtZXJnZUNsYXNzcGF0aChMaXN0IGNwLCBJUnVudGltZUNsYXNzcGF0aEVudHJ5IGVudHJ5KSB7CgkJSXRlcmF0b3IgaXRlcmF0b3IgPSBjcC5pdGVyYXRvcigpOwoJCXdoaWxlIChpdGVyYXRvci5oYXNOZXh0KCkpIHsKCQkJSVJ1bnRpbWVDbGFzc3BhdGhFbnRyeSBlbnRyeTIgPSAoSVJ1bnRpbWVDbGFzc3BhdGhFbnRyeSkgaXRlcmF0b3IubmV4dCgpOwoJCQkKCQkJaWYgKGVudHJ5Mi5nZXRQYXRoKCkuZXF1YWxzKGVudHJ5LmdldFBhdGgoKSkpCgkJCQlyZXR1cm47CgkJfQoJCQoJCWNwLmFkZChlbnRyeSk7Cgl9CgoJcHVibGljIHZvaWQgc2V0dXBMYXVuY2hDb25maWd1cmF0aW9uKElMYXVuY2hDb25maWd1cmF0aW9uV29ya2luZ0NvcHkgd29ya2luZ0NvcHksIElQcm9ncmVzc01vbml0b3IgbW9uaXRvcikgdGhyb3dzIENvcmVFeGNlcHRpb24gewoJCVN0cmluZyBleGlzdGluZ1Byb2dBcmdzID0gd29ya2luZ0NvcHkuZ2V0QXR0cmlidXRlKElKYXZhTGF1bmNoQ29uZmlndXJhdGlvbkNvbnN0YW50cy5BVFRSX1BST0dSQU1fQVJHVU1FTlRTLCAoU3RyaW5nKW51bGwpOwoJCXdvcmtpbmdDb3B5LnNldEF0dHJpYnV0ZShJSmF2YUxhdW5jaENvbmZpZ3VyYXRpb25Db25zdGFudHMuQVRUUl9QUk9HUkFNX0FSR1VNRU5UUywgbWVyZ2VBcmd1bWVudHMoZXhpc3RpbmdQcm9nQXJncywgZ2V0UnVudGltZVByb2dyYW1Bcmd1bWVudHModHJ1ZSkpKTsKCgkJU3RyaW5nIGV4aXN0aW5nVk1BcmdzID0gd29ya2luZ0NvcHkuZ2V0QXR0cmlidXRlKElKYXZhTGF1bmNoQ29uZmlndXJhdGlvbkNvbnN0YW50cy5BVFRSX1ZNX0FSR1VNRU5UUywgKFN0cmluZyludWxsKTsKCQlpZiAoZXhpc3RpbmdWTUFyZ3MgIT0gbnVsbCAmJiAhZ2V0VG9tY2F0U2VydmVyKCkuaXNTZWN1cmUoKSkgewoJCQkvLyByZW1vdmUgLURqYXZhLnNlY3VyaXR5Lm1hbmFnZXIgYW5kIC1EamF2YS5zZWN1cml0eS5wb2xpY3k9InggeCIKCQkJaW50IGluZGV4ID0gZXhpc3RpbmdWTUFyZ3MuaW5kZXhPZigiLURqYXZhLnNlY3VyaXR5Lm1hbmFnZXIiKTsKCQkJaWYgKGluZGV4ID49IDApIHsKCQkJCWlmIChpbmRleCA+IDAgJiYgZXhpc3RpbmdWTUFyZ3MuY2hhckF0KGluZGV4IC0gMSkgPT0gJyAnKQoJCQkJCWluZGV4IC0tOwoJCQkJaW50IGluZGV4MiA9IGV4aXN0aW5nVk1BcmdzLmluZGV4T2YoIiAiLCBpbmRleCArIDIpOwoJCQkJZXhpc3RpbmdWTUFyZ3MgPSBleGlzdGluZ1ZNQXJncy5zdWJzdHJpbmcoMCwgaW5kZXgpICsgZXhpc3RpbmdWTUFyZ3Muc3Vic3RyaW5nKGluZGV4Mik7CgkJCX0KCQkJaW5kZXggPSBleGlzdGluZ1ZNQXJncy5pbmRleE9mKCItRGphdmEuc2VjdXJpdHkucG9saWN5PSIpOwoJCQlpZiAoaW5kZXggPj0gMCkgewoJCQkJaWYgKGluZGV4ID4gMCAmJiBleGlzdGluZ1ZNQXJncy5jaGFyQXQoaW5kZXggLSAxKSA9PSAnICcpCgkJCQkJaW5kZXggLS07CgkJCQlpbnQgaW5kZXgyID0gZXhpc3RpbmdWTUFyZ3MuaW5kZXhPZigiXCIiLCBpbmRleCk7CgkJCQlpbmRleDIgPSBleGlzdGluZ1ZNQXJncy5pbmRleE9mKCJcIiIsIGluZGV4MiArIDEpOwoJCQkJZXhpc3RpbmdWTUFyZ3MgPSBleGlzdGluZ1ZNQXJncy5zdWJzdHJpbmcoMCwgaW5kZXgpICsgZXhpc3RpbmdWTUFyZ3Muc3Vic3RyaW5nKGluZGV4MisxKTsKCQkJfQoJCX0KCQl3b3JraW5nQ29weS5zZXRBdHRyaWJ1dGUoSUphdmFMYXVuY2hDb25maWd1cmF0aW9uQ29uc3RhbnRzLkFUVFJfVk1fQVJHVU1FTlRTLCBtZXJnZUFyZ3VtZW50cyhleGlzdGluZ1ZNQXJncywgZ2V0UnVudGltZVZNQXJndW1lbnRzKCkpKTsKCQkKCQlJVG9tY2F0UnVudGltZSBydW50aW1lID0gZ2V0VG9tY2F0UnVudGltZSgpOwoJCUlWTUluc3RhbGwgdm1JbnN0YWxsID0gcnVudGltZS5nZXRWTUluc3RhbGwoKTsKCQlpZiAodm1JbnN0YWxsICE9IG51bGwpIHsKCQkJd29ya2luZ0NvcHkuc2V0QXR0cmlidXRlKElKYXZhTGF1bmNoQ29uZmlndXJhdGlvbkNvbnN0YW50cy5BVFRSX1ZNX0lOU1RBTExfVFlQRSwgdm1JbnN0YWxsLmdldFZNSW5zdGFsbFR5cGUoKS5nZXRJZCgpKTsKCQkJd29ya2luZ0NvcHkuc2V0QXR0cmlidXRlKElKYXZhTGF1bmNoQ29uZmlndXJhdGlvbkNvbnN0YW50cy5BVFRSX1ZNX0lOU1RBTExfTkFNRSwgdm1JbnN0YWxsLmdldE5hbWUoKSk7CgkJfQoJCQoJCS8vIHVwZGF0ZSBjbGFzc3BhdGgKCQlJUnVudGltZUNsYXNzcGF0aEVudHJ5W10gb3JpZ2luYWxDbGFzc3BhdGggPSBKYXZhUnVudGltZS5jb21wdXRlVW5yZXNvbHZlZFJ1bnRpbWVDbGFzc3BhdGgod29ya2luZ0NvcHkpOwoJCWludCBzaXplID0gb3JpZ2luYWxDbGFzc3BhdGgubGVuZ3RoOwoJCUxpc3Qgb2xkQ3AgPSBuZXcgQXJyYXlMaXN0KG9yaWdpbmFsQ2xhc3NwYXRoLmxlbmd0aCArIDIpOwoJCWZvciAoaW50IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKQoJCQlvbGRDcC5hZGQob3JpZ2luYWxDbGFzc3BhdGhbaV0pOwoJCQoJCUxpc3QgY3AyID0gcnVudGltZS5nZXRSdW50aW1lQ2xhc3NwYXRoKCk7CgkJSXRlcmF0b3IgaXRlcmF0b3IgPSBjcDIuaXRlcmF0b3IoKTsKCQl3aGlsZSAoaXRlcmF0b3IuaGFzTmV4dCgpKSB7CgkJCUlSdW50aW1lQ2xhc3NwYXRoRW50cnkgZW50cnkgPSAoSVJ1bnRpbWVDbGFzc3BhdGhFbnRyeSkgaXRlcmF0b3IubmV4dCgpOwoJCQltZXJnZUNsYXNzcGF0aChvbGRDcCwgZW50cnkpOwoJCX0KCQkKCQlpZiAodm1JbnN0YWxsICE9IG51bGwpIHsKCQkJdHJ5IHsKCQkJCVN0cmluZyB0eXBlSWQgPSB2bUluc3RhbGwuZ2V0Vk1JbnN0YWxsVHlwZSgpLmdldElkKCk7CgkJCQlyZXBsYWNlSlJFQ29udGFpbmVyKG9sZENwLCBKYXZhUnVudGltZS5uZXdSdW50aW1lQ29udGFpbmVyQ2xhc3NwYXRoRW50cnkobmV3IFBhdGgoSmF2YVJ1bnRpbWUuSlJFX0NPTlRBSU5FUikuYXBwZW5kKHR5cGVJZCkuYXBwZW5kKHZtSW5zdGFsbC5nZXROYW1lKCkpLCBJUnVudGltZUNsYXNzcGF0aEVudHJ5LkJPT1RTVFJBUF9DTEFTU0VTKSk7CgkJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCQkvLyBpZ25vcmUKCQkJfQoJCQkKCQkJSVBhdGgganJlUGF0aCA9IG5ldyBQYXRoKHZtSW5zdGFsbC5nZXRJbnN0YWxsTG9jYXRpb24oKS5nZXRBYnNvbHV0ZVBhdGgoKSk7CgkJCWlmIChqcmVQYXRoICE9IG51bGwpIHsKCQkJCUlQYXRoIHRvb2xzUGF0aCA9IGpyZVBhdGguYXBwZW5kKCJsaWIiKS5hcHBlbmQoInRvb2xzLmphciIpOwoJCQkJaWYgKHRvb2xzUGF0aC50b0ZpbGUoKS5leGlzdHMoKSkKCQkJCQltZXJnZUNsYXNzcGF0aChvbGRDcCwgSmF2YVJ1bnRpbWUubmV3QXJjaGl2ZVJ1bnRpbWVDbGFzc3BhdGhFbnRyeSh0b29sc1BhdGgpKTsKCQkJfQoJCX0KCQkKCQlpdGVyYXRvciA9IG9sZENwLml0ZXJhdG9yKCk7CgkJTGlzdCBsaXN0ID0gbmV3IEFycmF5TGlzdCgpOwoJCXdoaWxlIChpdGVyYXRvci5oYXNOZXh0KCkpIHsKCQkJSVJ1bnRpbWVDbGFzc3BhdGhFbnRyeSBlbnRyeSA9IChJUnVudGltZUNsYXNzcGF0aEVudHJ5KSBpdGVyYXRvci5uZXh0KCk7CgkJCXRyeSB7CgkJCQlsaXN0LmFkZChlbnRyeS5nZXRNZW1lbnRvKCkpOwoJCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiQ291bGQgbm90IHJlc29sdmUgY2xhc3NwYXRoIGVudHJ5OiAiICsgZW50cnksIGUpOwoJCQl9CgkJfQoJCQoJCXdvcmtpbmdDb3B5LnNldEF0dHJpYnV0ZShJSmF2YUxhdW5jaENvbmZpZ3VyYXRpb25Db25zdGFudHMuQVRUUl9DTEFTU1BBVEgsIGxpc3QpOwoJCXdvcmtpbmdDb3B5LnNldEF0dHJpYnV0ZShJSmF2YUxhdW5jaENvbmZpZ3VyYXRpb25Db25zdGFudHMuQVRUUl9ERUZBVUxUX0NMQVNTUEFUSCwgZmFsc2UpOwoJfQoJCglwcm90ZWN0ZWQgSU1vZHVsZVJlc291cmNlRGVsdGFbXSBnZXRQdWJsaXNoZWRSZXNvdXJjZURlbHRhKElNb2R1bGVbXSBtb2R1bGUpIHsKCQlyZXR1cm4gc3VwZXIuZ2V0UHVibGlzaGVkUmVzb3VyY2VEZWx0YShtb2R1bGUpOwoJfQp9