LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogQ29weXJpZ2h0IChjKSAyMDAzLCAyMDA1IElCTSBDb3Jwb3JhdGlvbiBhbmQgb3RoZXJzLgogKiBBbGwgcmlnaHRzIHJlc2VydmVkLiBUaGlzIHByb2dyYW0gYW5kIHRoZSBhY2NvbXBhbnlpbmcgbWF0ZXJpYWxzCiAqIGFyZSBtYWRlIGF2YWlsYWJsZSB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEVjbGlwc2UgUHVibGljIExpY2Vuc2UgdjEuMAogKiB3aGljaCBhY2NvbXBhbmllcyB0aGlzIGRpc3RyaWJ1dGlvbiwgYW5kIGlzIGF2YWlsYWJsZSBhdAogKiBodHRwOi8vd3d3LmVjbGlwc2Uub3JnL2xlZ2FsL2VwbC12MTAuaHRtbAqgKiAKICogQ29udHJpYnV0b3JzOgogKiAgICAgSUJNIENvcnBvcmF0aW9uIC0gSW5pdGlhbCBBUEkgYW5kIGltcGxlbWVudGF0aW9uCiAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLwpwYWNrYWdlIG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIuY29yZS5pbnRlcm5hbDsKCmltcG9ydCBqYXZhLnV0aWwuKjsKCmltcG9ydCBvcmcuZWNsaXBzZS5jb3JlLnJlc291cmNlcy5JRmlsZTsKaW1wb3J0IG9yZy5lY2xpcHNlLmNvcmUucmVzb3VyY2VzLklGb2xkZXI7CmltcG9ydCBvcmcuZWNsaXBzZS5jb3JlLnJlc291cmNlcy5SZXNvdXJjZXNQbHVnaW47CmltcG9ydCBvcmcuZWNsaXBzZS5jb3JlLnJ1bnRpbWUuKjsKaW1wb3J0IG9yZy5lY2xpcHNlLmRlYnVnLmNvcmUuKjsKCmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc2VydmVyLmNvcmUuKjsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIuY29yZS5tb2RlbC4qOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNlcnZlci5jb3JlLnV0aWwuU2VydmVyQWRhcHRlcjsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIuY29yZS51dGlsLlNvY2tldFV0aWw7Ci8qKgogKiAKICovCnB1YmxpYyBjbGFzcyBTZXJ2ZXIgZXh0ZW5kcyBCYXNlIGltcGxlbWVudHMgSVNlcnZlciB7Cglwcm90ZWN0ZWQgc3RhdGljIGZpbmFsIExpc3QgRU1QVFlfTElTVCA9IG5ldyBBcnJheUxpc3QoMCk7CgkKCXByb3RlY3RlZCBzdGF0aWMgZmluYWwgU3RyaW5nIFBST1BfSE9TVE5BTUUgPSAiaG9zdG5hbWUiOwoJcHJvdGVjdGVkIHN0YXRpYyBmaW5hbCBTdHJpbmcgU0VSVkVSX0lEID0gInNlcnZlci1pZCI7Cglwcm90ZWN0ZWQgc3RhdGljIGZpbmFsIFN0cmluZyBSVU5USU1FX0lEID0gInJ1bnRpbWUtaWQiOwoJcHJvdGVjdGVkIHN0YXRpYyBmaW5hbCBTdHJpbmcgQ09ORklHVVJBVElPTl9JRCA9ICJjb25maWd1cmF0aW9uLWlkIjsKCXByb3RlY3RlZCBzdGF0aWMgZmluYWwgU3RyaW5nIE1PRFVMRV9MSVNUID0gIm1vZHVsZXMiOwoJcHJvdGVjdGVkIHN0YXRpYyBmaW5hbCBTdHJpbmcgUFJPUF9BVVRPX1BVQkxJU0hfVElNRSA9ICJhdXRvLXB1Ymxpc2gtdGltZSI7Cglwcm90ZWN0ZWQgc3RhdGljIGZpbmFsIFN0cmluZyBQUk9QX0FVVE9fUFVCTElTSF9ERUZBVUxUID0gImF1dG8tcHVibGlzaC1kZWZhdWx0IjsKCglwcm90ZWN0ZWQgc3RhdGljIGZpbmFsIGNoYXJbXSBJTlZBTElEX0NIQVJTID0gbmV3IGNoYXJbXSB7J1xcJywgJy8nLCAnOicsICcqJywgJz8nLCAnIicsICc8JywgJz4nLCAnfCcsICdcMCcsICdAJywgJyYnfTsKCglwcm90ZWN0ZWQgSVNlcnZlclR5cGUgc2VydmVyVHlwZTsKCXByb3RlY3RlZCBTZXJ2ZXJEZWxlZ2F0ZSBkZWxlZ2F0ZTsKCXByb3RlY3RlZCBTZXJ2ZXJCZWhhdmlvdXJEZWxlZ2F0ZSBiZWhhdmlvdXJEZWxlZ2F0ZTsKCglwcm90ZWN0ZWQgSVJ1bnRpbWUgcnVudGltZTsKCXByb3RlY3RlZCBJRm9sZGVyIGNvbmZpZ3VyYXRpb247CgkKCS8vIHRoZSBsaXN0IG9mIG1vZHVsZXMgdGhhdCBhcmUgdG8gYmUgcHVibGlzaGVkIHRvIHRoZSBzZXJ2ZXIKCXByb3RlY3RlZCBMaXN0IG1vZHVsZXM7CgkKCS8vIHRyYW5zaWVudCBmaWVsZHMKCXByb3RlY3RlZCB0cmFuc2llbnQgU3RyaW5nIG1vZGUgPSBJTGF1bmNoTWFuYWdlci5SVU5fTU9ERTsKCXByb3RlY3RlZCB0cmFuc2llbnQgSU1vZHVsZVtdIHNlcnZlck1vZHVsZXM7Cglwcm90ZWN0ZWQgdHJhbnNpZW50IGludCBzZXJ2ZXJTdGF0ZSA9IFNUQVRFX1VOS05PV047Cglwcm90ZWN0ZWQgdHJhbnNpZW50IGludCBzZXJ2ZXJTeW5jU3RhdGU7Cglwcm90ZWN0ZWQgdHJhbnNpZW50IGJvb2xlYW4gc2VydmVyUmVzdGFydE5lZWRlZDsKCglwcm90ZWN0ZWQgdHJhbnNpZW50IE1hcCBtb2R1bGVTdGF0ZSA9IG5ldyBIYXNoTWFwKCk7Cglwcm90ZWN0ZWQgdHJhbnNpZW50IE1hcCBtb2R1bGVQdWJsaXNoU3RhdGUgPSBuZXcgSGFzaE1hcCgpOwoJcHJvdGVjdGVkIHRyYW5zaWVudCBNYXAgbW9kdWxlUmVzdGFydFN0YXRlID0gbmV3IEhhc2hNYXAoKTsKCglwcm90ZWN0ZWQgdHJhbnNpZW50IFNlcnZlclB1Ymxpc2hJbmZvIHB1Ymxpc2hJbmZvOwoJcHJvdGVjdGVkIHRyYW5zaWVudCBBdXRvUHVibGlzaFRocmVhZCBhdXRvUHVibGlzaFRocmVhZDsKCi8qCXByaXZhdGUgc3RhdGljIGZpbmFsIFN0cmluZ1tdIHN0YXRlU3RyaW5ncyA9IG5ldyBTdHJpbmdbXSB7CgkJInVua25vd24iLCAic3RhcnRpbmciLCAic3RhcnRlZCIsICJzdGFydGVkX2RlYnVnIiwKCQkic3RvcHBpbmciLCAic3RvcHBlZCIsICJzdGFydGVkX3Vuc3VwcG9ydGVkIiwgInN0YXJ0ZWRfcHJvZmlsZSIKCX07Ki8KCQoJLy8gcHVibGlzaCBsaXN0ZW5lcnMKCXByb3RlY3RlZCB0cmFuc2llbnQgTGlzdCBwdWJsaXNoTGlzdGVuZXJzOwoJCgkvLyBzZXJ2ZXIgbGlzdGVuZXJzCglwcm90ZWN0ZWQgdHJhbnNpZW50IExpc3Qgc2VydmVyTGlzdGVuZXJzOwoJCglwdWJsaWMgY2xhc3MgQXV0b1B1Ymxpc2hUaHJlYWQgZXh0ZW5kcyBUaHJlYWQgewoJCXB1YmxpYyBib29sZWFuIHN0b3A7CgkJcHVibGljIGludCB0aW1lID0gMDsgCgkJCgkJcHVibGljIHZvaWQgcnVuKCkgewoJCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICJBdXRvLXB1Ymxpc2ggdGhyZWFkIHN0YXJ0aW5nIGZvciAiICsgU2VydmVyLnRoaXMgKyAiIC0gIiArIHRpbWUgKyAicyIpOwoJCQlpZiAoc3RvcCkKCQkJCXJldHVybjsKCQkJCgkJCXRyeSB7CgkJCQlzbGVlcCh0aW1lICogMTAwMCk7CgkJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCQkvLyBpZ25vcmUKCQkJfQoJCQkKCQkJaWYgKHN0b3ApCgkJCQlyZXR1cm47CgkJCQoJCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICJBdXRvLXB1Ymxpc2ggdGhyZWFkIHB1Ymxpc2hpbmcgIiArIFNlcnZlci50aGlzKTsKCgkJCVB1Ymxpc2hTZXJ2ZXJKb2IgcHVibGlzaEpvYiA9IG5ldyBQdWJsaXNoU2VydmVySm9iKFNlcnZlci50aGlzLCBJU2VydmVyLlBVQkxJU0hfQVVUTywgZmFsc2UpOwoJCQlwdWJsaXNoSm9iLnNjaGVkdWxlKCk7CgkJfQoJfQoKCS8vIHdvcmtpbmcgY29weSwgbG9hZGVkIHJlc291cmNlCglwdWJsaWMgU2VydmVyKElGaWxlIGZpbGUpIHsKCQlzdXBlcihmaWxlKTsKCQltYXAucHV0KFBST1BfSE9TVE5BTUUsICJsb2NhbGhvc3QiKTsKCX0KCgkvLyBjcmVhdGlvbiAod29ya2luZyBjb3B5KQoJcHVibGljIFNlcnZlcihTdHJpbmcgaWQsIElGaWxlIGZpbGUsIElSdW50aW1lIHJ1bnRpbWUsIElTZXJ2ZXJUeXBlIHNlcnZlclR5cGUpIHsKCQlzdXBlcihmaWxlLCBpZCk7CgkJdGhpcy5ydW50aW1lID0gcnVudGltZTsKCQl0aGlzLnNlcnZlclR5cGUgPSBzZXJ2ZXJUeXBlOwoJCW1hcC5wdXQoInNlcnZlci10eXBlLWlkIiwgc2VydmVyVHlwZS5nZXRJZCgpKTsKCQltYXAucHV0KFBST1BfSE9TVE5BTUUsICJsb2NhbGhvc3QiKTsKCQlpZiAocnVudGltZSAhPSBudWxsICYmIHJ1bnRpbWUuZ2V0UnVudGltZVR5cGUoKSAhPSBudWxsKSB7CgkJCVN0cmluZyBuYW1lID0gcnVudGltZS5nZXRSdW50aW1lVHlwZSgpLmdldE5hbWUoKTsKCQkJbWFwLnB1dChQUk9QX05BTUUsIG5hbWUpOwoJCX0KCQlzZXJ2ZXJTdGF0ZSA9ICgoU2VydmVyVHlwZSlzZXJ2ZXJUeXBlKS5nZXRJbml0aWFsU3RhdGUoKTsKCX0KCQoJcHVibGljIElTZXJ2ZXJUeXBlIGdldFNlcnZlclR5cGUoKSB7CgkJcmV0dXJuIHNlcnZlclR5cGU7Cgl9CgkKCXB1YmxpYyBJU2VydmVyV29ya2luZ0NvcHkgY3JlYXRlV29ya2luZ0NvcHkoKSB7CgkJcmV0dXJuIG5ldyBTZXJ2ZXJXb3JraW5nQ29weSh0aGlzKTsgCgl9CgoJcHVibGljIGJvb2xlYW4gaXNXb3JraW5nQ29weSgpIHsKCQlyZXR1cm4gZmFsc2U7Cgl9CgkKCXByb3RlY3RlZCB2b2lkIGRlbGV0ZUZyb21NZXRhZGF0YSgpIHsKCQlSZXNvdXJjZU1hbmFnZXIuZ2V0SW5zdGFuY2UoKS5yZW1vdmVTZXJ2ZXIodGhpcyk7Cgl9CgkKCXByb3RlY3RlZCB2b2lkIHNhdmVUb01ldGFkYXRhKElQcm9ncmVzc01vbml0b3IgbW9uaXRvcikgewoJCXN1cGVyLnNhdmVUb01ldGFkYXRhKG1vbml0b3IpOwoJCVJlc291cmNlTWFuYWdlci5nZXRJbnN0YW5jZSgpLmFkZFNlcnZlcih0aGlzKTsKCX0KCgkvKiAobm9uLUphdmFkb2MpCgkgKiBAc2VlIGNvbS5pYm0ud3RwLnNlcnZlci5jb3JlLklTZXJ2ZXIyI2dldFJ1bnRpbWUoKQoJICovCglwdWJsaWMgSVJ1bnRpbWUgZ2V0UnVudGltZSgpIHsKCQlyZXR1cm4gcnVudGltZTsKCX0KCglwcm90ZWN0ZWQgU3RyaW5nIGdldFJ1bnRpbWVJZCgpIHsKCQlyZXR1cm4gZ2V0QXR0cmlidXRlKFJVTlRJTUVfSUQsIChTdHJpbmcpIG51bGwpOwoJfQoKCS8qIChub24tSmF2YWRvYykKCSAqIEBzZWUgY29tLmlibS53dHAuc2VydmVyLmNvcmUuSVNlcnZlcjIjZ2V0U2VydmVyQ29uZmlndXJhdGlvbigpCgkgKi8KCXB1YmxpYyBJRm9sZGVyIGdldFNlcnZlckNvbmZpZ3VyYXRpb24oKSB7CgkJcmV0dXJuIGNvbmZpZ3VyYXRpb247Cgl9CgoJcHJvdGVjdGVkIFNlcnZlckRlbGVnYXRlIGdldERlbGVnYXRlKCkgewoJCWlmIChkZWxlZ2F0ZSAhPSBudWxsKQoJCQlyZXR1cm4gZGVsZWdhdGU7CgkJCgkJaWYgKHNlcnZlclR5cGUgIT0gbnVsbCkgewoJCQlzeW5jaHJvbml6ZWQgKHRoaXMpIHsKCQkJCWlmIChkZWxlZ2F0ZSA9PSBudWxsKSB7CgkJCQkJdHJ5IHsKCQkJCQkJbG9uZyB0aW1lID0gU3lzdGVtLmN1cnJlbnRUaW1lTWlsbGlzKCk7CgkJCQkJCUlDb25maWd1cmF0aW9uRWxlbWVudCBlbGVtZW50ID0gKChTZXJ2ZXJUeXBlKSBzZXJ2ZXJUeXBlKS5nZXRFbGVtZW50KCk7CgkJCQkJCWRlbGVnYXRlID0gKFNlcnZlckRlbGVnYXRlKSBlbGVtZW50LmNyZWF0ZUV4ZWN1dGFibGVFeHRlbnNpb24oImNsYXNzIik7CgkJCQkJCWRlbGVnYXRlLmluaXRpYWxpemUodGhpcyk7CgkJCQkJCVRyYWNlLnRyYWNlKFRyYWNlLlBFUkZPUk1BTkNFLCAiU2VydmVyLmdldERlbGVnYXRlKCk6IDwiICsgKFN5c3RlbS5jdXJyZW50VGltZU1pbGxpcygpIC0gdGltZSkgKyAiPiAiICsgZ2V0U2VydmVyVHlwZSgpLmdldElkKCkpOwoJCQkJCX0gY2F0Y2ggKFRocm93YWJsZSB0KSB7CgkJCQkJCVRyYWNlLnRyYWNlKFRyYWNlLlNFVkVSRSwgIkNvdWxkIG5vdCBjcmVhdGUgZGVsZWdhdGUgIiArIHRvU3RyaW5nKCksIHQpOwoJCQkJCX0KCQkJCX0KCQkJfQoJCX0KCQlyZXR1cm4gZGVsZWdhdGU7Cgl9CgkKCXByb3RlY3RlZCBTZXJ2ZXJCZWhhdmlvdXJEZWxlZ2F0ZSBnZXRCZWhhdmlvdXJEZWxlZ2F0ZSgpIHsKCQlpZiAoYmVoYXZpb3VyRGVsZWdhdGUgIT0gbnVsbCkKCQkJcmV0dXJuIGJlaGF2aW91ckRlbGVnYXRlOwoJCQoJCWlmIChzZXJ2ZXJUeXBlICE9IG51bGwpIHsKCQkJc3luY2hyb25pemVkICh0aGlzKSB7CgkJCQlpZiAoYmVoYXZpb3VyRGVsZWdhdGUgPT0gbnVsbCkgewoJCQkJCXRyeSB7CgkJCQkJCWxvbmcgdGltZSA9IFN5c3RlbS5jdXJyZW50VGltZU1pbGxpcygpOwoJCQkJCQlJQ29uZmlndXJhdGlvbkVsZW1lbnQgZWxlbWVudCA9ICgoU2VydmVyVHlwZSkgc2VydmVyVHlwZSkuZ2V0RWxlbWVudCgpOwoJCQkJCQliZWhhdmlvdXJEZWxlZ2F0ZSA9IChTZXJ2ZXJCZWhhdmlvdXJEZWxlZ2F0ZSkgZWxlbWVudC5jcmVhdGVFeGVjdXRhYmxlRXh0ZW5zaW9uKCJiZWhhdmlvdXJDbGFzcyIpOwoJCQkJCQliZWhhdmlvdXJEZWxlZ2F0ZS5pbml0aWFsaXplKHRoaXMpOwoJCQkJCQlUcmFjZS50cmFjZShUcmFjZS5QRVJGT1JNQU5DRSwgIlNlcnZlci5nZXREZWxlZ2F0ZSgpOiA8IiArIChTeXN0ZW0uY3VycmVudFRpbWVNaWxsaXMoKSAtIHRpbWUpICsgIj4gIiArIGdldFNlcnZlclR5cGUoKS5nZXRJZCgpKTsKCQkJCQl9IGNhdGNoIChUaHJvd2FibGUgdCkgewoJCQkJCQlUcmFjZS50cmFjZShUcmFjZS5TRVZFUkUsICJDb3VsZCBub3QgY3JlYXRlIGRlbGVnYXRlICIgKyB0b1N0cmluZygpLCB0KTsKCQkJCQl9CgkJCQl9CgkJCX0KCQl9CgkJcmV0dXJuIGJlaGF2aW91ckRlbGVnYXRlOwoJfQoKCS8qKgoJICogUmV0dXJucyB0cnVlIGlmIHRoZSBkZWxlZ2F0ZSBoYXMgYmVlbiBsb2FkZWQuCgkgKiAKCSAqIEByZXR1cm4gPGNvZGU+dHJ1ZTwvY29kZT4gaWYgdGhlIGRlbGVnYXRlIGhhcyBiZWVuIGxvYWRlZCwgYW5kCgkgKiAgICA8Y29kZT5mYWxzZTwvY29kZT4gb3RoZXJ3aXNlCgkgKi8KCXB1YmxpYyBib29sZWFuIGlzRGVsZWdhdGVMb2FkZWQoKSB7CgkJcmV0dXJuIGRlbGVnYXRlICE9IG51bGw7Cgl9CgkKCXB1YmxpYyB2b2lkIGRpc3Bvc2UoKSB7CgkJaWYgKGRlbGVnYXRlICE9IG51bGwpCgkJCWRlbGVnYXRlLmRpc3Bvc2UoKTsKCX0KCglwdWJsaWMgU3RyaW5nIGdldEhvc3QoKSB7CgkJcmV0dXJuIGdldEF0dHJpYnV0ZShQUk9QX0hPU1ROQU1FLCAibG9jYWxob3N0Iik7Cgl9CgkKCXB1YmxpYyBpbnQgZ2V0QXV0b1B1Ymxpc2hUaW1lKCkgewoJCXJldHVybiBnZXRBdHRyaWJ1dGUoUFJPUF9BVVRPX1BVQkxJU0hfVElNRSwgLTEpOwoJfQoJCglwdWJsaWMgYm9vbGVhbiBnZXRBdXRvUHVibGlzaERlZmF1bHQoKSB7CgkJcmV0dXJuIGdldEF0dHJpYnV0ZShQUk9QX0FVVE9fUFVCTElTSF9ERUZBVUxULCB0cnVlKTsKCX0KCgkvKioKCSAqIFJldHVybnMgdGhlIGN1cnJlbnQgc3RhdGUgb2YgdGhlIHNlcnZlci4gKHNlZSBTRVJWRVJfWFhYIGNvbnN0YW50cykKCSAqCgkgKiBAcmV0dXJuIGludAoJICovCglwdWJsaWMgaW50IGdldFNlcnZlclN0YXRlKCkgewoJCXJldHVybiBzZXJ2ZXJTdGF0ZTsKCX0KCQoJcHVibGljIFN0cmluZyBnZXRNb2RlKCkgewoJCXJldHVybiBtb2RlOwoJfQoKCXB1YmxpYyB2b2lkIHNldFNlcnZlclN0YXRlKGludCBzdGF0ZSkgewoJCWlmIChzdGF0ZSA9PSBzZXJ2ZXJTdGF0ZSkKCQkJcmV0dXJuOwoKCQl0aGlzLnNlcnZlclN0YXRlID0gc3RhdGU7CgkJZmlyZVNlcnZlclN0YXRlQ2hhbmdlRXZlbnQoKTsKCX0KCQoJLyoqCgkgKiBBZGQgYSBsaXN0ZW5lciB0byB0aGlzIHNlcnZlci4KCSAqCgkgKiBAcGFyYW0gbGlzdGVuZXIgb3JnLmVjbGlwc2Uud3N0LnNlcnZlci5tb2RlbC5JU2VydmVyTGlzdGVuZXIKCSAqLwoJcHVibGljIHZvaWQgYWRkU2VydmVyTGlzdGVuZXIoSVNlcnZlckxpc3RlbmVyIGxpc3RlbmVyKSB7CgkJVHJhY2UudHJhY2UoVHJhY2UuTElTVEVORVJTLCAiQWRkaW5nIHNlcnZlciBsaXN0ZW5lciAiICsgbGlzdGVuZXIgKyAiIHRvICIgKyB0aGlzKTsKCQoJCWlmIChzZXJ2ZXJMaXN0ZW5lcnMgPT0gbnVsbCkKCQkJc2VydmVyTGlzdGVuZXJzID0gbmV3IEFycmF5TGlzdCgpOwoJCXNlcnZlckxpc3RlbmVycy5hZGQobGlzdGVuZXIpOwoJfQoJCgkvKioKCSAqIFJlbW92ZSBhIGxpc3RlbmVyIGZyb20gdGhpcyBzZXJ2ZXIuCgkgKgoJICogQHBhcmFtIGxpc3RlbmVyIG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIubW9kZWwuSVNlcnZlckxpc3RlbmVyCgkgKi8KCXB1YmxpYyB2b2lkIHJlbW92ZVNlcnZlckxpc3RlbmVyKElTZXJ2ZXJMaXN0ZW5lciBsaXN0ZW5lcikgewoJCVRyYWNlLnRyYWNlKFRyYWNlLkxJU1RFTkVSUywgIlJlbW92aW5nIHNlcnZlciBsaXN0ZW5lciAiICsgbGlzdGVuZXIgKyAiIGZyb20gIiArIHRoaXMpOwoJCgkJaWYgKHNlcnZlckxpc3RlbmVycyAhPSBudWxsKQoJCQlzZXJ2ZXJMaXN0ZW5lcnMucmVtb3ZlKGxpc3RlbmVyKTsKCX0KCQoJLyoqCgkgKiBGaXJlIGEgc2VydmVyIGxpc3RlbmVyIGNvbmZpZ3VyYXRpb24gc3luYyBzdGF0ZSBjaGFuZ2UgZXZlbnQuCgkgKi8KCXByb3RlY3RlZCB2b2lkIGZpcmVDb25maWd1cmF0aW9uU3luY1N0YXRlQ2hhbmdlRXZlbnQoKSB7CgkJVHJhY2UudHJhY2UoVHJhY2UuTElTVEVORVJTLCAiLT4tIEZpcmluZyBzZXJ2ZXIgY29uZmlndXJhdGlvbiBjaGFuZ2UgZXZlbnQ6ICIgKyBnZXROYW1lKCkgKyAiIC0+LSIpOwoJCgkJaWYgKHNlcnZlckxpc3RlbmVycyA9PSBudWxsIHx8IHNlcnZlckxpc3RlbmVycy5pc0VtcHR5KCkpCgkJCXJldHVybjsKCQoJCWludCBzaXplID0gc2VydmVyTGlzdGVuZXJzLnNpemUoKTsKCQlJU2VydmVyTGlzdGVuZXJbXSBzaWwgPSBuZXcgSVNlcnZlckxpc3RlbmVyW3NpemVdOwoJCXNlcnZlckxpc3RlbmVycy50b0FycmF5KHNpbCk7CgkKCQlmb3IgKGludCBpID0gMDsgaSA8IHNpemU7IGkrKykgewoJCQl0cnkgewoJCQkJVHJhY2UudHJhY2UoVHJhY2UuTElTVEVORVJTLCAiICBGaXJpbmcgc2VydmVyIGNvbmZpZ3VyYXRpb24gY2hhbmdlIGV2ZW50IHRvOiAiICsgc2lsW2ldKTsKCQkJCXNpbFtpXS5jb25maWd1cmF0aW9uU3luY1N0YXRlQ2hhbmdlKHRoaXMpOwoJCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiICBFcnJvciBmaXJpbmcgc2VydmVyIGNvbmZpZ3VyYXRpb24gY2hhbmdlIGV2ZW50IiwgZSk7CgkJCX0KCQl9CgkJVHJhY2UudHJhY2UoVHJhY2UuTElTVEVORVJTLCAiLTwtIERvbmUgZmlyaW5nIHNlcnZlciBjb25maWd1cmF0aW9uIGNoYW5nZSBldmVudCAtPC0iKTsKCX0KCQoJLyoqCgkgKiBGaXJlIGEgc2VydmVyIGxpc3RlbmVyIHJlc3RhcnQgc3RhdGUgY2hhbmdlIGV2ZW50LgoJICovCglwcm90ZWN0ZWQgdm9pZCBmaXJlUmVzdGFydFN0YXRlQ2hhbmdlRXZlbnQoKSB7CgkJVHJhY2UudHJhY2UoVHJhY2UuTElTVEVORVJTLCAiLT4tIEZpcmluZyBzZXJ2ZXIgcmVzdGFydCBjaGFuZ2UgZXZlbnQ6ICIgKyBnZXROYW1lKCkgKyAiIC0+LSIpOwoJCgkJaWYgKHNlcnZlckxpc3RlbmVycyA9PSBudWxsIHx8IHNlcnZlckxpc3RlbmVycy5pc0VtcHR5KCkpCgkJCXJldHVybjsKCQoJCWludCBzaXplID0gc2VydmVyTGlzdGVuZXJzLnNpemUoKTsKCQlJU2VydmVyTGlzdGVuZXJbXSBzaWwgPSBuZXcgSVNlcnZlckxpc3RlbmVyW3NpemVdOwoJCXNlcnZlckxpc3RlbmVycy50b0FycmF5KHNpbCk7CgkKCQlmb3IgKGludCBpID0gMDsgaSA8IHNpemU7IGkrKykgewoJCQl0cnkgewoJCQkJVHJhY2UudHJhY2UoVHJhY2UuTElTVEVORVJTLCAiICBGaXJpbmcgc2VydmVyIHJlc3RhcnQgY2hhbmdlIGV2ZW50IHRvOiAiICsgc2lsW2ldKTsKCQkJCXNpbFtpXS5yZXN0YXJ0U3RhdGVDaGFuZ2UodGhpcyk7CgkJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCQlUcmFjZS50cmFjZShUcmFjZS5TRVZFUkUsICIgIEVycm9yIGZpcmluZyBzZXJ2ZXIgcmVzdGFydCBjaGFuZ2UgZXZlbnQiLCBlKTsKCQkJfQoJCX0KCQlUcmFjZS50cmFjZShUcmFjZS5MSVNURU5FUlMsICItPC0gRG9uZSBmaXJpbmcgc2VydmVyIHJlc3RhcnQgY2hhbmdlIGV2ZW50IC08LSIpOwoJfQoJCgkvKioKCSAqIEZpcmUgYSBzZXJ2ZXIgbGlzdGVuZXIgc3RhdGUgY2hhbmdlIGV2ZW50LgoJICovCglwcm90ZWN0ZWQgdm9pZCBmaXJlU2VydmVyU3RhdGVDaGFuZ2VFdmVudCgpIHsKCQlUcmFjZS50cmFjZShUcmFjZS5MSVNURU5FUlMsICItPi0gRmlyaW5nIHNlcnZlciBzdGF0ZSBjaGFuZ2UgZXZlbnQ6ICIgKyBnZXROYW1lKCkgKyAiLCAiICsgZ2V0U2VydmVyU3RhdGUoKSArICIgLT4tIik7CgkKCQlpZiAoc2VydmVyTGlzdGVuZXJzID09IG51bGwgfHwgc2VydmVyTGlzdGVuZXJzLmlzRW1wdHkoKSkKCQkJcmV0dXJuOwoJCgkJaW50IHNpemUgPSBzZXJ2ZXJMaXN0ZW5lcnMuc2l6ZSgpOwoJCUlTZXJ2ZXJMaXN0ZW5lcltdIHNpbCA9IG5ldyBJU2VydmVyTGlzdGVuZXJbc2l6ZV07CgkJc2VydmVyTGlzdGVuZXJzLnRvQXJyYXkoc2lsKTsKCQoJCWZvciAoaW50IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKSB7CgkJCXRyeSB7CgkJCQlUcmFjZS50cmFjZShUcmFjZS5MSVNURU5FUlMsICIgIEZpcmluZyBzZXJ2ZXIgc3RhdGUgY2hhbmdlIGV2ZW50IHRvOiAiICsgc2lsW2ldKTsKCQkJCXNpbFtpXS5zZXJ2ZXJTdGF0ZUNoYW5nZSh0aGlzKTsKCQkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJCVRyYWNlLnRyYWNlKFRyYWNlLlNFVkVSRSwgIiAgRXJyb3IgZmlyaW5nIHNlcnZlciBzdGF0ZSBjaGFuZ2UgZXZlbnQiLCBlKTsKCQkJfQoJCX0KCQlUcmFjZS50cmFjZShUcmFjZS5MSVNURU5FUlMsICItPC0gRG9uZSBmaXJpbmcgc2VydmVyIHN0YXRlIGNoYW5nZSBldmVudCAtPC0iKTsKCX0KCQoJLyoqCgkgKiBGaXJlIGEgc2VydmVyIGxpc3RlbmVyIG1vZHVsZSBjaGFuZ2UgZXZlbnQuCgkgKi8KCXByb3RlY3RlZCB2b2lkIGZpcmVTZXJ2ZXJNb2R1bGVDaGFuZ2VFdmVudCgpIHsKCQlUcmFjZS50cmFjZShUcmFjZS5MSVNURU5FUlMsICItPi0gRmlyaW5nIHNlcnZlciBtb2R1bGUgY2hhbmdlIGV2ZW50OiAiICsgZ2V0TmFtZSgpICsgIiwgIiArIGdldFNlcnZlclN0YXRlKCkgKyAiIC0+LSIpOwoJCQoJCWlmIChzZXJ2ZXJMaXN0ZW5lcnMgPT0gbnVsbCB8fCBzZXJ2ZXJMaXN0ZW5lcnMuaXNFbXB0eSgpKQoJCQlyZXR1cm47CgkJCgkJaW50IHNpemUgPSBzZXJ2ZXJMaXN0ZW5lcnMuc2l6ZSgpOwoJCUlTZXJ2ZXJMaXN0ZW5lcltdIHNpbCA9IG5ldyBJU2VydmVyTGlzdGVuZXJbc2l6ZV07CgkJc2VydmVyTGlzdGVuZXJzLnRvQXJyYXkoc2lsKTsKCQkKCQlmb3IgKGludCBpID0gMDsgaSA8IHNpemU7IGkrKykgewoJCQl0cnkgewoJCQkJVHJhY2UudHJhY2UoVHJhY2UuTElTVEVORVJTLCAiICBGaXJpbmcgc2VydmVyIG1vZHVsZSBjaGFuZ2UgZXZlbnQgdG86ICIgKyBzaWxbaV0pOwoJCQkJc2lsW2ldLm1vZHVsZXNDaGFuZ2VkKHRoaXMpOwoJCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiICBFcnJvciBmaXJpbmcgc2VydmVyIG1vZHVsZSBjaGFuZ2UgZXZlbnQiLCBlKTsKCQkJfQoJCX0KCQlUcmFjZS50cmFjZShUcmFjZS5MSVNURU5FUlMsICItPC0gRG9uZSBmaXJpbmcgc2VydmVyIG1vZHVsZSBjaGFuZ2UgZXZlbnQgLTwtIik7Cgl9CgoJLyoqCgkgKiBGaXJlIGEgc2VydmVyIGxpc3RlbmVyIG1vZHVsZSBzdGF0ZSBjaGFuZ2UgZXZlbnQuCgkgKi8KCXByb3RlY3RlZCB2b2lkIGZpcmVTZXJ2ZXJNb2R1bGVTdGF0ZUNoYW5nZUV2ZW50KElNb2R1bGUgbW9kdWxlKSB7CgkJVHJhY2UudHJhY2UoVHJhY2UuTElTVEVORVJTLCAiLT4tIEZpcmluZyBzZXJ2ZXIgbW9kdWxlIHN0YXRlIGNoYW5nZSBldmVudDogIiArIGdldE5hbWUoKSArICIsICIgKyBnZXRTZXJ2ZXJTdGF0ZSgpICsgIiAtPi0iKTsKCQkKCQlpZiAoc2VydmVyTGlzdGVuZXJzID09IG51bGwgfHwgc2VydmVyTGlzdGVuZXJzLmlzRW1wdHkoKSkKCQkJcmV0dXJuOwoJCQoJCWludCBzaXplID0gc2VydmVyTGlzdGVuZXJzLnNpemUoKTsKCQlJU2VydmVyTGlzdGVuZXJbXSBzaWwgPSBuZXcgSVNlcnZlckxpc3RlbmVyW3NpemVdOwoJCUlNb2R1bGVbXSBwYXJlbnRzID0gbmV3IElNb2R1bGVbMF07CgkJdHJ5IHsKCQkJcGFyZW50cyA9IGdldFJvb3RNb2R1bGVzKG1vZHVsZSwgbnVsbCk7CgkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJLy8gaWdub3JlCgkJfQoJCXNlcnZlckxpc3RlbmVycy50b0FycmF5KHNpbCk7CgkJCgkJZm9yIChpbnQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHsKCQkJdHJ5IHsKCQkJCVRyYWNlLnRyYWNlKFRyYWNlLkxJU1RFTkVSUywgIiAgRmlyaW5nIHNlcnZlciBtb2R1bGUgc3RhdGUgY2hhbmdlIGV2ZW50IHRvOiAiICsgc2lsW2ldKTsKCQkJCXNpbFtpXS5tb2R1bGVTdGF0ZUNoYW5nZSh0aGlzLCBwYXJlbnRzLCBtb2R1bGUpOwoJCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiICBFcnJvciBmaXJpbmcgc2VydmVyIG1vZHVsZSBzdGF0ZSBjaGFuZ2UgZXZlbnQiLCBlKTsKCQkJfQoJCX0KCQlUcmFjZS50cmFjZShUcmFjZS5MSVNURU5FUlMsICItPC0gRG9uZSBmaXJpbmcgc2VydmVyIG1vZHVsZSBzdGF0ZSBjaGFuZ2UgZXZlbnQgLTwtIik7Cgl9CgoJcHVibGljIHZvaWQgc2V0TW9kZShTdHJpbmcgbSkgewoJCXRoaXMubW9kZSA9IG07Cgl9CgoJcHVibGljIHZvaWQgc2V0TW9kdWxlcyhJTW9kdWxlW10gbW9kdWxlcykgewoJCXRoaXMuc2VydmVyTW9kdWxlcyA9IG1vZHVsZXM7Cgl9CgoJcHVibGljIHZvaWQgc2V0TW9kdWxlU3RhdGUoSU1vZHVsZSBtb2R1bGUsIGludCBzdGF0ZSkgewoJCUludGVnZXIgaW4gPSBuZXcgSW50ZWdlcihzdGF0ZSk7CgkJbW9kdWxlU3RhdGUucHV0KG1vZHVsZS5nZXRJZCgpLCBpbik7CgkJZmlyZVNlcnZlck1vZHVsZVN0YXRlQ2hhbmdlRXZlbnQobW9kdWxlKTsKCX0KCQoJcHVibGljIHZvaWQgc2V0TW9kdWxlUHVibGlzaFN0YXRlKElNb2R1bGUgbW9kdWxlLCBpbnQgc3RhdGUpIHsKCQlJbnRlZ2VyIGluID0gbmV3IEludGVnZXIoc3RhdGUpOwoJCW1vZHVsZVB1Ymxpc2hTdGF0ZS5wdXQobW9kdWxlLmdldElkKCksIGluKTsKCQkvL2ZpcmVTZXJ2ZXJNb2R1bGVTdGF0ZUNoYW5nZUV2ZW50KG1vZHVsZSk7Cgl9CgoJcHVibGljIHZvaWQgc2V0TW9kdWxlUmVzdGFydFN0YXRlKElNb2R1bGUgbW9kdWxlLCBib29sZWFuIHIpIHsKCQlCb29sZWFuIGIgPSBuZXcgQm9vbGVhbihyKTsKCQltb2R1bGVTdGF0ZS5wdXQobW9kdWxlLmdldElkKCksIGIpOwoJCS8vZmlyZVNlcnZlck1vZHVsZVN0YXRlQ2hhbmdlRXZlbnQobW9kdWxlKTsKCX0KCglwcm90ZWN0ZWQgdm9pZCBoYW5kbGVNb2R1bGVQcm9qZWN0Q2hhbmdlKGZpbmFsIElNb2R1bGUgbW9kdWxlKSB7CgkJVHJhY2UudHJhY2UoVHJhY2UuRklORVNULCAiPiBoYW5kbGVEZXBsb3lhYmxlUHJvamVjdENoYW5nZSgpICIgKyB0aGlzICsgIiAiICsgbW9kdWxlKTsKCQkKCQljbGFzcyBIZWxwZXIgewoJCQlib29sZWFuIGNoYW5nZWQ7CgkJfQoJCWZpbmFsIEhlbHBlciBoZWxwZXIgPSBuZXcgSGVscGVyKCk7CgkJCgkJSU1vZHVsZVZpc2l0b3IgdmlzaXRvciA9IG5ldyBJTW9kdWxlVmlzaXRvcigpIHsKCQkJcHVibGljIGJvb2xlYW4gdmlzaXQoSU1vZHVsZVtdIHBhcmVudHMyLCBJTW9kdWxlIG1vZHVsZTIpIHsKCQkJCWlmIChtb2R1bGUyLmdldFByb2plY3QoKSA9PSBudWxsKQoJCQkJCXJldHVybiB0cnVlOwoJCQkJCgkJCQlpZiAobW9kdWxlLmVxdWFscyhtb2R1bGUyKSkgewoJCQkJCUlNb2R1bGVSZXNvdXJjZURlbHRhW10gZGVsdGEyID0gZ2V0UHVibGlzaGVkUmVzb3VyY2VEZWx0YShwYXJlbnRzMiwgbW9kdWxlMik7CgkJCQkJaWYgKGRlbHRhMi5sZW5ndGggPiAwKQoJCQkJCQloZWxwZXIuY2hhbmdlZCA9IHRydWU7CgkJCQkJCgkJCQkJLy8gVE9ETwoJCQkJCS8qaWYgKGRlcGxveWFibGVEZWx0YVtpXSA9PSBudWxsKQoJCQkJCQlkZXBsb3lhYmxlRGVsdGFbaV0gPSBtb2R1bGVQcm9qZWN0c1tpXS5nZXRNb2R1bGVSZXNvdXJjZURlbHRhKGRlbHRhKTsKCQkJCQkKCQkJCQlpZiAoZGVwbG95YWJsZURlbHRhW2ldICE9IG51bGwpIHsKCQkJCQkJLy8gdXBkYXRlRGVwbG95YWJsZShtb2R1bGUsIGRlcGxveWFibGVEZWx0YVtpXSk7CgoJCQkJCQlNb2R1bGVQdWJsaXNoSW5mbyBjb250cm9sID0gUHVibGlzaEluZm8uZ2V0UHVibGlzaEluZm8oKS5nZXRQdWJsaXNoQ29udHJvbChTZXJ2ZXIudGhpcywgcGFyZW50cywgbW9kdWxlKTsKCQkJCQkJaWYgKGNvbnRyb2wuaXNEaXJ0eSgpKQoJCQkJCQkJcmV0dXJuIHRydWU7CgkKCQkJCQkJY29udHJvbC5zZXREaXJ0eSh0cnVlKTsKCQkJCQkJZmlyZVB1Ymxpc2hTdGF0ZUNoYW5nZShwYXJlbnRzLCBtb2R1bGUpOwoJCQkJCX0qLwoJCQkJCXJldHVybiB0cnVlOwoJCQkJfQoJCQkJcmV0dXJuIHRydWU7CgkJCX0KCQl9OwoKCQl2aXNpdCh2aXNpdG9yLCBudWxsKTsKCQkKCQlpZiAoIWhlbHBlci5jaGFuZ2VkKQoJCQlyZXR1cm47CgkJCgkJLy8gY2hlY2sgZm9yIGF1dG8tcHVibGlzaAoJCWlmIChhdXRvUHVibGlzaFRocmVhZCAhPSBudWxsKSB7CgkJCWF1dG9QdWJsaXNoVGhyZWFkLnN0b3AgPSB0cnVlOwoJCQlhdXRvUHVibGlzaFRocmVhZC5pbnRlcnJ1cHQoKTsKCQkJYXV0b1B1Ymxpc2hUaHJlYWQgPSBudWxsOwoJCX0KCQkKCQlpbnQgdGltZSA9IDA7CgkJaWYgKGdldEF1dG9QdWJsaXNoRGVmYXVsdCgpKSB7CgkJCWJvb2xlYW4gbG9jYWwgPSBTb2NrZXRVdGlsLmlzTG9jYWxob3N0KGdldEhvc3QoKSk7CgkJCWlmIChsb2NhbCAmJiBTZXJ2ZXJQcmVmZXJlbmNlcy5nZXRJbnN0YW5jZSgpLmdldEF1dG9QdWJsaXNoTG9jYWwoKSkKCQkJCXRpbWUgPSBTZXJ2ZXJQcmVmZXJlbmNlcy5nZXRJbnN0YW5jZSgpLmdldEF1dG9QdWJsaXNoTG9jYWxUaW1lKCk7CgkJCWVsc2UgaWYgKCFsb2NhbCAmJiBTZXJ2ZXJQcmVmZXJlbmNlcy5nZXRJbnN0YW5jZSgpLmdldEF1dG9QdWJsaXNoUmVtb3RlKCkpCgkJCQl0aW1lID0gU2VydmVyUHJlZmVyZW5jZXMuZ2V0SW5zdGFuY2UoKS5nZXRBdXRvUHVibGlzaFJlbW90ZVRpbWUoKTsKCQl9IGVsc2UgewoJCQl0aW1lID0gZ2V0QXV0b1B1Ymxpc2hUaW1lKCk7CgkJfQoJCQoJCWlmICh0aW1lID4gNSkgewoJCQlhdXRvUHVibGlzaFRocmVhZCA9IG5ldyBBdXRvUHVibGlzaFRocmVhZCgpOwoJCQlhdXRvUHVibGlzaFRocmVhZC50aW1lID0gdGltZTsKCQkJYXV0b1B1Ymxpc2hUaHJlYWQuc2V0UHJpb3JpdHkoVGhyZWFkLk1JTl9QUklPUklUWSArIDEpOwoJCQlhdXRvUHVibGlzaFRocmVhZC5zdGFydCgpOwoJCX0KCQkKCQkvL1RyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgIjwgaGFuZGxlRGVwbG95YWJsZVByb2plY3RDaGFuZ2UoKSIpOwoJfQoKCS8qKgoJICogUmV0dXJucyB0aGUgY29uZmlndXJhdGlvbidzIHN5bmMgc3RhdGUuCgkgKgoJICogQHJldHVybiBpbnQKCSAqLwoJcHVibGljIGludCBnZXRTZXJ2ZXJQdWJsaXNoU3RhdGUoKSB7CgkJcmV0dXJuIHNlcnZlclN5bmNTdGF0ZTsKCX0KCgkvKioKCSAqIFNldHMgdGhlIGNvbmZpZ3VyYXRpb24gc3luYyBzdGF0ZS4KCSAqCgkgKiBAcGFyYW0gc3RhdGUgaW50CgkgKi8KCXB1YmxpYyB2b2lkIHNldFNlcnZlclB1Ymxpc2hTdGF0ZShpbnQgc3RhdGUpIHsKCQlpZiAoc3RhdGUgPT0gc2VydmVyU3luY1N0YXRlKQoJCQlyZXR1cm47CgkJc2VydmVyU3luY1N0YXRlID0gc3RhdGU7CgkJZmlyZUNvbmZpZ3VyYXRpb25TeW5jU3RhdGVDaGFuZ2VFdmVudCgpOwoJfQoKCS8qKgoJICogQWRkcyBhIHB1Ymxpc2ggbGlzdGVuZXIgdG8gdGhpcyBzZXJ2ZXIuCgkgKiBIYXMgbm8gZWZmZWN0IGlmIGFuIGlkZW50aWNhbCBsaXN0ZW5lciBpcyBhbHJlYWR5IHJlZ2lzdGVyZWQuCgkgKgoJICogQHBhcmFtIGxpc3RlbmVyIHRoZSBwdWJsaXNoIGxpc3RlbmVyCgkgKiBAc2VlICNyZW1vdmVQdWJsaXNoTGlzdGVuZXIoSVB1Ymxpc2hMaXN0ZW5lcikKCSAqLwoJcHVibGljIHZvaWQgYWRkUHVibGlzaExpc3RlbmVyKElQdWJsaXNoTGlzdGVuZXIgbGlzdGVuZXIpIHsKCQlUcmFjZS50cmFjZShUcmFjZS5MSVNURU5FUlMsICJBZGRpbmcgcHVibGlzaCBsaXN0ZW5lciAiICsgbGlzdGVuZXIgKyAiIHRvICIgKyB0aGlzKTsKCgkJaWYgKHB1Ymxpc2hMaXN0ZW5lcnMgPT0gbnVsbCkKCQkJcHVibGlzaExpc3RlbmVycyA9IG5ldyBBcnJheUxpc3QoKTsKCQlwdWJsaXNoTGlzdGVuZXJzLmFkZChsaXN0ZW5lcik7Cgl9CgoJLyoqCgkgKiBSZW1vdmVzIGEgcHVibGlzaCBsaXN0ZW5lciBmcm9tIHRoaXMgc2VydmVyLgoJICogSGFzIG5vIGVmZmVjdCBpZiB0aGUgbGlzdGVuZXIgaXMgbm90IHJlZ2lzdGVyZWQuCgkgKgoJICogQHBhcmFtIGxpc3RlbmVyIHRoZSBwdWJsaXNoIGxpc3RlbmVyCgkgKiBAc2VlICNhZGRQdWJsaXNoTGlzdGVuZXIoSVB1Ymxpc2hMaXN0ZW5lcikKCSAqLwoJcHVibGljIHZvaWQgcmVtb3ZlUHVibGlzaExpc3RlbmVyKElQdWJsaXNoTGlzdGVuZXIgbGlzdGVuZXIpIHsKCQlUcmFjZS50cmFjZShUcmFjZS5MSVNURU5FUlMsICJSZW1vdmluZyBwdWJsaXNoIGxpc3RlbmVyICIgKyBsaXN0ZW5lciArICIgZnJvbSAiICsgdGhpcyk7CgoJCWlmIChwdWJsaXNoTGlzdGVuZXJzICE9IG51bGwpCgkJCXB1Ymxpc2hMaXN0ZW5lcnMucmVtb3ZlKGxpc3RlbmVyKTsKCX0KCQoJLyoqCgkgKiBGaXJlIGEgcHVibGlzaCBzdGFydCBldmVudC4KCSAqCgkgKiBAcGFyYW0gCgkgKi8KCXByaXZhdGUgdm9pZCBmaXJlUHVibGlzaFN0YXJ0ZWQoKSB7CgkJVHJhY2UudHJhY2UoVHJhY2UuRklORVNULCAiLT4tIEZpcmluZyBwdWJsaXNoIHN0YXJ0ZWQgZXZlbnQgLT4tIik7CgkKCQlpZiAocHVibGlzaExpc3RlbmVycyA9PSBudWxsIHx8IHB1Ymxpc2hMaXN0ZW5lcnMuaXNFbXB0eSgpKQoJCQlyZXR1cm47CgoJCWludCBzaXplID0gcHVibGlzaExpc3RlbmVycy5zaXplKCk7CgkJSVB1Ymxpc2hMaXN0ZW5lcltdIHNybCA9IG5ldyBJUHVibGlzaExpc3RlbmVyW3NpemVdOwoJCXB1Ymxpc2hMaXN0ZW5lcnMudG9BcnJheShzcmwpOwoKCQlmb3IgKGludCBpID0gMDsgaSA8IHNpemU7IGkrKykgewoJCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICIgIEZpcmluZyBwdWJsaXNoIHN0YXJ0ZWQgZXZlbnQgdG8gIiArIHNybFtpXSk7CgkJCXRyeSB7CgkJCQlzcmxbaV0ucHVibGlzaFN0YXJ0ZWQodGhpcyk7CgkJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCQlUcmFjZS50cmFjZShUcmFjZS5TRVZFUkUsICIgIEVycm9yIGZpcmluZyBwdWJsaXNoIHN0YXJ0ZWQgZXZlbnQgdG8gIiArIHNybFtpXSwgZSk7CgkJCX0KCQl9CgoJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgIi08LSBEb25lIGZpcmluZyBwdWJsaXNoIHN0YXJ0ZWQgZXZlbnQgLTwtIik7Cgl9CgkKCS8qKgoJICogRmlyZSBhIHB1Ymxpc2ggdGFyZ2V0IGV2ZW50LgoJICoKCSAqIEBwYXJhbSAKCSAqLwoJcHJpdmF0ZSB2b2lkIGZpcmVNb2R1bGVQdWJsaXNoU3RhcnRlZChJTW9kdWxlW10gcGFyZW50cywgSU1vZHVsZSBtb2R1bGUpIHsKCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICItPi0gRmlyaW5nIG1vZHVsZSBwdWJsaXNoIHN0YXJ0ZWQgZXZlbnQ6ICIgKyBtb2R1bGUgKyAiIC0+LSIpOwoJCgkJaWYgKHB1Ymxpc2hMaXN0ZW5lcnMgPT0gbnVsbCB8fCBwdWJsaXNoTGlzdGVuZXJzLmlzRW1wdHkoKSkKCQkJcmV0dXJuOwoKCQlpbnQgc2l6ZSA9IHB1Ymxpc2hMaXN0ZW5lcnMuc2l6ZSgpOwoJCUlQdWJsaXNoTGlzdGVuZXJbXSBzcmwgPSBuZXcgSVB1Ymxpc2hMaXN0ZW5lcltzaXplXTsKCQlwdWJsaXNoTGlzdGVuZXJzLnRvQXJyYXkoc3JsKTsKCgkJZm9yIChpbnQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHsKCQkJVHJhY2UudHJhY2UoVHJhY2UuRklORVNULCAiICBGaXJpbmcgbW9kdWxlIHB1Ymxpc2ggc3RhcnRlZCBldmVudCB0byAiICsgc3JsW2ldKTsKCQkJdHJ5IHsKCQkJCXNybFtpXS5wdWJsaXNoTW9kdWxlU3RhcnRlZCh0aGlzLCBwYXJlbnRzLCBtb2R1bGUpOwoJCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiICBFcnJvciBmaXJpbmcgbW9kdWxlIHB1Ymxpc2ggc3RhcnRlZCBldmVudCB0byAiICsgc3JsW2ldLCBlKTsKCQkJfQoJCX0KCgkJVHJhY2UudHJhY2UoVHJhY2UuRklORVNULCAiLTwtIERvbmUgZmlyaW5nIG1vZHVsZSBwdWJsaXNoIHN0YXJ0ZWQgZXZlbnQgLTwtIik7Cgl9CgkKCS8qKgoJICogRmlyZSBhIHB1Ymxpc2ggdGFyZ2V0IGV2ZW50LgoJICoKCSAqIEBwYXJhbSAKCSAqLwoJcHJpdmF0ZSB2b2lkIGZpcmVNb2R1bGVQdWJsaXNoRmluaXNoZWQoSU1vZHVsZVtdIHBhcmVudHMsIElNb2R1bGUgbW9kdWxlLCBJU3RhdHVzIHN0YXR1cykgewoJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgIi0+LSBGaXJpbmcgbW9kdWxlIGZpbmlzaGVkIGV2ZW50OiAiICsgbW9kdWxlICsgIiAiICsgc3RhdHVzICsgIiAtPi0iKTsKCQoJCWlmIChwdWJsaXNoTGlzdGVuZXJzID09IG51bGwgfHwgcHVibGlzaExpc3RlbmVycy5pc0VtcHR5KCkpCgkJCXJldHVybjsKCgkJaW50IHNpemUgPSBwdWJsaXNoTGlzdGVuZXJzLnNpemUoKTsKCQlJUHVibGlzaExpc3RlbmVyW10gc3JsID0gbmV3IElQdWJsaXNoTGlzdGVuZXJbc2l6ZV07CgkJcHVibGlzaExpc3RlbmVycy50b0FycmF5KHNybCk7CgoJCWZvciAoaW50IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKSB7CgkJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgIiAgRmlyaW5nIG1vZHVsZSBmaW5pc2hlZCBldmVudCB0byAiICsgc3JsW2ldKTsKCQkJdHJ5IHsKCQkJCXNybFtpXS5wdWJsaXNoTW9kdWxlRmluaXNoZWQodGhpcywgcGFyZW50cywgbW9kdWxlLCBzdGF0dXMpOwoJCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiICBFcnJvciBmaXJpbmcgbW9kdWxlIGZpbmlzaGVkIGV2ZW50IHRvICIgKyBzcmxbaV0sIGUpOwoJCQl9CgkJfQoKCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICItPC0gRG9uZSBmaXJpbmcgbW9kdWxlIGZpbmlzaGVkIGV2ZW50IC08LSIpOwoJfQoJCgkvKioKCSAqIEZpcmUgYSBwdWJsaXNoIHN0b3AgZXZlbnQuCgkgKgoJICogQHBhcmFtIAoJICovCglwcml2YXRlIHZvaWQgZmlyZVB1Ymxpc2hGaW5pc2hlZChJU3RhdHVzIHN0YXR1cykgewoJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgIi0+LSBGaXJpbmcgcHVibGlzaGluZyBmaW5pc2hlZCBldmVudDogIiArIHN0YXR1cyArICIgLT4tIik7CgkKCQlpZiAocHVibGlzaExpc3RlbmVycyA9PSBudWxsIHx8IHB1Ymxpc2hMaXN0ZW5lcnMuaXNFbXB0eSgpKQoJCQlyZXR1cm47CgoJCWludCBzaXplID0gcHVibGlzaExpc3RlbmVycy5zaXplKCk7CgkJSVB1Ymxpc2hMaXN0ZW5lcltdIHNybCA9IG5ldyBJUHVibGlzaExpc3RlbmVyW3NpemVdOwoJCXB1Ymxpc2hMaXN0ZW5lcnMudG9BcnJheShzcmwpOwoKCQlmb3IgKGludCBpID0gMDsgaSA8IHNpemU7IGkrKykgewoJCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICIgIEZpcmluZyBwdWJsaXNoaW5nIGZpbmlzaGVkIGV2ZW50IHRvICIgKyBzcmxbaV0pOwoJCQl0cnkgewoJCQkJc3JsW2ldLnB1Ymxpc2hGaW5pc2hlZCh0aGlzLCBzdGF0dXMpOwoJCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiICBFcnJvciBmaXJpbmcgcHVibGlzaGluZyBmaW5pc2hlZCBldmVudCB0byAiICsgc3JsW2ldLCBlKTsKCQkJfQoJCX0KCgkJVHJhY2UudHJhY2UoVHJhY2UuRklORVNULCAiLTwtIERvbmUgZmlyaW5nIHB1Ymxpc2hpbmcgZmluaXNoZWQgZXZlbnQgLTwtIik7Cgl9CgoJLyoqCgkgKiBGaXJlIGEgcHVibGlzaCBzdGF0ZSBjaGFuZ2UgZXZlbnQuCgkgKi8KCXByb3RlY3RlZCB2b2lkIGZpcmVQdWJsaXNoU3RhdGVDaGFuZ2UoSU1vZHVsZVtdIHBhcmVudHMsIElNb2R1bGUgbW9kdWxlKSB7CgkJVHJhY2UudHJhY2UoVHJhY2UuRklORVNULCAiLT4tIEZpcmluZyBwdWJsaXNoIHN0YXRlIGNoYW5nZSBldmVudDogIiArIG1vZHVsZSArICIgLT4tIik7CgkKCQlpZiAoc2VydmVyTGlzdGVuZXJzID09IG51bGwgfHwgc2VydmVyTGlzdGVuZXJzLmlzRW1wdHkoKSkKCQkJcmV0dXJuOwoKCQlpbnQgc2l6ZSA9IHNlcnZlckxpc3RlbmVycy5zaXplKCk7CgkJSVNlcnZlckxpc3RlbmVyW10gc2wgPSBuZXcgSVNlcnZlckxpc3RlbmVyW3NpemVdOwoJCXNlcnZlckxpc3RlbmVycy50b0FycmF5KHNsKTsKCgkJZm9yIChpbnQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHsKCQkJVHJhY2UudHJhY2UoVHJhY2UuRklORVNULCAiICBGaXJpbmcgcHVibGlzaCBzdGF0ZSBjaGFuZ2UgZXZlbnQgdG8gIiArIHNsW2ldKTsKCQkJdHJ5IHsKCQkJCXNsW2ldLm1vZHVsZVN0YXRlQ2hhbmdlKHRoaXMsIHBhcmVudHMsIG1vZHVsZSk7CgkJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCQlUcmFjZS50cmFjZShUcmFjZS5TRVZFUkUsICIgIEVycm9yIGZpcmluZyBwdWJsaXNoIHN0YXRlIGNoYW5nZSBldmVudCB0byAiICsgc2xbaV0sIGUpOwoJCQl9CgkJfQoKCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICItPC0gRG9uZSBmaXJpbmcgcHVibGlzaCBzdGF0ZSBjaGFuZ2UgZXZlbnQgLTwtIik7Cgl9CgoJLyoqCgkgKiBSZXR1cm5zIHRydWUgaWYgdGhlIHNlcnZlciBpcyBpbiBhIHN0YXRlIHRoYXQgaXQgY2FuCgkgKiBiZSBwdWJsaXNoZWQgdG8uCgkgKgoJICogQHJldHVybiBib29sZWFuCgkgKiBUT0RPOiBmaXggcmV0dXJuIHN0cmluZ3MgCgkgKi8KCXB1YmxpYyBJU3RhdHVzIGNhblB1Ymxpc2goKSB7CgkJLy8gY2FuJ3QgcHVibGlzaCBpZiB0aGUgc2VydmVyIGlzIHN0YXJ0aW5nIG9yIHN0b3BwaW5nCgkJaW50IHN0YXRlID0gZ2V0U2VydmVyU3RhdGUoKTsKCQlpZiAoc3RhdGUgPT0gU1RBVEVfU1RBUlRJTkcgfHwgc3RhdGUgPT0gU1RBVEVfU1RPUFBJTkcpCgkJCXJldHVybiBuZXcgU3RhdHVzKElTdGF0dXMuRVJST1IsIFNlcnZlclBsdWdpbi5QTFVHSU5fSUQsIDAsIFNlcnZlclBsdWdpbi5nZXRSZXNvdXJjZSgiJWVycm9yTGF1bmNoTW9kZSIpLCBudWxsKTsKCQoJCS8vIGNhbid0IHB1Ymxpc2ggaWYgdGhlcmUgaXMgbm8gY29uZmlndXJhdGlvbgoJCWlmIChnZXRTZXJ2ZXJUeXBlKCkgPT0gbnVsbCB8fCBnZXRTZXJ2ZXJUeXBlKCkuaGFzU2VydmVyQ29uZmlndXJhdGlvbigpICYmIGNvbmZpZ3VyYXRpb24gPT0gbnVsbCkKCQkJcmV0dXJuIG5ldyBTdGF0dXMoSVN0YXR1cy5FUlJPUiwgU2VydmVyUGx1Z2luLlBMVUdJTl9JRCwgMCwgU2VydmVyUGx1Z2luLmdldFJlc291cmNlKCIlZXJyb3JMYXVuY2hNb2RlIiksIG51bGwpOwoJCgkJLy8gcmV0dXJuIHRydWUgaWYgdGhlIGNvbmZpZ3VyYXRpb24gY2FuIGJlIHB1Ymxpc2hlZAoJCWlmIChnZXRTZXJ2ZXJQdWJsaXNoU3RhdGUoKSAhPSBQVUJMSVNIX1NUQVRFX05PTkUpCgkJCXJldHVybiBuZXcgU3RhdHVzKElTdGF0dXMuT0ssIFNlcnZlclBsdWdpbi5QTFVHSU5fSUQsIDAsIFNlcnZlclBsdWdpbi5nZXRSZXNvdXJjZSgiJWVycm9yTGF1bmNoTW9kZSIpLCBudWxsKTsKCgkJLy8gcmV0dXJuIHRydWUgaWYgYW55IG1vZHVsZXMgY2FuIGJlIHB1Ymxpc2hlZAoJCWNsYXNzIFRlbXAgewoJCQlib29sZWFuIGZvdW5kID0gZmFsc2U7CgkJfQoJCS8vZmluYWwgVGVtcCB0ZW1wID0gbmV3IFRlbXAoKTsKCQkKCQlyZXR1cm4gbmV3IFN0YXR1cyhJU3RhdHVzLk9LLCBTZXJ2ZXJQbHVnaW4uUExVR0lOX0lELCAwLCBTZXJ2ZXJQbHVnaW4uZ2V0UmVzb3VyY2UoIiVlcnJvckxhdW5jaE1vZGUiKSwgbnVsbCk7CgkKCQkvKklNb2R1bGVWaXNpdG9yIHZpc2l0b3IgPSBuZXcgSU1vZHVsZVZpc2l0b3IoKSB7CgkJCXB1YmxpYyBib29sZWFuIHZpc2l0KElNb2R1bGVbXSBwYXJlbnRzLCBJTW9kdWxlIG1vZHVsZSkgewoJCQkJaWYgKGdldE1vZHVsZVB1Ymxpc2hTdGF0ZShtb2R1bGUpICE9IFBVQkxJU0hfU1RBVEVfTk9ORSkgewoJCQkJCXRlbXAuZm91bmQgPSB0cnVlOwoJCQkJCXJldHVybiBmYWxzZTsKCQkJCX0KCQkJCXJldHVybiB0cnVlOwoJCQl9CgkJfTsKCQlTZXJ2ZXJVdGlsLnZpc2l0KHRoaXMsIHZpc2l0b3IsIG51bGwpOwoJCQoJCXJldHVybiB0ZW1wLmZvdW5kOyovCgl9CgoJLyoqCgkgKiBSZXR1cm5zIHRydWUgaWYgdGhlIHNlcnZlciBpcyBpbiBhIHN0YXRlIHRoYXQgaXQgY2FuCgkgKiBiZSBwdWJsaXNoZWQgdG8uCgkgKgoJICogQHJldHVybiBib29sZWFuCgkgKi8KCXB1YmxpYyBib29sZWFuIHNob3VsZFB1Ymxpc2goKSB7CgkJaWYgKCFjYW5QdWJsaXNoKCkuaXNPSygpKQoJCQlyZXR1cm4gZmFsc2U7CgkKCQlpZiAoZ2V0U2VydmVyUHVibGlzaFN0YXRlKCkgIT0gUFVCTElTSF9TVEFURV9OT05FKQoJCQlyZXR1cm4gdHJ1ZTsKCQoJCS8vaWYgKGdldFVucHVibGlzaGVkTW9kdWxlcygpLmxlbmd0aCA+IDApCgkJcmV0dXJuIHRydWU7CgkKCQkvL3JldHVybiBmYWxzZTsKCX0KCQoKCS8qKgoJICogUmV0dXJucyBhIGxpc3Qgb2YgdGhlIHByb2plY3RzIHRoYXQgaGF2ZSBub3QgYmVlbiBwdWJsaXNoZWQKCSAqIHNpbmNlIHRoZSBsYXN0IG1vZGlmaWNhdGlvbi4gKGkuZS4gdGhlIHByb2plY3RzIHRoYXQgYXJlCgkgKiBvdXQgb2Ygc3luYyB3aXRoIHRoZSBzZXJ2ZXIuCgkgKgoJICogQHJldHVybiBqYXZhLnV0aWwuTGlzdAoJICovCgkvKnB1YmxpYyBJTW9kdWxlW10gZ2V0VW5wdWJsaXNoZWRNb2R1bGVzKCkgewoJCWZpbmFsIExpc3QgbW9kdWxlcyA9IG5ldyBBcnJheUxpc3QoKTsKCQlJTW9kdWxlVmlzaXRvciB2aXNpdG9yID0gbmV3IElNb2R1bGVWaXNpdG9yKCkgewoJCQlwdWJsaWMgYm9vbGVhbiB2aXNpdChJTW9kdWxlW10gcGFyZW50cywgSU1vZHVsZSBtb2R1bGUpIHsKCQkJCWlmIChnZXRNb2R1bGVQdWJsaXNoU3RhdGUobW9kdWxlKSAhPSBQVUJMSVNIX1NUQVRFX05PTkUgJiYgIW1vZHVsZXMuY29udGFpbnMobW9kdWxlKSkgewoJCQkJCU1vZHVsZVB1Ymxpc2hJbmZvIGNvbnRyb2wgPSBQdWJsaXNoSW5mby5nZXRQdWJsaXNoSW5mbygpLmdldFB1Ymxpc2hDb250cm9sKFNlcnZlci50aGlzLCBwYXJlbnRzLCBtb2R1bGUpOwoJCQkJCWlmIChjb250cm9sLmlzRGlydHkpCgkJCQkJCW1vZHVsZXMuYWRkKG1vZHVsZSk7CgkJCQl9CgkJCQlyZXR1cm4gdHJ1ZTsKCQkJfQoJCX07CgkJU2VydmVyVXRpbC52aXNpdCh0aGlzLCB2aXNpdG9yLCBudWxsKTsKCQkKCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICJVbnB1Ymxpc2hlZCBtb2R1bGVzOiAiICsgbW9kdWxlcyk7CgkJCgkJSU1vZHVsZVtdIG0gPSBuZXcgSU1vZHVsZVttb2R1bGVzLnNpemUoKV07CgkJbW9kdWxlcy50b0FycmF5KG0pOwoJCXJldHVybiBtOwoJfSovCgoJcHJvdGVjdGVkIFNlcnZlclB1Ymxpc2hJbmZvIGdldFNlcnZlclB1Ymxpc2hJbmZvKCkgewoJCWlmIChwdWJsaXNoSW5mbyA9PSBudWxsKSB7CgkJCXB1Ymxpc2hJbmZvID0gUHVibGlzaEluZm8uZ2V0SW5zdGFuY2UoKS5nZXRTZXJ2ZXJQdWJsaXNoSW5mbyh0aGlzKTsKCQl9CgkJcmV0dXJuIHB1Ymxpc2hJbmZvOwoJfQoKCS8qCgkgKiBQdWJsaXNoIHRvIHRoZSBzZXJ2ZXIgdXNpbmcgdGhlIHByb2dyZXNzIG1vbml0b3IuIFRoZSByZXN1bHQgb2YgdGhlCgkgKiBwdWJsaXNoIG9wZXJhdGlvbiBpcyByZXR1cm5lZCBhcyBhbiBJU3RhdHVzLgoJICovCglwdWJsaWMgSVN0YXR1cyBwdWJsaXNoKElQcm9ncmVzc01vbml0b3IgbW9uaXRvcikgewoJCXJldHVybiBwdWJsaXNoKFBVQkxJU0hfSU5DUkVNRU5UQUwsIG1vbml0b3IpOwoJfQoKCS8qCgkgKiBQdWJsaXNoIHRvIHRoZSBzZXJ2ZXIgdXNpbmcgdGhlIHByb2dyZXNzIG1vbml0b3IuIFRoZSByZXN1bHQgb2YgdGhlCgkgKiBwdWJsaXNoIG9wZXJhdGlvbiBpcyByZXR1cm5lZCBhcyBhbiBJU3RhdHVzLgoJICovCglwdWJsaWMgSVN0YXR1cyBwdWJsaXNoKGZpbmFsIGludCBraW5kLCBJUHJvZ3Jlc3NNb25pdG9yIG1vbml0b3IpIHsKCQlpZiAoZ2V0U2VydmVyVHlwZSgpID09IG51bGwpCgkJCXJldHVybiBuZXcgU3RhdHVzKElTdGF0dXMuRVJST1IsIFNlcnZlclBsdWdpbi5QTFVHSU5fSUQsIDAsIFNlcnZlclBsdWdpbi5nZXRSZXNvdXJjZSgiJWVycm9yUHVibGlzaGluZyIpLCBudWxsKTsKCgkJLy8gY2hlY2sgd2hhdCBpcyBvdXQgb2Ygc3luYyBhbmQgcHVibGlzaAoJCWlmIChnZXRTZXJ2ZXJUeXBlKCkuaGFzU2VydmVyQ29uZmlndXJhdGlvbigpICYmIGNvbmZpZ3VyYXRpb24gPT0gbnVsbCkKCQkJcmV0dXJuIG5ldyBTdGF0dXMoSVN0YXR1cy5FUlJPUiwgU2VydmVyUGx1Z2luLlBMVUdJTl9JRCwgMCwgU2VydmVyUGx1Z2luLmdldFJlc291cmNlKCIlZXJyb3JOb0NvbmZpZ3VyYXRpb24iKSwgbnVsbCk7CgkJCgkJcmV0dXJuIGRvUHVibGlzaChraW5kLCBtb25pdG9yKTsKCX0KCglwcm90ZWN0ZWQgSVN0YXR1cyBkb1B1Ymxpc2goaW50IGtpbmQsIElQcm9ncmVzc01vbml0b3IgbW9uaXRvcikgewoJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgIi0tPi0tIFB1Ymxpc2hpbmcgdG8gc2VydmVyOiAiICsgdG9TdHJpbmcoKSArICIgLS0+LS0iKTsKCgkJZmluYWwgTGlzdCBwYXJlbnRMaXN0ID0gbmV3IEFycmF5TGlzdCgpOwoJCWZpbmFsIExpc3QgbW9kdWxlTGlzdCA9IG5ldyBBcnJheUxpc3QoKTsKCQlmaW5hbCBMaXN0IHRhc2tQYXJlbnRMaXN0ID0gbmV3IEFycmF5TGlzdCgpOwoJCWZpbmFsIExpc3Qga2luZExpc3QgPSBuZXcgQXJyYXlMaXN0KCk7CgkJCgkJZmluYWwgU2VydmVyUHVibGlzaEluZm8gc3BpID0gZ2V0U2VydmVyUHVibGlzaEluZm8oKTsKCQkKCQlJTW9kdWxlVmlzaXRvciB2aXNpdG9yID0gbmV3IElNb2R1bGVWaXNpdG9yKCkgewoJCQlwdWJsaWMgYm9vbGVhbiB2aXNpdChJTW9kdWxlW10gcGFyZW50cywgSU1vZHVsZSBtb2R1bGUpIHsKCQkJCWludCBzaXplID0gcGFyZW50cy5sZW5ndGg7CgkJCQlMaXN0IGxpc3QgPSBuZXcgQXJyYXlMaXN0KHNpemUpOwoJCQkJZm9yIChpbnQgaSA9IDA7IGkgPCBzaXplOyBpKyspCgkJCQkJbGlzdC5hZGQocGFyZW50c1tpXSk7CgkJCQkKCQkJCXRhc2tQYXJlbnRMaXN0LmFkZChsaXN0KTsKCQkJCWlmIChwYXJlbnRzICE9IG51bGwpCgkJCQkJcGFyZW50TGlzdC5hZGQocGFyZW50cyk7CgkJCQllbHNlCgkJCQkJcGFyZW50TGlzdC5hZGQoRU1QVFlfTElTVCk7CgkJCQltb2R1bGVMaXN0LmFkZChtb2R1bGUpOwoJCQkJCgkJCQlpZiAoc3BpLmhhc01vZHVsZVB1Ymxpc2hJbmZvKHBhcmVudHMsIG1vZHVsZSkpIHsKCQkJCQlpZiAoZ2V0UHVibGlzaGVkUmVzb3VyY2VEZWx0YShwYXJlbnRzLCBtb2R1bGUpLmxlbmd0aCA9PSAwKQoJCQkJCQlraW5kTGlzdC5hZGQobmV3IEludGVnZXIoTk9fQ0hBTkdFKSk7CgkJCQkJZWxzZQoJCQkJCQlraW5kTGlzdC5hZGQobmV3IEludGVnZXIoQ0hBTkdFRCkpOwoJCQkJfSBlbHNlCgkJCQkJa2luZExpc3QuYWRkKG5ldyBJbnRlZ2VyKEFEREVEKSk7CgkJCQlyZXR1cm4gdHJ1ZTsKCQkJfQoJCX07CgoJCXZpc2l0KHZpc2l0b3IsIG1vbml0b3IpOwoJCQoJCS8vIGJ1aWxkIGFycmF5cyAmIGxpc3RzCgkJTGlzdFtdIHRhc2tQYXJlbnRzID0gbmV3IExpc3RbdGFza1BhcmVudExpc3Quc2l6ZSgpXTsKCQl0YXNrUGFyZW50TGlzdC50b0FycmF5KHRhc2tQYXJlbnRzKTsKCQlMaXN0IHBhcmVudHMgPSBwYXJlbnRMaXN0OwoJCUlNb2R1bGVbXSBtb2R1bGVzMiA9IG5ldyBJTW9kdWxlW21vZHVsZUxpc3Quc2l6ZSgpXTsKCQltb2R1bGVMaXN0LnRvQXJyYXkobW9kdWxlczIpOwoJCQoJCUxpc3QgdGFza3MgPSBnZXRUYXNrcyh0YXNrUGFyZW50cywgbW9kdWxlczIpOwoJCQoJCXNwaS5hZGRSZW1vdmVkTW9kdWxlcyhwYXJlbnRMaXN0LCBtb2R1bGVMaXN0LCBraW5kTGlzdCk7CgkJCgkJcGFyZW50cyA9IHBhcmVudExpc3Q7CgkJbW9kdWxlczIgPSBuZXcgSU1vZHVsZVttb2R1bGVMaXN0LnNpemUoKV07CgkJbW9kdWxlTGlzdC50b0FycmF5KG1vZHVsZXMyKTsKCQkKCQlpbnQgc2l6ZSA9IHBhcmVudHMuc2l6ZSgpOwoJCWludFtdIGRlbHRhS2luZCA9IG5ldyBpbnRbc2l6ZV07CgkJZm9yIChpbnQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHsKCQkJSW50ZWdlciBpbiA9IChJbnRlZ2VyKSBraW5kTGlzdC5nZXQoaSk7CgkJCWRlbHRhS2luZFtpXSA9IGluLmludFZhbHVlKCk7CgkJfQoKCQlzaXplID0gMjAwMCArIDM1MDAgKiBwYXJlbnRMaXN0LnNpemUoKTsKCQkKCQkvLyBmaW5kIHRhc2tzCgkJc2l6ZSArPSB0YXNrcy5zaXplKCkgKiA1MDA7CgkJCgkJbW9uaXRvciA9IFByb2dyZXNzVXRpbC5nZXRNb25pdG9yRm9yKG1vbml0b3IpOwoJCW1vbml0b3IuYmVnaW5UYXNrKFNlcnZlclBsdWdpbi5nZXRSZXNvdXJjZSgiJXB1Ymxpc2hpbmciLCB0b1N0cmluZygpKSwgc2l6ZSk7CgoJCS8vIFRPRE8gLSBncm91cCB1cCBzdGF0dXMgdW50aWwgdGhlIGVuZCBhbmQgdXNlIGJldHRlciBtZXNzYWdlIGJhc2VkIG9uIHN1Y2Nlc3Mgb3IgZmFpbHVyZQoJCU11bHRpU3RhdHVzIG11bHRpID0gbmV3IE11bHRpU3RhdHVzKFNlcnZlclBsdWdpbi5QTFVHSU5fSUQsIDAsIFNlcnZlclBsdWdpbi5nZXRSZXNvdXJjZSgiJXB1Ymxpc2hpbmdTdGF0dXMiKSwgbnVsbCk7CgkJCgkJLy8gcGVyZm9ybSB0YXNrcwoJCUlTdGF0dXMgdGFza1N0YXR1cyA9IHBlcmZvcm1UYXNrcyh0YXNrcywgbW9uaXRvcik7CgkJaWYgKHRhc2tTdGF0dXMgIT0gbnVsbCkKCQkJbXVsdGkuYWRkKHRhc2tTdGF0dXMpOwoKCQlpZiAobW9uaXRvci5pc0NhbmNlbGVkKCkpCgkJCXJldHVybiBuZXcgU3RhdHVzKElTdGF0dXMuSU5GTywgU2VydmVyUGx1Z2luLlBMVUdJTl9JRCwgMCwgU2VydmVyUGx1Z2luLmdldFJlc291cmNlKCIlcHVibGlzaGluZ0NhbmNlbGxlZCIpLCBudWxsKTsKCQkKCQkvLyBzdGFydCBwdWJsaXNoaW5nCgkJVHJhY2UudHJhY2UoVHJhY2UuRklORVNULCAiQ2FsbGluZyBwdWJsaXNoU3RhcnQoKSIpOwoJCWZpcmVQdWJsaXNoU3RhcnRlZCgpOwoJCXRyeSB7CgkJCWdldEJlaGF2aW91ckRlbGVnYXRlKCkucHVibGlzaFN0YXJ0KFByb2dyZXNzVXRpbC5nZXRTdWJNb25pdG9yRm9yKG1vbml0b3IsIDEwMDApKTsKCQl9IGNhdGNoIChDb3JlRXhjZXB0aW9uIGNlKSB7CgkJCVRyYWNlLnRyYWNlKFRyYWNlLklORk8sICJDb3JlRXhjZXB0aW9uIHB1Ymxpc2hpbmcgdG8gIiArIHRvU3RyaW5nKCksIGNlKTsKCQkJZmlyZVB1Ymxpc2hGaW5pc2hlZChjZS5nZXRTdGF0dXMoKSk7CgkJCXJldHVybiBjZS5nZXRTdGF0dXMoKTsKCQl9CgkJCgkJLy8gcHVibGlzaCB0aGUgc2VydmVyCgkJdHJ5IHsKCQkJaWYgKCFtb25pdG9yLmlzQ2FuY2VsZWQoKSAmJiBzZXJ2ZXJUeXBlLmhhc1NlcnZlckNvbmZpZ3VyYXRpb24oKSkgewoJCQkJZ2V0QmVoYXZpb3VyRGVsZWdhdGUoKS5wdWJsaXNoU2VydmVyKGtpbmQsIFByb2dyZXNzVXRpbC5nZXRTdWJNb25pdG9yRm9yKG1vbml0b3IsIDEwMDApKTsKCQkJfQoJCX0gY2F0Y2ggKENvcmVFeGNlcHRpb24gY2UpIHsKCQkJVHJhY2UudHJhY2UoVHJhY2UuSU5GTywgIkNvcmVFeGNlcHRpb24gcHVibGlzaGluZyB0byAiICsgdG9TdHJpbmcoKSwgY2UpOwoJCQltdWx0aS5hZGQoY2UuZ2V0U3RhdHVzKCkpOwoJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCVRyYWNlLnRyYWNlKFRyYWNlLlNFVkVSRSwgIkVycm9yIHB1Ymxpc2hpbmcgY29uZmlndXJhdGlvbiB0byAiICsgdG9TdHJpbmcoKSwgZSk7CgkJCW11bHRpLmFkZChuZXcgU3RhdHVzKElTdGF0dXMuRVJST1IsIFNlcnZlclBsdWdpbi5QTFVHSU5fSUQsIDAsIFNlcnZlclBsdWdpbi5nZXRSZXNvdXJjZSgiJWVycm9yUHVibGlzaGluZyIpLCBlKSk7CgkJfQoJCQoJCS8vIHB1Ymxpc2ggbW9kdWxlcwoJCWlmICghbW9uaXRvci5pc0NhbmNlbGVkKCkpIHsKCQkJdHJ5IHsKCQkJCXB1Ymxpc2hNb2R1bGVzKGtpbmQsIHBhcmVudHMsIG1vZHVsZXMyLCBkZWx0YUtpbmQsIG11bHRpLCBtb25pdG9yKTsKCQkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJCW11bHRpLmFkZChuZXcgU3RhdHVzKElTdGF0dXMuRVJST1IsIFNlcnZlclBsdWdpbi5QTFVHSU5fSUQsIDAsIFNlcnZlclBsdWdpbi5nZXRSZXNvdXJjZSgiJWVycm9yUHVibGlzaGluZyIpLCBlKSk7CgkJCX0KCQl9CgkJCgkJLy8gZW5kIHRoZSBwdWJsaXNoaW5nCgkJVHJhY2UudHJhY2UoVHJhY2UuRklORVNULCAiQ2FsbGluZyBwdWJsaXNoRmluaXNoKCkiKTsKCQl0cnkgewoJCQlnZXRCZWhhdmlvdXJEZWxlZ2F0ZSgpLnB1Ymxpc2hGaW5pc2goUHJvZ3Jlc3NVdGlsLmdldFN1Yk1vbml0b3JGb3IobW9uaXRvciwgNTAwKSk7CgkJfSBjYXRjaCAoQ29yZUV4Y2VwdGlvbiBjZSkgewoJCQlUcmFjZS50cmFjZShUcmFjZS5JTkZPLCAiQ29yZUV4Y2VwdGlvbiBwdWJsaXNoaW5nIHRvICIgKyB0b1N0cmluZygpLCBjZSk7CgkJCW11bHRpLmFkZChjZS5nZXRTdGF0dXMoKSk7CgkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiRXJyb3Igc3RvcHBpbmcgcHVibGlzaCB0byAiICsgdG9TdHJpbmcoKSwgZSk7CgkJCW11bHRpLmFkZChuZXcgU3RhdHVzKElTdGF0dXMuRVJST1IsIFNlcnZlclBsdWdpbi5QTFVHSU5fSUQsIDAsIFNlcnZlclBsdWdpbi5nZXRSZXNvdXJjZSgiJWVycm9yUHVibGlzaGluZyIpLCBlKSk7CgkJfQoJCQoJCWlmIChtb25pdG9yLmlzQ2FuY2VsZWQoKSkgewoJCQlJU3RhdHVzIHN0YXR1cyA9IG5ldyBTdGF0dXMoSVN0YXR1cy5JTkZPLCBTZXJ2ZXJQbHVnaW4uUExVR0lOX0lELCAwLCBTZXJ2ZXJQbHVnaW4uZ2V0UmVzb3VyY2UoIiVwdWJsaXNoaW5nQ2FuY2VsbGVkIiksIG51bGwpOwoJCQltdWx0aS5hZGQoc3RhdHVzKTsKCQl9CgoJCU11bHRpU3RhdHVzIHBzID0gbmV3IE11bHRpU3RhdHVzKFNlcnZlclBsdWdpbi5QTFVHSU5fSUQsIDAsIFNlcnZlclBsdWdpbi5nZXRSZXNvdXJjZSgiJXB1Ymxpc2hpbmdTdG9wIiksIG51bGwpOwoJCXBzLmFkZChtdWx0aSk7CgkJZmlyZVB1Ymxpc2hGaW5pc2hlZChtdWx0aSk7CgkJCgkJc3BpLnNhdmUoKTsKCgkJbW9uaXRvci5kb25lKCk7CgoJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgIi0tPC0tIERvbmUgcHVibGlzaGluZyAtLTwtLSIpOwoJCQoJCWlmIChtdWx0aS5nZXRDaGlsZHJlbigpLmxlbmd0aCA9PSAxKQoJCQlyZXR1cm4gbXVsdGkuZ2V0Q2hpbGRyZW4oKVswXTsKCQkKCQlyZXR1cm4gbXVsdGk7Cgl9CgoJLyoqCgkgKiBQdWJsaXNoIGEgc2luZ2xlIG1vZHVsZS4KCSAqLwoJcHJvdGVjdGVkIElTdGF0dXMgcHVibGlzaE1vZHVsZShpbnQga2luZCwgSU1vZHVsZVtdIHBhcmVudHMsIElNb2R1bGUgbW9kdWxlLCBpbnQgZGVsdGFLaW5kLCBJUHJvZ3Jlc3NNb25pdG9yIG1vbml0b3IpIHsKCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICJQdWJsaXNoaW5nIG1vZHVsZTogIiArIG1vZHVsZSk7CgkJCgkJbW9uaXRvci5iZWdpblRhc2soU2VydmVyUGx1Z2luLmdldFJlc291cmNlKCIlcHVibGlzaGluZ01vZHVsZSIsIG1vZHVsZS5nZXROYW1lKCkpLCAxMDAwKTsKCQkKCQlmaXJlTW9kdWxlUHVibGlzaFN0YXJ0ZWQocGFyZW50cywgbW9kdWxlKTsKCQkKCQlJU3RhdHVzIHN0YXR1cyA9IG5ldyBTdGF0dXMoSVN0YXR1cy5PSywgU2VydmVyUGx1Z2luLlBMVUdJTl9JRCwgMCwgU2VydmVyUGx1Z2luLmdldFJlc291cmNlKCIlcHVibGlzaGVkTW9kdWxlIiwgbW9kdWxlLmdldE5hbWUoKSksIG51bGwpOwoJCXRyeSB7CgkJCWdldEJlaGF2aW91ckRlbGVnYXRlKCkucHVibGlzaE1vZHVsZShraW5kLCBkZWx0YUtpbmQsIHBhcmVudHMsIG1vZHVsZSwgbW9uaXRvcik7CgkJfSBjYXRjaCAoQ29yZUV4Y2VwdGlvbiBjZSkgewoJCQlzdGF0dXMgPSBjZS5nZXRTdGF0dXMoKTsKCQl9CgkJZmlyZU1vZHVsZVB1Ymxpc2hGaW5pc2hlZChwYXJlbnRzLCBtb2R1bGUsIHN0YXR1cyk7CgkJCgkJLypUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICJEZWx0YToiKTsKCQlJTW9kdWxlUmVzb3VyY2VEZWx0YVtdIGRlbHRhID0gZ2V0U2VydmVyUHVibGlzaEluZm8oKS5nZXREZWx0YShwYXJlbnRzLCBtb2R1bGUpOwoJCWludCBzaXplID0gZGVsdGEubGVuZ3RoOwoJCWZvciAoaW50IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKSB7CgkJCSgoTW9kdWxlUmVzb3VyY2VEZWx0YSlkZWx0YVtpXSkudHJhY2UoIj4gICIpOwoJCX0qLwoJCWlmIChkZWx0YUtpbmQgPT0gUkVNT1ZFRCkKCQkJZ2V0U2VydmVyUHVibGlzaEluZm8oKS5yZW1vdmVNb2R1bGVQdWJsaXNoSW5mbyhwYXJlbnRzLCBtb2R1bGUpOwoJCWVsc2UKCQkJZ2V0U2VydmVyUHVibGlzaEluZm8oKS5maWxsKHBhcmVudHMsIG1vZHVsZSk7CgkJCgkJbW9uaXRvci5kb25lKCk7CgkJCgkJVHJhY2UudHJhY2UoVHJhY2UuRklORVNULCAiRG9uZSBwdWJsaXNoaW5nOiAiICsgbW9kdWxlKTsKCQlyZXR1cm4gc3RhdHVzOwoJfQoKCS8qKgoJICogUHVibGlzaGVzIHRoZSBnaXZlbiBtb2R1bGVzLiBSZXR1cm5zIHRydWUgaWYgdGhlIHB1Ymxpc2hpbmcKCSAqIHNob3VsZCBjb250aW51ZSwgb3IgZmFsc2UgaWYgcHVibGlzaGluZyBoYXMgZmFpbGVkIG9yIGlzIGNhbmNlbGxlZC4KCSAqIAoJICogVXNlcyA1MDAgdGlja3MgcGx1cyAzNTAwIHRpY2tzIHBlciBtb2R1bGUKCSAqLwoJcHJvdGVjdGVkIHZvaWQgcHVibGlzaE1vZHVsZXMoaW50IGtpbmQsIExpc3QgcGFyZW50cywgSU1vZHVsZVtdIG1vZHVsZXMyLCBpbnRbXSBkZWx0YUtpbmQsIE11bHRpU3RhdHVzIG11bHRpLCBJUHJvZ3Jlc3NNb25pdG9yIG1vbml0b3IpIHsKCQlpZiAocGFyZW50cyA9PSBudWxsKQoJCQlyZXR1cm47CgoJCWludCBzaXplID0gcGFyZW50cy5zaXplKCk7CgkJaWYgKHNpemUgPT0gMCkKCQkJcmV0dXJuOwoJCQoJCWlmIChtb25pdG9yLmlzQ2FuY2VsZWQoKSkKCQkJcmV0dXJuOwoKCQkvLyBwdWJsaXNoIG1vZHVsZXMKCQlmb3IgKGludCBpID0gMDsgaSA8IHNpemU7IGkrKykgewoJCQlJU3RhdHVzIHN0YXR1cyA9IHB1Ymxpc2hNb2R1bGUoa2luZCwgKElNb2R1bGVbXSkgcGFyZW50cy5nZXQoaSksIG1vZHVsZXMyW2ldLCBkZWx0YUtpbmRbaV0sIFByb2dyZXNzVXRpbC5nZXRTdWJNb25pdG9yRm9yKG1vbml0b3IsIDMwMDApKTsKCQkJbXVsdGkuYWRkKHN0YXR1cyk7CgkJfQoJfQoKCS8qCgkgKiBSZXR1cm5zIHRoZSBtb2R1bGUgcmVzb3VyY2VzIHRoYXQgaGF2ZSBiZWVuIHB1Ymxpc2hlZC4KCSAqIAoJICogQHNlZSBTZXJ2ZXJCZWhhdmlvdXJEZWxlZ2F0ZS5nZXRQdWJsaXNoZWRSZXNvdXJjZXMoSU1vZHVsZVtdLCBJTW9kdWxlKQoJICovCglwdWJsaWMgSU1vZHVsZVJlc291cmNlW10gZ2V0UHVibGlzaGVkUmVzb3VyY2VzKElNb2R1bGVbXSBwYXJlbnRzLCBJTW9kdWxlIG1vZHVsZSkgewoJCXJldHVybiBnZXRTZXJ2ZXJQdWJsaXNoSW5mbygpLmdldE1vZHVsZVB1Ymxpc2hJbmZvKHBhcmVudHMsIG1vZHVsZSkuZ2V0UmVzb3VyY2VzKCk7Cgl9CgoJLyoKCSAqIFJldHVybnMgdGhlIGRlbHRhIG9mIHRoZSBjdXJyZW50IG1vZHVsZSByZXNvdXJjZXMgdGhhdCBoYXZlIGJlZW4KCSAqIHB1Ymxpc2hlZCBjb21wYXJlZCB0byB0aGUgY3VycmVudCBzdGF0ZSBvZiB0aGUgbW9kdWxlLgoJICogCgkgKiBAc2VlIFNlcnZlckJlaGF2aW91ckRlbGVnYXRlLmdldFB1Ymxpc2hlZFJlc291cmNlRGVsdGEoSU1vZHVsZVtdLCBJTW9kdWxlKQoJICovCglwdWJsaWMgSU1vZHVsZVJlc291cmNlRGVsdGFbXSBnZXRQdWJsaXNoZWRSZXNvdXJjZURlbHRhKElNb2R1bGVbXSBwYXJlbnRzLCBJTW9kdWxlIG1vZHVsZSkgewoJCXJldHVybiBnZXRTZXJ2ZXJQdWJsaXNoSW5mbygpLmdldERlbHRhKHBhcmVudHMsIG1vZHVsZSk7Cgl9CgoJcHJvdGVjdGVkIExpc3QgZ2V0VGFza3MoTGlzdFtdIHBhcmVudHMsIElNb2R1bGVbXSBtb2R1bGVzMikgewoJCUxpc3QgdGFza3MgPSBuZXcgQXJyYXlMaXN0KCk7CgkJCgkJU3RyaW5nIHNlcnZlclR5cGVJZCA9IGdldFNlcnZlclR5cGUoKS5nZXRJZCgpOwoJCQoJCUlTZXJ2ZXJUYXNrW10gc2VydmVyVGFza3MgPSBTZXJ2ZXJQbHVnaW4uZ2V0U2VydmVyVGFza3MoKTsKCQlpZiAoc2VydmVyVGFza3MgIT0gbnVsbCkgewoJCQlpbnQgc2l6ZSA9IHNlcnZlclRhc2tzLmxlbmd0aDsKCQkJZm9yIChpbnQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHsKCQkJCUlTZXJ2ZXJUYXNrIHRhc2sgPSBzZXJ2ZXJUYXNrc1tpXTsKCQkJCWlmICh0YXNrLnN1cHBvcnRzVHlwZShzZXJ2ZXJUeXBlSWQpKSB7CgkJCQkJSU9wdGlvbmFsVGFza1tdIHRhc2tzMiA9IHRhc2suZ2V0VGFza3ModGhpcywgcGFyZW50cywgbW9kdWxlczIpOwoJCQkJCWlmICh0YXNrczIgIT0gbnVsbCkgewoJCQkJCQlpbnQgc2l6ZTIgPSB0YXNrczIubGVuZ3RoOwoJCQkJCQlmb3IgKGludCBqID0gMDsgaiA8IHNpemUyOyBqKyspIHsKCQkJCQkJCWlmICh0YXNrczJbal0uZ2V0U3RhdHVzKCkgPT0gSU9wdGlvbmFsVGFzay5UQVNLX01BTkRBVE9SWSkKCQkJCQkJCQl0YXNrcy5hZGQodGFza3MyW2pdKTsKCQkJCQkJfQoJCQkJCX0KCQkJCX0KCQkJfQoJCX0KCgkJaW50IHNpemUgPSB0YXNrcy5zaXplKCk7CgkJZm9yIChpbnQgaSA9IDA7IGkgPCBzaXplIC0gMTsgaSsrKSB7CgkJCWZvciAoaW50IGogPSBpICsgMTsgaiA8IHNpemU7IGorKykgewoJCQkJSU9yZGVyZWQgYSA9IChJT3JkZXJlZCkgdGFza3MuZ2V0KGkpOwoJCQkJSU9yZGVyZWQgYiA9IChJT3JkZXJlZCkgdGFza3MuZ2V0KGopOwoJCQkJaWYgKGEuZ2V0T3JkZXIoKSA+IGIuZ2V0T3JkZXIoKSkgewoJCQkJCU9iamVjdCB0ZW1wID0gYTsKCQkJCQl0YXNrcy5zZXQoaSwgYik7CgkJCQkJdGFza3Muc2V0KGosIHRlbXApOwoJCQkJfQoJCQl9CgkJfQoJCQoJCXJldHVybiB0YXNrczsKCX0KCglwcm90ZWN0ZWQgSVN0YXR1cyBwZXJmb3JtVGFza3MoTGlzdCB0YXNrcywgSVByb2dyZXNzTW9uaXRvciBtb25pdG9yKSB7CgkJVHJhY2UudHJhY2UoVHJhY2UuRklORVNULCAiUGVyZm9ybWluZyB0YXNrczogIiArIHRhc2tzLnNpemUoKSk7CgkJCgkJaWYgKHRhc2tzLmlzRW1wdHkoKSkKCQkJcmV0dXJuIG51bGw7CgkJCgkJU3RhdHVzIG11bHRpID0gbmV3IE11bHRpU3RhdHVzKFNlcnZlclBsdWdpbi5QTFVHSU5fSUQsIDAsIFNlcnZlclBsdWdpbi5nZXRSZXNvdXJjZSgiJXRhc2tQZXJmb3JtaW5nIiksIG51bGwpOwoKCQlJdGVyYXRvciBpdGVyYXRvciA9IHRhc2tzLml0ZXJhdG9yKCk7CgkJd2hpbGUgKGl0ZXJhdG9yLmhhc05leHQoKSkgewoJCQlJT3B0aW9uYWxUYXNrIHRhc2sgPSAoSU9wdGlvbmFsVGFzaykgaXRlcmF0b3IubmV4dCgpOwoJCQltb25pdG9yLnN1YlRhc2soU2VydmVyUGx1Z2luLmdldFJlc291cmNlKCIldGFza1BlcmZvcm1pbmciLCB0YXNrLnRvU3RyaW5nKCkpKTsKCQkJdHJ5IHsKCQkJCXRhc2suZXhlY3V0ZShQcm9ncmVzc1V0aWwuZ2V0U3ViTW9uaXRvckZvcihtb25pdG9yLCA1MDApKTsKCQkJfSBjYXRjaCAoQ29yZUV4Y2VwdGlvbiBjZSkgewoJCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiVGFzayBmYWlsZWQiLCBjZSk7CgkJCX0KCQkJaWYgKG1vbml0b3IuaXNDYW5jZWxlZCgpKQoJCQkJcmV0dXJuIG11bHRpOwoJCX0KCQkKCQkvLyBzYXZlIHNlcnZlciBhbmQgY29uZmlndXJhdGlvbgoJCS8qdHJ5IHsKCQkJU2VydmVyVXRpbC5zYXZlKHNlcnZlciwgUHJvZ3Jlc3NVdGlsLmdldFN1Yk1vbml0b3JGb3IobW9uaXRvciwgMTAwMCkpOwoJCQlTZXJ2ZXJVdGlsLnNhdmUoY29uZmlndXJhdGlvbiwgUHJvZ3Jlc3NVdGlsLmdldFN1Yk1vbml0b3JGb3IobW9uaXRvciwgMTAwMCkpOwoJCX0gY2F0Y2ggKENvcmVFeGNlcHRpb24gc2UpIHsKCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiRXJyb3Igc2F2aW5nIHNlcnZlciBhbmQvb3IgY29uZmlndXJhdGlvbiIsIHNlKTsKCQkJbXVsdGkuYWRkQ2hpbGQoc2UuZ2V0U3RhdHVzKCkpOwoJCX0qLwoKCQlyZXR1cm4gbXVsdGk7Cgl9CgkKCS8qIChub24tSmF2YWRvYykKCSAqIEBzZWUgb3JnLmVjbGlwc2UuY29yZS5ydW50aW1lLklBZGFwdGFibGUjZ2V0QWRhcHRlcihqYXZhLmxhbmcuQ2xhc3MpCgkgKi8KCXB1YmxpYyBPYmplY3QgZ2V0QWRhcHRlcihDbGFzcyBhZGFwdGVyKSB7CgkJU2VydmVyRGVsZWdhdGUgZGVsZWdhdGUyID0gZ2V0RGVsZWdhdGUoKTsKCQlpZiAoYWRhcHRlci5pc0luc3RhbmNlKGRlbGVnYXRlMikpCgkJCXJldHVybiBkZWxlZ2F0ZTI7CgkJU2VydmVyQmVoYXZpb3VyRGVsZWdhdGUgZGVsZWdhdGUzID0gZ2V0QmVoYXZpb3VyRGVsZWdhdGUoKTsKCQlpZiAoYWRhcHRlci5pc0luc3RhbmNlKGRlbGVnYXRlMykpCgkJCXJldHVybiBkZWxlZ2F0ZTM7CgkJcmV0dXJuIFBsYXRmb3JtLmdldEFkYXB0ZXJNYW5hZ2VyKCkuZ2V0QWRhcHRlcih0aGlzLCBhZGFwdGVyKTsKCX0KCglwdWJsaWMgU3RyaW5nIHRvU3RyaW5nKCkgewoJCXJldHVybiBnZXROYW1lKCk7Cgl9CgoJLyoqCgkgKiBSZXR1cm5zIHRydWUgaWYgdGhlIHNlcnZlciBpcyBpbiBhIHN0YXRlIHRoYXQgaXQgY2FuCgkgKiBiZSBzdGFydGVkLCBhbmQgc3VwcG9ydHMgdGhlIGdpdmVuIG1vZGUuCgkgKgoJICogQHBhcmFtIG1vZGUyCgkgKiBAcmV0dXJuIHN0YXR1cwoJICovCglwdWJsaWMgSVN0YXR1cyBjYW5TdGFydChTdHJpbmcgbW9kZTIpIHsKCQlpbnQgc3RhdGUgPSBnZXRTZXJ2ZXJTdGF0ZSgpOwoJCWlmIChzdGF0ZSAhPSBTVEFURV9TVE9QUEVEICYmIHN0YXRlICE9IFNUQVRFX1VOS05PV04pCgkJCXJldHVybiBuZXcgU3RhdHVzKElTdGF0dXMuRVJST1IsIFNlcnZlclBsdWdpbi5QTFVHSU5fSUQsIDAsIFNlcnZlclBsdWdpbi5nZXRSZXNvdXJjZSgiJWNhblN0YXJ0RXJyb3JTdGF0ZSIpLCBudWxsKTsKCQkKCQlpZiAoZ2V0U2VydmVyVHlwZSgpID09IG51bGwgfHwgIWdldFNlcnZlclR5cGUoKS5zdXBwb3J0c0xhdW5jaE1vZGUobW9kZTIpKQoJCQlyZXR1cm4gbmV3IFN0YXR1cyhJU3RhdHVzLkVSUk9SLCBTZXJ2ZXJQbHVnaW4uUExVR0lOX0lELCAwLCBTZXJ2ZXJQbHVnaW4uZ2V0UmVzb3VyY2UoIiVlcnJvckxhdW5jaE1vZGUiKSwgbnVsbCk7CgoJCXJldHVybiBuZXcgU3RhdHVzKElTdGF0dXMuT0ssIFNlcnZlclBsdWdpbi5QTFVHSU5fSUQsIDAsIFNlcnZlclBsdWdpbi5nZXRSZXNvdXJjZSgiJWNhblN0YXJ0T2siKSwgbnVsbCk7Cgl9CgkKCXB1YmxpYyBJTGF1bmNoIGdldEV4aXN0aW5nTGF1bmNoKCkgewoJCUlMYXVuY2hNYW5hZ2VyIGxhdW5jaE1hbmFnZXIgPSBEZWJ1Z1BsdWdpbi5nZXREZWZhdWx0KCkuZ2V0TGF1bmNoTWFuYWdlcigpOwoJCQoJCUlMYXVuY2hbXSBsYXVuY2hlcyA9IGxhdW5jaE1hbmFnZXIuZ2V0TGF1bmNoZXMoKTsKCQlpbnQgc2l6ZSA9IGxhdW5jaGVzLmxlbmd0aDsKCQlmb3IgKGludCBpID0gMDsgaSA8IHNpemU7IGkrKykgewoJCQlJTGF1bmNoQ29uZmlndXJhdGlvbiBsYXVuY2hDb25maWcgPSBsYXVuY2hlc1tpXS5nZXRMYXVuY2hDb25maWd1cmF0aW9uKCk7CgkJCXRyeSB7CgkJCQlpZiAobGF1bmNoQ29uZmlnICE9IG51bGwpIHsKCQkJCQlTdHJpbmcgc2VydmVySWQgPSBsYXVuY2hDb25maWcuZ2V0QXR0cmlidXRlKFNFUlZFUl9JRCwgKFN0cmluZykgbnVsbCk7CgkJCQkJaWYgKGdldElkKCkuZXF1YWxzKHNlcnZlcklkKSkgewoJCQkJCQlpZiAoIWxhdW5jaGVzW2ldLmlzVGVybWluYXRlZCgpKQoJCQkJCQkJcmV0dXJuIGxhdW5jaGVzW2ldOwoJCQkJCX0KCQkJCX0KCQkJfSBjYXRjaCAoQ29yZUV4Y2VwdGlvbiBlKSB7CgkJCQkvLyBpZ25vcmUKCQkJfQoJCX0KCQkKCQlyZXR1cm4gbnVsbDsKCX0KCglwdWJsaWMgdm9pZCBzZXR1cExhdW5jaENvbmZpZ3VyYXRpb24oSUxhdW5jaENvbmZpZ3VyYXRpb25Xb3JraW5nQ29weSB3b3JraW5nQ29weSwgSVByb2dyZXNzTW9uaXRvciBtb25pdG9yKSB0aHJvd3MgQ29yZUV4Y2VwdGlvbiB7CgkJdHJ5IHsKCQkJZ2V0QmVoYXZpb3VyRGVsZWdhdGUoKS5zZXR1cExhdW5jaENvbmZpZ3VyYXRpb24od29ya2luZ0NvcHksIG1vbml0b3IpOwoJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCVRyYWNlLnRyYWNlKFRyYWNlLlNFVkVSRSwgIkVycm9yIGNhbGxpbmcgZGVsZWdhdGUgc2V0TGF1bmNoRGVmYXVsdHMoKSAiICsgdG9TdHJpbmcoKSwgZSk7CgkJfQoJfQoKCXB1YmxpYyB2b2lkIGltcG9ydENvbmZpZ3VyYXRpb24oSVJ1bnRpbWUgcnVudGltZTIsIElQcm9ncmVzc01vbml0b3IgbW9uaXRvcikgewoJCXRyeSB7CgkJCWdldERlbGVnYXRlKCkuaW1wb3J0Q29uZmlndXJhdGlvbihydW50aW1lMiwgbW9uaXRvcik7CgkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiRXJyb3IgY2FsbGluZyBkZWxlZ2F0ZSBzZXRMYXVuY2hEZWZhdWx0cygpICIgKyB0b1N0cmluZygpLCBlKTsKCQl9Cgl9CgoJcHVibGljIElMYXVuY2hDb25maWd1cmF0aW9uIGdldExhdW5jaENvbmZpZ3VyYXRpb24oYm9vbGVhbiBjcmVhdGUsIElQcm9ncmVzc01vbml0b3IgbW9uaXRvcikgdGhyb3dzIENvcmVFeGNlcHRpb24gewoJCUlMYXVuY2hDb25maWd1cmF0aW9uVHlwZSBsYXVuY2hDb25maWdUeXBlID0gKChTZXJ2ZXJUeXBlKSBnZXRTZXJ2ZXJUeXBlKCkpLmdldExhdW5jaENvbmZpZ3VyYXRpb25UeXBlKCk7CgkJCgkJSUxhdW5jaE1hbmFnZXIgbGF1bmNoTWFuYWdlciA9IERlYnVnUGx1Z2luLmdldERlZmF1bHQoKS5nZXRMYXVuY2hNYW5hZ2VyKCk7CgkJSUxhdW5jaENvbmZpZ3VyYXRpb25bXSBsYXVuY2hDb25maWdzID0gbnVsbDsKCQl0cnkgewoJCQlsYXVuY2hDb25maWdzID0gbGF1bmNoTWFuYWdlci5nZXRMYXVuY2hDb25maWd1cmF0aW9ucyhsYXVuY2hDb25maWdUeXBlKTsKCQl9IGNhdGNoIChDb3JlRXhjZXB0aW9uIGUpIHsKCQkJLy8gaWdub3JlCgkJfQoJCQoJCWlmIChsYXVuY2hDb25maWdzICE9IG51bGwpIHsKCQkJaW50IHNpemUgPSBsYXVuY2hDb25maWdzLmxlbmd0aDsKCQkJZm9yIChpbnQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHsKCQkJCXRyeSB7CgkJCQkJU3RyaW5nIHNlcnZlcklkID0gbGF1bmNoQ29uZmlnc1tpXS5nZXRBdHRyaWJ1dGUoU0VSVkVSX0lELCAoU3RyaW5nKSBudWxsKTsKCQkJCQlpZiAoZ2V0SWQoKS5lcXVhbHMoc2VydmVySWQpKSB7CgkJCQkJCUlMYXVuY2hDb25maWd1cmF0aW9uV29ya2luZ0NvcHkgd2MgPSBsYXVuY2hDb25maWdzW2ldLmdldFdvcmtpbmdDb3B5KCk7CgkJCQkJCXNldHVwTGF1bmNoQ29uZmlndXJhdGlvbih3YywgbW9uaXRvcik7CgkJCQkJCWlmICh3Yy5pc0RpcnR5KCkpCgkJCQkJCQlyZXR1cm4gd2MuZG9TYXZlKCk7CgkJCQkJCXJldHVybiBsYXVuY2hDb25maWdzW2ldOwoJCQkJCX0KCQkJCX0gY2F0Y2ggKENvcmVFeGNlcHRpb24gZSkgewoJCQkJCS8vIGlnbm9yZQoJCQkJfQoJCQl9CgkJfQoJCQoJCWlmICghY3JlYXRlKQoJCQlyZXR1cm4gbnVsbDsKCQkKCQkvLyBjcmVhdGUgYSBuZXcgbGF1bmNoIGNvbmZpZ3VyYXRpb24KCQlTdHJpbmcgbGF1bmNoTmFtZSA9IGdldFZhbGlkTGF1bmNoQ29uZmlndXJhdGlvbk5hbWUoZ2V0TmFtZSgpKTsKCQlsYXVuY2hOYW1lID0gbGF1bmNoTWFuYWdlci5nZW5lcmF0ZVVuaXF1ZUxhdW5jaENvbmZpZ3VyYXRpb25OYW1lRnJvbShsYXVuY2hOYW1lKTsgCgkJSUxhdW5jaENvbmZpZ3VyYXRpb25Xb3JraW5nQ29weSB3YyA9IGxhdW5jaENvbmZpZ1R5cGUubmV3SW5zdGFuY2UobnVsbCwgbGF1bmNoTmFtZSk7CgkJd2Muc2V0QXR0cmlidXRlKFNFUlZFUl9JRCwgZ2V0SWQoKSk7CgkJc2V0dXBMYXVuY2hDb25maWd1cmF0aW9uKHdjLCBtb25pdG9yKTsKCQlyZXR1cm4gd2MuZG9TYXZlKCk7Cgl9CgoJcHJvdGVjdGVkIFN0cmluZyBnZXRWYWxpZExhdW5jaENvbmZpZ3VyYXRpb25OYW1lKFN0cmluZyBzKSB7CgkJaWYgKHMgPT0gbnVsbCB8fCBzLmxlbmd0aCgpID09IDApCgkJCXJldHVybiAiMSI7CgkJaW50IHNpemUgPSBJTlZBTElEX0NIQVJTLmxlbmd0aDsKCQlmb3IgKGludCBpID0gMDsgaSA8IHNpemU7IGkrKykgewoJCQlzID0gcy5yZXBsYWNlKElOVkFMSURfQ0hBUlNbaV0sICdfJyk7CgkJfQoJCXJldHVybiBzOwoJfQoKCS8qKgoJICogU3RhcnQgdGhlIHNlcnZlciBpbiB0aGUgZ2l2ZW4gbW9kZS4KCSAqCgkgKiBAcGFyYW0gbW9kZTIgCgkgKiBAcGFyYW0gbW9uaXRvciBhIHByb2dyZXNzIG1vbml0b3IKCSAqIEByZXR1cm4gYSBsYXVuY2gKCSAqLwoJcHVibGljIElMYXVuY2ggc3RhcnQoU3RyaW5nIG1vZGUyLCBJUHJvZ3Jlc3NNb25pdG9yIG1vbml0b3IpIHRocm93cyBDb3JlRXhjZXB0aW9uIHsKCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICJTdGFydGluZyBzZXJ2ZXI6ICIgKyB0b1N0cmluZygpICsgIiwgbGF1bmNoTW9kZTogIiArIG1vZGUyKTsKCQoJCXRyeSB7CgkJCUlMYXVuY2hDb25maWd1cmF0aW9uIGxhdW5jaENvbmZpZyA9IGdldExhdW5jaENvbmZpZ3VyYXRpb24odHJ1ZSwgbW9uaXRvcik7CgkJCUlMYXVuY2ggbGF1bmNoID0gbGF1bmNoQ29uZmlnLmxhdW5jaChtb2RlMiwgbW9uaXRvcik7CgkJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgIkxhdW5jaDogIiArIGxhdW5jaCk7CgkJCXJldHVybiBsYXVuY2g7CgkJfSBjYXRjaCAoQ29yZUV4Y2VwdGlvbiBlKSB7CgkJCVRyYWNlLnRyYWNlKFRyYWNlLlNFVkVSRSwgIkVycm9yIHN0YXJ0aW5nIHNlcnZlciAiICsgdG9TdHJpbmcoKSwgZSk7CgkJCXRocm93IGU7CgkJfQoJfQoKCS8qKgoJICogQ2xlYW4gdXAgYW55IG9sZCBsYXVuY2ggY29uZmlndXJhdGlvbnMgd2l0aCB0aGUgY3VycmVudCBzZXJ2ZXIncyBpZC4KCSAqLwoJcHJvdGVjdGVkIHZvaWQgZGVsZXRlTGF1bmNoQ29uZmlndXJhdGlvbnMoKSB7CgkJaWYgKGdldFNlcnZlclR5cGUoKSA9PSBudWxsKQoJCQlyZXR1cm47CgkJSUxhdW5jaE1hbmFnZXIgbGF1bmNoTWFuYWdlciA9IERlYnVnUGx1Z2luLmdldERlZmF1bHQoKS5nZXRMYXVuY2hNYW5hZ2VyKCk7CgkJSUxhdW5jaENvbmZpZ3VyYXRpb25UeXBlIGxhdW5jaENvbmZpZ1R5cGUgPSAoKFNlcnZlclR5cGUpIGdldFNlcnZlclR5cGUoKSkuZ2V0TGF1bmNoQ29uZmlndXJhdGlvblR5cGUoKTsKCQkKCQlJTGF1bmNoQ29uZmlndXJhdGlvbltdIGNvbmZpZ3MgPSBudWxsOwoJCXRyeSB7CgkJCWNvbmZpZ3MgPSBsYXVuY2hNYW5hZ2VyLmdldExhdW5jaENvbmZpZ3VyYXRpb25zKGxhdW5jaENvbmZpZ1R5cGUpOwoJCQlpbnQgc2l6ZSA9IGNvbmZpZ3MubGVuZ3RoOwoJCQlmb3IgKGludCBpID0gMDsgaSA8IHNpemU7IGkrKykgewoJCQkJdHJ5IHsKCQkJCQlpZiAoZ2V0SWQoKS5lcXVhbHMoY29uZmlnc1tpXS5nZXRBdHRyaWJ1dGUoU0VSVkVSX0lELCAoU3RyaW5nKSBudWxsKSkpCgkJCQkJCWNvbmZpZ3NbaV0uZGVsZXRlKCk7CgkJCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkJCS8vIGlnbm9yZQoJCQkJfQoJCQl9CgkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJLy8gaWdub3JlCgkJfQoJfQoKCS8qKgoJICogUmV0dXJucyB0cnVlIGlmIHRoZSBzZXJ2ZXIgaXMgaW4gYSBzdGF0ZSB0aGF0IGl0IGNhbgoJICogYmUgcmVzdGFydGVkLgoJICoKCSAqIEByZXR1cm4gYm9vbGVhbgoJICogVE9ETzogZml4IHJldHVybiBzdHJpbmdzCgkgKi8KCXB1YmxpYyBJU3RhdHVzIGNhblJlc3RhcnQoU3RyaW5nIG1vZGUyKSB7CgkJaWYgKCFnZXRTZXJ2ZXJUeXBlKCkuc3VwcG9ydHNMYXVuY2hNb2RlKG1vZGUyKSkKCQkJcmV0dXJuIG5ldyBTdGF0dXMoSVN0YXR1cy5FUlJPUiwgU2VydmVyUGx1Z2luLlBMVUdJTl9JRCwgMCwgU2VydmVyUGx1Z2luLmdldFJlc291cmNlKCIlZXJyb3JMYXVuY2hNb2RlIiksIG51bGwpOwoKCQlpbnQgc3RhdGUgPSBnZXRTZXJ2ZXJTdGF0ZSgpOwoJCWlmIChzdGF0ZSA9PSBTVEFURV9TVEFSVEVEKQoJCQlyZXR1cm4gbmV3IFN0YXR1cyhJU3RhdHVzLk9LLCBTZXJ2ZXJQbHVnaW4uUExVR0lOX0lELCAwLCBTZXJ2ZXJQbHVnaW4uZ2V0UmVzb3VyY2UoIiVlcnJvckxhdW5jaE1vZGUiKSwgbnVsbCk7CgkJCgkJcmV0dXJuIG5ldyBTdGF0dXMoSVN0YXR1cy5FUlJPUiwgU2VydmVyUGx1Z2luLlBMVUdJTl9JRCwgMCwgU2VydmVyUGx1Z2luLmdldFJlc291cmNlKCIlZXJyb3JMYXVuY2hNb2RlIiksIG51bGwpOwoJfQoKCS8qKgoJICogUmV0dXJucyB0aGUgY3VycmVudCByZXN0YXJ0IHN0YXRlIG9mIHRoZSBzZXJ2ZXIuIFRoaXMKCSAqIGltcGxlbWVudGF0aW9uIHdpbGwgYWx3YXlzIHJldHVybiBmYWxzZSB3aGVuIHRoZSBzZXJ2ZXIKCSAqIGlzIHN0b3BwZWQuCgkgKgoJICogQHJldHVybiBib29sZWFuCgkgKi8KCXB1YmxpYyBib29sZWFuIGdldFNlcnZlclJlc3RhcnRTdGF0ZSgpIHsKCQlpZiAoZ2V0U2VydmVyU3RhdGUoKSA9PSBTVEFURV9TVE9QUEVEKQoJCQlyZXR1cm4gZmFsc2U7CgkJcmV0dXJuIHNlcnZlclJlc3RhcnROZWVkZWQ7Cgl9CgoJLyoqCgkgKiBTZXRzIHRoZSBzZXJ2ZXIgcmVzdGFydCBzdGF0ZS4KCSAqCgkgKiBAcGFyYW0gc3RhdGUgYm9vbGVhbgoJICovCglwdWJsaWMgc3luY2hyb25pemVkIHZvaWQgc2V0U2VydmVyUmVzdGFydFN0YXRlKGJvb2xlYW4gc3RhdGUpIHsKCQlpZiAoc3RhdGUgPT0gc2VydmVyUmVzdGFydE5lZWRlZCkKCQkJcmV0dXJuOwoJCXNlcnZlclJlc3RhcnROZWVkZWQgPSBzdGF0ZTsKCQlmaXJlUmVzdGFydFN0YXRlQ2hhbmdlRXZlbnQoKTsKCX0KCgkvKioKCSAqIFJlc3RhcnQgdGhlIHNlcnZlciB3aXRoIHRoZSBnaXZlbiBkZWJ1ZyBtb2RlLgoJICogQSBzZXJ2ZXIgbWF5IG9ubHkgYmUgcmVzdGFydGVkIHdoZW4gaXQgaXMgY3VycmVudGx5IHJ1bm5pbmcuCgkgKiBUaGlzIG1ldGhvZCBpcyBhc3luY2hyb25vdXMuCgkgKi8KCXB1YmxpYyB2b2lkIHJlc3RhcnQoZmluYWwgU3RyaW5nIG1vZGUyKSB7CgkJaWYgKGdldFNlcnZlclN0YXRlKCkgPT0gU1RBVEVfU1RPUFBFRCkKCQkJcmV0dXJuOwoJCgkJVHJhY2UudHJhY2UoVHJhY2UuRklORVNULCAiUmVzdGFydGluZyBzZXJ2ZXI6ICIgKyBnZXROYW1lKCkpOwoJCgkJdHJ5IHsKCQkJdHJ5IHsKCQkJCWdldEJlaGF2aW91ckRlbGVnYXRlKCkucmVzdGFydChtb2RlMik7CgkJCQlyZXR1cm47CgkJCX0gY2F0Y2ggKENvcmVFeGNlcHRpb24gY2UpIHsKCQkJCVRyYWNlLnRyYWNlKFRyYWNlLlNFVkVSRSwgIkVycm9yIGNhbGxpbmcgZGVsZWdhdGUgcmVzdGFydCgpICIgKyB0b1N0cmluZygpKTsKCQkJfQoJCQoJCQkvLyBhZGQgbGlzdGVuZXIgdG8gc3RhcnQgaXQgYXMgc29vbiBhcyBpdCBpcyBzdG9wcGVkCgkJCWFkZFNlcnZlckxpc3RlbmVyKG5ldyBTZXJ2ZXJBZGFwdGVyKCkgewoJCQkJcHVibGljIHZvaWQgc2VydmVyU3RhdGVDaGFuZ2UoSVNlcnZlciBzZXJ2ZXIpIHsKCQkJCQlpZiAoc2VydmVyLmdldFNlcnZlclN0YXRlKCkgPT0gU1RBVEVfU1RPUFBFRCkgewoJCQkJCQlzZXJ2ZXIucmVtb3ZlU2VydmVyTGlzdGVuZXIodGhpcyk7CgoJCQkJCQkvLyByZXN0YXJ0IGluIGEgcXVhcnRlciBzZWNvbmQgKGdpdmUgb3RoZXIgbGlzdGVuZXJzIGEgY2hhbmNlCgkJCQkJCS8vIHRvIGhlYXIgdGhlIHN0b3BwZWQgbWVzc2FnZSkKCQkJCQkJVGhyZWFkIHQgPSBuZXcgVGhyZWFkKCkgewoJCQkJCQkJcHVibGljIHZvaWQgcnVuKCkgewoJCQkJCQkJCXRyeSB7CgkJCQkJCQkJCVRocmVhZC5zbGVlcCgyNTApOwoJCQkJCQkJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCQkJCQkJCS8vIGlnbm9yZQoJCQkJCQkJCX0KCQkJCQkJCQl0cnkgewoJCQkJCQkJCQlTZXJ2ZXIudGhpcy5zdGFydChtb2RlMiwgbmV3IE51bGxQcm9ncmVzc01vbml0b3IoKSk7CgkJCQkJCQkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJCQkJCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiRXJyb3Igd2hpbGUgcmVzdGFydGluZyBzZXJ2ZXIiLCBlKTsKCQkJCQkJCQl9CgkJCQkJCQl9CgkJCQkJCX07CgkJCQkJCXQuc2V0RGFlbW9uKHRydWUpOwoJCQkJCQl0LnNldFByaW9yaXR5KFRocmVhZC5OT1JNX1BSSU9SSVRZIC0gMik7CgkJCQkJCXQuc3RhcnQoKTsKCQkJCQl9CgkJCQl9CgkJCX0pOwoJCgkJCS8vIHN0b3AgdGhlIHNlcnZlcgoJCQlzdG9wKGZhbHNlKTsKCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQlUcmFjZS50cmFjZShUcmFjZS5TRVZFUkUsICJFcnJvciByZXN0YXJ0aW5nIHNlcnZlciIsIGUpOwoJCX0KCX0KCgoJLyoqCgkgKiBSZXR1cm5zIHRydWUgaWYgdGhlIHNlcnZlciBpcyBpbiBhIHN0YXRlIHRoYXQgaXQgY2FuCgkgKiBiZSBzdG9wcGVkLgoJICoKCSAqIEByZXR1cm4gYm9vbGVhbgoJICogVE9ETzogZml4IHJldHVybiBzdHJpbmdzCgkgKi8KCXB1YmxpYyBJU3RhdHVzIGNhblN0b3AoKSB7CgkJaWYgKGdldFNlcnZlclN0YXRlKCkgPT0gU1RBVEVfU1RPUFBFRCkKCQkJcmV0dXJuIG5ldyBTdGF0dXMoSVN0YXR1cy5FUlJPUiwgU2VydmVyUGx1Z2luLlBMVUdJTl9JRCwgMCwgU2VydmVyUGx1Z2luLmdldFJlc291cmNlKCIlZXJyb3JMYXVuY2hNb2RlIiksIG51bGwpOwoKCQlyZXR1cm4gbmV3IFN0YXR1cyhJU3RhdHVzLk9LLCBTZXJ2ZXJQbHVnaW4uUExVR0lOX0lELCAwLCBTZXJ2ZXJQbHVnaW4uZ2V0UmVzb3VyY2UoIiVlcnJvckxhdW5jaE1vZGUiKSwgbnVsbCk7Cgl9CgoJLyoqCgkgKiBTdG9wIHRoZSBzZXJ2ZXIgaWYgaXQgaXMgcnVubmluZy4KCSAqLwoJcHVibGljIHZvaWQgc3RvcChib29sZWFuIGZvcmNlKSB7CgkJaWYgKGdldFNlcnZlclN0YXRlKCkgPT0gU1RBVEVfU1RPUFBFRCkKCQkJcmV0dXJuOwoKCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICJTdG9wcGluZyBzZXJ2ZXI6ICIgKyB0b1N0cmluZygpKTsKCgkJdHJ5IHsKCQkJZ2V0QmVoYXZpb3VyRGVsZWdhdGUoKS5zdG9wKGZvcmNlKTsKCQl9IGNhdGNoIChUaHJvd2FibGUgdCkgewoJCQlUcmFjZS50cmFjZShUcmFjZS5TRVZFUkUsICJFcnJvciBjYWxsaW5nIGRlbGVnYXRlIHN0b3AoKSAiICsgdG9TdHJpbmcoKSwgdCk7CgkJfQoJfQoJCgkvKioKCSAqIFN0YXJ0IHRoZSBzZXJ2ZXIgaW4gdGhlIGdpdmVuIHN0YXJ0IG1vZGUgYW5kIHdhaXRzIHVudGlsIHRoZSBzZXJ2ZXIKCSAqIGhhcyBmaW5pc2hlZCBzdGFydGVkLgoJICoKCSAqIEBwYXJhbSBtb2RlMiB0aGUgbGF1bmNoIG1vZGUKCSAqIEBwYXJhbSBtb25pdG9yIGEgcHJvZ3Jlc3MgbW9uaXRvcgoJICogQGV4Y2VwdGlvbiBvcmcuZWNsaXBzZS5jb3JlLnJ1bnRpbWUuQ29yZUV4Y2VwdGlvbiAtIHRocm93biBpZiBhbiBlcnJvciBvY2N1cnMgd2hpbGUgdHJ5aW5nIHRvIHN0YXJ0IHRoZSBzZXJ2ZXIKCSAqLwoJcHVibGljIElMYXVuY2ggc3luY2hyb25vdXNTdGFydChTdHJpbmcgbW9kZTIsIElQcm9ncmVzc01vbml0b3IgbW9uaXRvcikgdGhyb3dzIENvcmVFeGNlcHRpb24gewoJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgInN5bmNocm9ub3VzU3RhcnQgMSIpOwoJCWZpbmFsIE9iamVjdCBtdXRleCA9IG5ldyBPYmplY3QoKTsKCQoJCS8vIGFkZCBsaXN0ZW5lciB0byB0aGUgc2VydmVyCgkJSVNlcnZlckxpc3RlbmVyIGxpc3RlbmVyID0gbmV3IFNlcnZlckFkYXB0ZXIoKSB7CgkJCXB1YmxpYyB2b2lkIHNlcnZlclN0YXRlQ2hhbmdlKElTZXJ2ZXIgc2VydmVyKSB7CgkJCQlpbnQgc3RhdGUgPSBzZXJ2ZXIuZ2V0U2VydmVyU3RhdGUoKTsKCQkJCWlmIChzdGF0ZSA9PSBJU2VydmVyLlNUQVRFX1NUQVJURUQgfHwgc3RhdGUgPT0gSVNlcnZlci5TVEFURV9TVE9QUEVEKSB7CgkJCQkJLy8gbm90aWZ5IHdhaXRlcgoJCQkJCXN5bmNocm9uaXplZCAobXV0ZXgpIHsKCQkJCQkJdHJ5IHsKCQkJCQkJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgInN5bmNocm9ub3VzU3RhcnQgbm90aWZ5Iik7CgkJCQkJCQltdXRleC5ub3RpZnlBbGwoKTsKCQkJCQkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJCQkJCVRyYWNlLnRyYWNlKFRyYWNlLlNFVkVSRSwgIkVycm9yIG5vdGlmeWluZyBzZXJ2ZXIgc3RhcnQiLCBlKTsKCQkJCQkJfQoJCQkJCX0KCQkJCX0KCQkJfQoJCX07CgkJYWRkU2VydmVyTGlzdGVuZXIobGlzdGVuZXIpOwoJCQoJCWZpbmFsIGludCBzZXJ2ZXJUaW1lb3V0ID0gKChTZXJ2ZXJUeXBlKSBnZXRTZXJ2ZXJUeXBlKCkpLmdldFN0YXJ0VGltZW91dCgpOwoJCWNsYXNzIFRpbWVyIHsKCQkJYm9vbGVhbiB0aW1lb3V0OwoJCQlib29sZWFuIGFscmVhZHlEb25lOwoJCX0KCQlmaW5hbCBUaW1lciB0aW1lciA9IG5ldyBUaW1lcigpOwoJCQoJCVRocmVhZCB0aHJlYWQgPSBuZXcgVGhyZWFkKCkgewoJCQlwdWJsaWMgdm9pZCBydW4oKSB7CgkJCQl0cnkgewoJCQkJCVRocmVhZC5zbGVlcChzZXJ2ZXJUaW1lb3V0ICogMTAwMCk7CgkJCQkJaWYgKCF0aW1lci5hbHJlYWR5RG9uZSkgewoJCQkJCQl0aW1lci50aW1lb3V0ID0gdHJ1ZTsKCQkJCQkJLy8gbm90aWZ5IHdhaXRlcgoJCQkJCQlzeW5jaHJvbml6ZWQgKG11dGV4KSB7CgkJCQkJCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICJzeW5jaHJvbm91c1N0YXJ0IG5vdGlmeSB0aW1lb3V0Iik7CgkJCQkJCQltdXRleC5ub3RpZnlBbGwoKTsKCQkJCQkJfQoJCQkJCX0KCQkJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiRXJyb3Igbm90aWZ5aW5nIHNlcnZlciBzdGFydCB0aW1lb3V0IiwgZSk7CgkJCQl9CgkJCX0KCQl9OwoJCXRocmVhZC5zZXREYWVtb24odHJ1ZSk7CgkJdGhyZWFkLnN0YXJ0KCk7CgkKCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICJzeW5jaHJvbm91c1N0YXJ0IDIiKTsKCQoJCS8vIHN0YXJ0IHRoZSBzZXJ2ZXIKCQlJTGF1bmNoIGxhdW5jaDsKCQl0cnkgewoJCQlsYXVuY2ggPSBzdGFydChtb2RlMiwgbW9uaXRvcik7CgkJfSBjYXRjaCAoQ29yZUV4Y2VwdGlvbiBlKSB7CgkJCXJlbW92ZVNlcnZlckxpc3RlbmVyKGxpc3RlbmVyKTsKCQkJdGltZXIuYWxyZWFkeURvbmUgPSB0cnVlOwoJCQl0aHJvdyBlOwoJCX0KCQoJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgInN5bmNocm9ub3VzU3RhcnQgMyIpOwoJCgkJLy8gd2FpdCBmb3IgaXQhIHdhaXQgZm9yIGl0ISAuLi4KCQlzeW5jaHJvbml6ZWQgKG11dGV4KSB7CgkJCXRyeSB7CgkJCQl3aGlsZSAoIXRpbWVyLnRpbWVvdXQgJiYgIShnZXRTZXJ2ZXJTdGF0ZSgpID09IElTZXJ2ZXIuU1RBVEVfU1RBUlRFRCB8fCBnZXRTZXJ2ZXJTdGF0ZSgpID09IElTZXJ2ZXIuU1RBVEVfU1RPUFBFRCkpCgkJCQkJbXV0ZXgud2FpdCgpOwoJCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiRXJyb3Igd2FpdGluZyBmb3Igc2VydmVyIHN0YXJ0IiwgZSk7CgkJCX0KCQl9CgkJcmVtb3ZlU2VydmVyTGlzdGVuZXIobGlzdGVuZXIpOwoJCXRpbWVyLmFscmVhZHlEb25lID0gdHJ1ZTsKCQkKCQlpZiAodGltZXIudGltZW91dCkKCQkJdGhyb3cgbmV3IENvcmVFeGNlcHRpb24obmV3IFN0YXR1cyhJU3RhdHVzLkVSUk9SLCBTZXJ2ZXJQbHVnaW4uUExVR0lOX0lELCAwLCBTZXJ2ZXJQbHVnaW4uZ2V0UmVzb3VyY2UoIiVlcnJvclN0YXJ0VGltZW91dCIsIG5ldyBTdHJpbmdbXSB7IGdldE5hbWUoKSwgc2VydmVyVGltZW91dCArICIiIH0pLCBudWxsKSk7CgkJdGltZXIuYWxyZWFkeURvbmUgPSB0cnVlOwoJCQoJCWlmIChnZXRTZXJ2ZXJTdGF0ZSgpID09IElTZXJ2ZXIuU1RBVEVfU1RPUFBFRCkKCQkJdGhyb3cgbmV3IENvcmVFeGNlcHRpb24obmV3IFN0YXR1cyhJU3RhdHVzLkVSUk9SLCBTZXJ2ZXJQbHVnaW4uUExVR0lOX0lELCAwLCBTZXJ2ZXJQbHVnaW4uZ2V0UmVzb3VyY2UoIiVlcnJvclN0YXJ0RmFpbGVkIiwgZ2V0TmFtZSgpKSwgbnVsbCkpOwoJCgkJVHJhY2UudHJhY2UoVHJhY2UuRklORVNULCAic3luY2hyb25vdXNTdGFydCA0Iik7CgkJCgkJcmV0dXJuIGxhdW5jaDsKCX0KCgkvKgoJICogQHNlZSBJU2VydmVyI3N5bmNocm9ub3VzUmVzdGFydChTdHJpbmcsIElQcm9ncmVzc01vbml0b3IpCgkgKi8KCXB1YmxpYyB2b2lkIHN5bmNocm9ub3VzUmVzdGFydChTdHJpbmcgbW9kZTIsIElQcm9ncmVzc01vbml0b3IgbW9uaXRvcikgdGhyb3dzIENvcmVFeGNlcHRpb24gewoJCXN5bmNocm9ub3VzU3RvcCh0cnVlKTsKCQlzeW5jaHJvbm91c1N0YXJ0KG1vZGUyLCBtb25pdG9yKTsKCX0KCgkvKgoJICogQHNlZSBJU2VydmVyI3N5bmNocm9ub3VzU3RvcCgpCgkgKi8KCXB1YmxpYyB2b2lkIHN5bmNocm9ub3VzU3RvcChib29sZWFuIGZvcmNlKSB7CgkJaWYgKGdldFNlcnZlclN0YXRlKCkgPT0gSVNlcnZlci5TVEFURV9TVE9QUEVEKQoJCQlyZXR1cm47CgkJCgkJZmluYWwgT2JqZWN0IG11dGV4ID0gbmV3IE9iamVjdCgpOwoJCgkJLy8gYWRkIGxpc3RlbmVyIHRvIHRoZSBzZXJ2ZXIKCQlJU2VydmVyTGlzdGVuZXIgbGlzdGVuZXIgPSBuZXcgU2VydmVyQWRhcHRlcigpIHsKCQkJcHVibGljIHZvaWQgc2VydmVyU3RhdGVDaGFuZ2UoSVNlcnZlciBzZXJ2ZXIpIHsKCQkJCWludCBzdGF0ZSA9IHNlcnZlci5nZXRTZXJ2ZXJTdGF0ZSgpOwoJCQkJaWYgKFNlcnZlci50aGlzID09IHNlcnZlciAmJiBzdGF0ZSA9PSBJU2VydmVyLlNUQVRFX1NUT1BQRUQpIHsKCQkJCQkvLyBub3RpZnkgd2FpdGVyCgkJCQkJc3luY2hyb25pemVkIChtdXRleCkgewoJCQkJCQl0cnkgewoJCQkJCQkJbXV0ZXgubm90aWZ5QWxsKCk7CgkJCQkJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCQkJCQlUcmFjZS50cmFjZShUcmFjZS5TRVZFUkUsICJFcnJvciBub3RpZnlpbmcgc2VydmVyIHN0b3AiLCBlKTsKCQkJCQkJfQoJCQkJCX0KCQkJCX0KCQkJfQoJCX07CgkJYWRkU2VydmVyTGlzdGVuZXIobGlzdGVuZXIpOwoJCQoJCWNsYXNzIFRpbWVyIHsKCQkJYm9vbGVhbiB0aW1lb3V0OwoJCQlib29sZWFuIGFscmVhZHlEb25lOwoJCX0KCQlmaW5hbCBUaW1lciB0aW1lciA9IG5ldyBUaW1lcigpOwoJCQoJCVRocmVhZCB0aHJlYWQgPSBuZXcgVGhyZWFkKCkgewoJCQlwdWJsaWMgdm9pZCBydW4oKSB7CgkJCQl0cnkgewoJCQkJCVRocmVhZC5zbGVlcCgxMjAwMDApOwoJCQkJCWlmICghdGltZXIuYWxyZWFkeURvbmUpIHsKCQkJCQkJdGltZXIudGltZW91dCA9IHRydWU7CgkJCQkJCS8vIG5vdGlmeSB3YWl0ZXIKCQkJCQkJc3luY2hyb25pemVkIChtdXRleCkgewoJCQkJCQkJVHJhY2UudHJhY2UoVHJhY2UuRklORVNULCAic3RvcCBub3RpZnkgdGltZW91dCIpOwoJCQkJCQkJbXV0ZXgubm90aWZ5QWxsKCk7CgkJCQkJCX0KCQkJCQl9CgkJCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkJCVRyYWNlLnRyYWNlKFRyYWNlLlNFVkVSRSwgIkVycm9yIG5vdGlmeWluZyBzZXJ2ZXIgc3RvcCB0aW1lb3V0IiwgZSk7CgkJCQl9CgkJCX0KCQl9OwoJCXRocmVhZC5zZXREYWVtb24odHJ1ZSk7CgkJdGhyZWFkLnN0YXJ0KCk7CgkKCQkvLyBzdG9wIHRoZSBzZXJ2ZXIKCQlzdG9wKGZvcmNlKTsKCQoJCS8vIHdhaXQgZm9yIGl0ISB3YWl0IGZvciBpdCEKCQlzeW5jaHJvbml6ZWQgKG11dGV4KSB7CgkJCXRyeSB7CgkJCQl3aGlsZSAoIXRpbWVyLnRpbWVvdXQgJiYgZ2V0U2VydmVyU3RhdGUoKSAhPSBJU2VydmVyLlNUQVRFX1NUT1BQRUQpCgkJCQkJbXV0ZXgud2FpdCgpOwoJCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiRXJyb3Igd2FpdGluZyBmb3Igc2VydmVyIHN0b3AiLCBlKTsKCQkJfQoJCX0KCQlyZW1vdmVTZXJ2ZXJMaXN0ZW5lcihsaXN0ZW5lcik7CgkJCgkJLyoKCQkvL2Nhbid0IHRocm93IGV4Y2VwdGlvbnMKCQlpZiAodGltZXIudGltZW91dCkKCQkJdGhyb3cgbmV3IENvcmVFeGNlcHRpb24obmV3IFN0YXR1cyhJU3RhdHVzLkVSUk9SLCBTZXJ2ZXJDb3JlLlBMVUdJTl9JRCwgMCwgU2VydmVyUGx1Z2luLmdldFJlc291cmNlKCIlZXJyb3JTdGFydEZhaWxlZCIsIGdldE5hbWUoKSksIG51bGwpKTsKCQllbHNlCgkJCXRpbWVyLmFscmVhZHlEb25lID0gdHJ1ZTsKCQkKCQlpZiAoZ2V0U2VydmVyU3RhdGUoKSA9PSBJU2VydmVyLlNUQVRFX1NUT1BQRUQpCgkJCXRocm93IG5ldyBDb3JlRXhjZXB0aW9uKG5ldyBTdGF0dXMoSVN0YXR1cy5FUlJPUiwgU2VydmVyQ29yZS5QTFVHSU5fSUQsIDAsIFNlcnZlclBsdWdpbi5nZXRSZXNvdXJjZSgiJWVycm9yU3RhcnRGYWlsZWQiLCBnZXROYW1lKCkpLCBudWxsKSk7Ki8KCX0KCQoJLyoqCgkgKiBUcmlnZ2VyIGEgcmVzdGFydCBvZiB0aGUgZ2l2ZW4gbW9kdWxlIGFuZCB3YWl0IHVudGlsIGl0IGhhcyBmaW5pc2hlZCByZXN0YXJ0aW5nLgoJICoKCSAqIEBwYXJhbSBtb2R1bGUgb3JnLmVjbGlwc2Uud3N0LnNlcnZlci5jb3JlLklNb2R1bGUKCSAqIEBwYXJhbSBtb25pdG9yIG9yZy5lY2xpcHNlLmNvcmUucnVudGltZS5JUHJvZ3Jlc3NNb25pdG9yCgkgKiBAZXhjZXB0aW9uIG9yZy5lY2xpcHNlLmNvcmUucnVudGltZS5Db3JlRXhjZXB0aW9uIC0gdGhyb3duIGlmIGFuIGVycm9yIG9jY3VycyB3aGlsZSB0cnlpbmcgdG8gcmVzdGFydCB0aGUgbW9kdWxlCgkgKi8KCXB1YmxpYyB2b2lkIHN5bmNocm9ub3VzUmVzdGFydE1vZHVsZShmaW5hbCBJTW9kdWxlIG1vZHVsZSwgSVByb2dyZXNzTW9uaXRvciBtb25pdG9yKSB0aHJvd3MgQ29yZUV4Y2VwdGlvbiB7CgkJVHJhY2UudHJhY2UoVHJhY2UuRklORVNULCAic3luY2hyb25vdXNNb2R1bGVSZXN0YXJ0IDEiKTsKCgkJZmluYWwgT2JqZWN0IG11dGV4ID0gbmV3IE9iamVjdCgpOwoJCgkJLy8gYWRkIGxpc3RlbmVyIHRvIHRoZSBtb2R1bGUKCQlJU2VydmVyTGlzdGVuZXIgbGlzdGVuZXIgPSBuZXcgU2VydmVyQWRhcHRlcigpIHsKCQkJcHVibGljIHZvaWQgbW9kdWxlU3RhdGVDaGFuZ2UoSVNlcnZlciBzZXJ2ZXIpIHsKCQkJCWludCBzdGF0ZSA9IHNlcnZlci5nZXRNb2R1bGVTdGF0ZShtb2R1bGUpOwoJCQkJaWYgKHN0YXRlID09IElTZXJ2ZXIuU1RBVEVfU1RBUlRFRCB8fCBzdGF0ZSA9PSBJU2VydmVyLlNUQVRFX1NUT1BQRUQpIHsKCQkJCQkvLyBub3RpZnkgd2FpdGVyCgkJCQkJc3luY2hyb25pemVkIChtdXRleCkgewoJCQkJCQl0cnkgewoJCQkJCQkJVHJhY2UudHJhY2UoVHJhY2UuRklORVNULCAic3luY2hyb25vdXNNb2R1bGVSZXN0YXJ0IG5vdGlmeSIpOwoJCQkJCQkJbXV0ZXgubm90aWZ5QWxsKCk7CgkJCQkJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCQkJCQlUcmFjZS50cmFjZShUcmFjZS5TRVZFUkUsICJFcnJvciBub3RpZnlpbmcgbW9kdWxlIHJlc3RhcnQiLCBlKTsKCQkJCQkJfQoJCQkJCX0KCQkJCX0KCQkJfQoJCX07CgkJYWRkU2VydmVyTGlzdGVuZXIobGlzdGVuZXIpOwoJCQoJCS8vIG1ha2Ugc3VyZSBpdCB0aW1lcyBvdXQgYWZ0ZXIgMzBzCgkJY2xhc3MgVGltZXIgewoJCQlib29sZWFuIHRpbWVvdXQ7CgkJCWJvb2xlYW4gYWxyZWFkeURvbmU7CgkJfQoJCWZpbmFsIFRpbWVyIHRpbWVyID0gbmV3IFRpbWVyKCk7CgkJCgkJVGhyZWFkIHRocmVhZCA9IG5ldyBUaHJlYWQoKSB7CgkJCXB1YmxpYyB2b2lkIHJ1bigpIHsKCQkJCXRyeSB7CgkJCQkJVGhyZWFkLnNsZWVwKDMwMDAwKTsKCQkJCQlpZiAoIXRpbWVyLmFscmVhZHlEb25lKSB7CgkJCQkJCXRpbWVyLnRpbWVvdXQgPSB0cnVlOwoJCQkJCQkvLyBub3RpZnkgd2FpdGVyCgkJCQkJCXN5bmNocm9uaXplZCAobXV0ZXgpIHsKCQkJCQkJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgInN5bmNocm9ub3VzTW9kdWxlUmVzdGFydCBub3RpZnkgdGltZW91dCIpOwoJCQkJCQkJbXV0ZXgubm90aWZ5QWxsKCk7CgkJCQkJCX0KCQkJCQl9CgkJCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkJCVRyYWNlLnRyYWNlKFRyYWNlLlNFVkVSRSwgIkVycm9yIG5vdGlmeWluZyBtb2R1bGUgcmVzdGFydCB0aW1lb3V0IiwgZSk7CgkJCQl9CgkJCX0KCQl9OwoJCXRocmVhZC5zZXREYWVtb24odHJ1ZSk7CgkJdGhyZWFkLnN0YXJ0KCk7CgkKCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICJzeW5jaHJvbm91c01vZHVsZVJlc3RhcnQgMiIpOwoJCgkJLy8gcmVzdGFydCB0aGUgbW9kdWxlCgkJdHJ5IHsKCQkJZ2V0QmVoYXZpb3VyRGVsZWdhdGUoKS5yZXN0YXJ0TW9kdWxlKG1vZHVsZSwgbW9uaXRvcik7CgkJfSBjYXRjaCAoQ29yZUV4Y2VwdGlvbiBlKSB7CgkJCXJlbW92ZVNlcnZlckxpc3RlbmVyKGxpc3RlbmVyKTsKCQkJdGhyb3cgZTsKCQl9CgkKCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICJzeW5jaHJvbm91c01vZHVsZVJlc3RhcnQgMyIpOwoJCgkJLy8gd2FpdCBmb3IgaXQhIHdhaXQgZm9yIGl0ISAuLi4KCQlzeW5jaHJvbml6ZWQgKG11dGV4KSB7CgkJCXRyeSB7CgkJCQl3aGlsZSAoIXRpbWVyLnRpbWVvdXQgJiYgIShnZXRNb2R1bGVTdGF0ZShtb2R1bGUpID09IElTZXJ2ZXIuU1RBVEVfU1RBUlRFRCB8fCBnZXRNb2R1bGVTdGF0ZShtb2R1bGUpID09IElTZXJ2ZXIuU1RBVEVfU1RPUFBFRCkpCgkJCQkJbXV0ZXgud2FpdCgpOwoJCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiRXJyb3Igd2FpdGluZyBmb3Igc2VydmVyIHN0YXJ0IiwgZSk7CgkJCX0KCQl9CgkJcmVtb3ZlU2VydmVyTGlzdGVuZXIobGlzdGVuZXIpOwoJCWlmICh0aW1lci50aW1lb3V0KQoJCQl0aHJvdyBuZXcgQ29yZUV4Y2VwdGlvbihuZXcgU3RhdHVzKElTdGF0dXMuRVJST1IsIFNlcnZlclBsdWdpbi5QTFVHSU5fSUQsIDAsIFNlcnZlclBsdWdpbi5nZXRSZXNvdXJjZSgiJWVycm9yTW9kdWxlUmVzdGFydEZhaWxlZCIsIGdldE5hbWUoKSksIG51bGwpKTsKCQl0aW1lci5hbHJlYWR5RG9uZSA9IHRydWU7CgkJCgkJaWYgKGdldE1vZHVsZVN0YXRlKG1vZHVsZSkgPT0gSVNlcnZlci5TVEFURV9TVE9QUEVEKQoJCQl0aHJvdyBuZXcgQ29yZUV4Y2VwdGlvbihuZXcgU3RhdHVzKElTdGF0dXMuRVJST1IsIFNlcnZlclBsdWdpbi5QTFVHSU5fSUQsIDAsIFNlcnZlclBsdWdpbi5nZXRSZXNvdXJjZSgiJWVycm9yTW9kdWxlUmVzdGFydEZhaWxlZCIsIGdldE5hbWUoKSksIG51bGwpKTsKCQoJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgInN5bmNocm9ub3VzTW9kdWxlUmVzdGFydCA0Iik7Cgl9CgoJcHVibGljIElQYXRoIGdldFRlbXBEaXJlY3RvcnkoKSB7CgkJcmV0dXJuIFNlcnZlclBsdWdpbi5nZXRJbnN0YW5jZSgpLmdldFRlbXBEaXJlY3RvcnkoZ2V0SWQoKSk7Cgl9CgoJcHJvdGVjdGVkIFN0cmluZyBnZXRYTUxSb290KCkgewoJCXJldHVybiAic2VydmVyIjsKCX0KCQoJcHJvdGVjdGVkIHZvaWQgbG9hZFN0YXRlKElNZW1lbnRvIG1lbWVudG8pIHsKCQkvKlN0cmluZyBzZXJ2ZXJUeXBlSWQgPSBtZW1lbnRvLmdldFN0cmluZygic2VydmVyLXR5cGUtaWQiKTsKCQlzZXJ2ZXJUeXBlID0gU2VydmVyQ29yZS5nZXRTZXJ2ZXJUeXBlKHNlcnZlclR5cGVJZCk7CgkJCgkJU3RyaW5nIHJ1bnRpbWVJZCA9IG1lbWVudG8uZ2V0U3RyaW5nKCJydW50aW1lLWlkIik7CgkJcnVudGltZSA9IFNlcnZlckNvcmUuZ2V0UmVzb3VyY2VNYW5hZ2VyKCkuZ2V0UnVudGltZShydW50aW1lSWQpOwoJCQoJCVN0cmluZyBjb25maWd1cmF0aW9uSWQgPSBtZW1lbnRvLmdldFN0cmluZygiY29uZmlndXJhdGlvbi1pZCIpOwoJCWNvbmZpZ3VyYXRpb24gPSBTZXJ2ZXJDb3JlLmdldFJlc291cmNlTWFuYWdlcigpLmdldFNlcnZlckNvbmZpZ3VyYXRpb24oY29uZmlndXJhdGlvbklkKTsqLwoJCXJlc29sdmUoKTsKCX0KCQoJcHJvdGVjdGVkIHZvaWQgcmVzb2x2ZSgpIHsKCQlJU2VydmVyVHlwZSBvbGRTZXJ2ZXJUeXBlID0gc2VydmVyVHlwZTsKCQlTdHJpbmcgc2VydmVyVHlwZUlkID0gZ2V0QXR0cmlidXRlKCJzZXJ2ZXItdHlwZS1pZCIsIChTdHJpbmcpbnVsbCk7CgkJaWYgKHNlcnZlclR5cGVJZCAhPSBudWxsKQoJCQlzZXJ2ZXJUeXBlID0gU2VydmVyQ29yZS5maW5kU2VydmVyVHlwZShzZXJ2ZXJUeXBlSWQpOwoJCWVsc2UKCQkJc2VydmVyVHlwZSA9IG51bGw7CgkJaWYgKHNlcnZlclR5cGUgIT0gbnVsbCAmJiAhc2VydmVyVHlwZS5lcXVhbHMob2xkU2VydmVyVHlwZSkpCgkJCXNlcnZlclN0YXRlID0gKChTZXJ2ZXJUeXBlKXNlcnZlclR5cGUpLmdldEluaXRpYWxTdGF0ZSgpOwoJCQoJCVN0cmluZyBydW50aW1lSWQgPSBnZXRBdHRyaWJ1dGUoUlVOVElNRV9JRCwgKFN0cmluZyludWxsKTsKCQlpZiAocnVudGltZUlkICE9IG51bGwpCgkJCXJ1bnRpbWUgPSBTZXJ2ZXJDb3JlLmZpbmRSdW50aW1lKHJ1bnRpbWVJZCk7CgkJCgkJU3RyaW5nIGNvbmZpZ1BhdGggPSBnZXRBdHRyaWJ1dGUoQ09ORklHVVJBVElPTl9JRCwgKFN0cmluZyludWxsKTsKCQljb25maWd1cmF0aW9uID0gbnVsbDsKCQlpZiAoY29uZmlnUGF0aCAhPSBudWxsKQoJCQljb25maWd1cmF0aW9uID0gUmVzb3VyY2VzUGx1Z2luLmdldFdvcmtzcGFjZSgpLmdldFJvb3QoKS5nZXRGb2xkZXIobmV3IFBhdGgoY29uZmlnUGF0aCkpOwoJfQoKCXByb3RlY3RlZCB2b2lkIHNldEludGVybmFsKFNlcnZlcldvcmtpbmdDb3B5IHdjKSB7CgkJbWFwID0gd2MubWFwOwoJCWNvbmZpZ3VyYXRpb24gPSB3Yy5jb25maWd1cmF0aW9uOwoJCXJ1bnRpbWUgPSB3Yy5ydW50aW1lOwoJCXNlcnZlclN5bmNTdGF0ZSA9IHdjLnNlcnZlclN5bmNTdGF0ZTsKCQkvL3Jlc3RhcnROZWVkZWQgPSB3Yy5yZXN0YXJ0TmVlZGVkOwoJCXNlcnZlclR5cGUgPSB3Yy5zZXJ2ZXJUeXBlOwoJCW1vZHVsZXMgPSB3Yy5tb2R1bGVzOwoKCQkvLyBjYW4gbmV2ZXIgbW9kaWZ5IHRoZSBmb2xsb3dpbmcgcHJvcGVydGllcyB2aWEgdGhlIHdvcmtpbmcgY29weQoJCS8vc2VydmVyU3RhdGUgPSB3Yy5zZXJ2ZXJTdGF0ZTsKCQlkZWxlZ2F0ZSA9IHdjLmRlbGVnYXRlOwoJfQoKCXByb3RlY3RlZCB2b2lkIHNhdmVTdGF0ZShJTWVtZW50byBtZW1lbnRvKSB7CgkJaWYgKHNlcnZlclR5cGUgIT0gbnVsbCkKCQkJbWVtZW50by5wdXRTdHJpbmcoInNlcnZlci10eXBlIiwgc2VydmVyVHlwZS5nZXRJZCgpKTsKCgkJaWYgKGNvbmZpZ3VyYXRpb24gIT0gbnVsbCkKCQkJbWVtZW50by5wdXRTdHJpbmcoQ09ORklHVVJBVElPTl9JRCwgY29uZmlndXJhdGlvbi5nZXRGdWxsUGF0aCgpLnRvU3RyaW5nKCkpOwoJCWVsc2UKCQkJbWVtZW50by5wdXRTdHJpbmcoQ09ORklHVVJBVElPTl9JRCwgbnVsbCk7CgkJCgkJaWYgKHJ1bnRpbWUgIT0gbnVsbCkKCQkJbWVtZW50by5wdXRTdHJpbmcoUlVOVElNRV9JRCwgcnVudGltZS5nZXRJZCgpKTsKCQllbHNlCgkJCW1lbWVudG8ucHV0U3RyaW5nKFJVTlRJTUVfSUQsIG51bGwpOwoJfQoKCS8qcHVibGljIHZvaWQgdXBkYXRlQ29uZmlndXJhdGlvbigpIHsKCQl0cnkgewoJCQlnZXREZWxlZ2F0ZShudWxsKS51cGRhdGVDb25maWd1cmF0aW9uKCk7CgkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiRXJyb3IgY2FsbGluZyBkZWxlZ2F0ZSB1cGRhdGVDb25maWd1cmF0aW9uKCkgIiArIHRvU3RyaW5nKCksIGUpOwoJCX0KCX0qLwoJCgkvKiAobm9uLUphdmFkb2MpCgkgKiBAc2VlIG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIuY29yZS5JU2VydmVyQ29uZmlndXJhdGlvbiNjYW5Nb2RpZnlNb2R1bGUob3JnLmVjbGlwc2Uud3N0LnNlcnZlci5jb3JlLm1vZGVsLklNb2R1bGUpCgkgKi8KCXB1YmxpYyBJU3RhdHVzIGNhbk1vZGlmeU1vZHVsZXMoSU1vZHVsZVtdIGFkZCwgSU1vZHVsZVtdIHJlbW92ZSwgSVByb2dyZXNzTW9uaXRvciBtb25pdG9yKSB7CgkJdHJ5IHsKCQkJcmV0dXJuIGdldERlbGVnYXRlKCkuY2FuTW9kaWZ5TW9kdWxlcyhhZGQsIHJlbW92ZSk7CgkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiRXJyb3IgY2FsbGluZyBkZWxlZ2F0ZSBjYW5Nb2RpZnlNb2R1bGVzKCkgIiArIHRvU3RyaW5nKCksIGUpOwoJCQlyZXR1cm4gbnVsbDsKCQl9Cgl9CgoJLyogKG5vbi1KYXZhZG9jKQoJICogQHNlZSBvcmcuZWNsaXBzZS53c3Quc2VydmVyLmNvcmUuSVNlcnZlciNnZXRNb2R1bGVzKCkKCSAqLwoJcHVibGljIElNb2R1bGVbXSBnZXRNb2R1bGVzKCkgewoJCWlmIChtb2R1bGVzID09IG51bGwpIHsKCQkJLy8gY29udmVydCBmcm9tIGF0dHJpYnV0ZQoJCQlMaXN0IGxpc3QgPSBnZXRBdHRyaWJ1dGUoTU9EVUxFX0xJU1QsIChMaXN0KSBudWxsKTsKCQkJaWYgKGxpc3QgPT0gbnVsbCkKCQkJCWxpc3QgPSBuZXcgQXJyYXlMaXN0KDEpOwoJCQkKCQkJbW9kdWxlcyA9IG5ldyBBcnJheUxpc3QobGlzdC5zaXplKCkgKyAxKTsKCQkJSXRlcmF0b3IgaXRlcmF0b3IgPSBsaXN0Lml0ZXJhdG9yKCk7CgkJCXdoaWxlIChpdGVyYXRvci5oYXNOZXh0KCkpIHsKCQkJCVN0cmluZyBtb2R1bGVTdHIgPSAoU3RyaW5nKSBpdGVyYXRvci5uZXh0KCk7CgkJCQlJTW9kdWxlIG1vZHVsZSA9IFNlcnZlclV0aWwuZ2V0TW9kdWxlKG1vZHVsZVN0cik7CgkJCQlpZiAobW9kdWxlICE9IG51bGwpCgkJCQkJbW9kdWxlcy5hZGQobW9kdWxlKTsKCQkJfQoJCX0gZWxzZSB7CgkJCS8vIHZlcmlmeSBtb2R1bGVzIGFyZSBzdGlsbCBhdmFpbGFibGUKCQkJTGlzdCByZW1vdmUgPSBuZXcgQXJyYXlMaXN0KCk7CgkJCUl0ZXJhdG9yIGl0ZXJhdG9yID0gbW9kdWxlcy5pdGVyYXRvcigpOwoJCQl3aGlsZSAoaXRlcmF0b3IuaGFzTmV4dCgpKSB7CgkJCQlJTW9kdWxlIG1vZHVsZSA9IChJTW9kdWxlKSBpdGVyYXRvci5uZXh0KCk7CgkJCQlpZiAoU2VydmVyVXRpbC5nZXRNb2R1bGUobW9kdWxlLmdldElkKCkpID09IG51bGwpCgkJCQkJcmVtb3ZlLmFkZChtb2R1bGUpOwoJCQl9CgkJCQoJCQlpdGVyYXRvciA9IHJlbW92ZS5pdGVyYXRvcigpOwoJCQl3aGlsZSAoaXRlcmF0b3IuaGFzTmV4dCgpKSB7CgkJCQltb2R1bGVzLnJlbW92ZShpdGVyYXRvci5uZXh0KCkpOwoJCQl9CgkJfQoJCQoJCUlNb2R1bGVbXSBtb2R1bGVzMiA9IG5ldyBJTW9kdWxlW21vZHVsZXMuc2l6ZSgpXTsKCQltb2R1bGVzLnRvQXJyYXkobW9kdWxlczIpOwoJCXJldHVybiBtb2R1bGVzMjsKCX0KCQoJLyogKG5vbi1KYXZhZG9jKQoJICogQHNlZSBvcmcuZWNsaXBzZS53c3Quc2VydmVyLmNvcmUuSVNlcnZlciNnZXRTZXJ2ZXJNb2R1bGVzKCkKCSAqLwoJcHVibGljIElNb2R1bGVbXSBnZXRTZXJ2ZXJNb2R1bGVzKElQcm9ncmVzc01vbml0b3IgbW9uaXRvcikgewoJCXRyeSB7CgkJCXJldHVybiBzZXJ2ZXJNb2R1bGVzOwoJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCVRyYWNlLnRyYWNlKFRyYWNlLlNFVkVSRSwgIkVycm9yIGNhbGxpbmcgZGVsZWdhdGUgZ2V0TW9kdWxlcygpICIgKyB0b1N0cmluZygpLCBlKTsKCQkJcmV0dXJuIG5ldyBJTW9kdWxlWzBdOwoJCX0KCX0KCgkvKiAobm9uLUphdmFkb2MpCgkgKiBAc2VlIG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIuY29yZS5JU2VydmVyI2dldE1vZHVsZVN0YXRlKCkKCSAqLwoJcHVibGljIGludCBnZXRNb2R1bGVTdGF0ZShJTW9kdWxlIG1vZHVsZSkgewoJCXRyeSB7CgkJCUludGVnZXIgaW4gPSAoSW50ZWdlcikgbW9kdWxlU3RhdGUuZ2V0KG1vZHVsZS5nZXRJZCgpKTsKCQkJaWYgKGluICE9IG51bGwpCgkJCQlyZXR1cm4gaW4uaW50VmFsdWUoKTsKCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkvLyBpZ25vcmUKCQl9CgkJcmV0dXJuIFNUQVRFX1VOS05PV047Cgl9CgoJLyogKG5vbi1KYXZhZG9jKQoJICogQHNlZSBvcmcuZWNsaXBzZS53c3Quc2VydmVyLmNvcmUuSVNlcnZlciNnZXRNb2R1bGVTdGF0ZSgpCgkgKi8KCXB1YmxpYyBpbnQgZ2V0TW9kdWxlUHVibGlzaFN0YXRlKElNb2R1bGUgbW9kdWxlKSB7CgkJdHJ5IHsKCQkJSW50ZWdlciBpbiA9IChJbnRlZ2VyKSBtb2R1bGVQdWJsaXNoU3RhdGUuZ2V0KG1vZHVsZS5nZXRJZCgpKTsKCQkJaWYgKGluICE9IG51bGwpCgkJCQlyZXR1cm4gaW4uaW50VmFsdWUoKTsKCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkvLyBpZ25vcmUKCQl9CgkJcmV0dXJuIFBVQkxJU0hfU1RBVEVfVU5LTk9XTjsKCX0KCgkvKgoJICogQHNlZSBJU2VydmVyI2dldENoaWxkTW9kdWxlKElNb2R1bGUpCgkgKi8KCXB1YmxpYyBJTW9kdWxlW10gZ2V0Q2hpbGRNb2R1bGVzKElNb2R1bGUgbW9kdWxlLCBJUHJvZ3Jlc3NNb25pdG9yIG1vbml0b3IpIHsKCQl0cnkgewoJCQlyZXR1cm4gZ2V0RGVsZWdhdGUoKS5nZXRDaGlsZE1vZHVsZXMobW9kdWxlKTsKCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQlUcmFjZS50cmFjZShUcmFjZS5TRVZFUkUsICJFcnJvciBjYWxsaW5nIGRlbGVnYXRlIGdldENoaWxkTW9kdWxlcygpICIgKyB0b1N0cmluZygpLCBlKTsKCQkJcmV0dXJuIG51bGw7CgkJfQoJfQoKCS8qCgkgKiBAc2VlIElTZXJ2ZXIjZ2V0Um9vdE1vZHVsZXMoSU1vZHVsZSkKCSAqLwoJcHVibGljIElNb2R1bGVbXSBnZXRSb290TW9kdWxlcyhJTW9kdWxlIG1vZHVsZSwgSVByb2dyZXNzTW9uaXRvciBtb25pdG9yKSB0aHJvd3MgQ29yZUV4Y2VwdGlvbiB7CgkJdHJ5IHsKCQkJcmV0dXJuIGdldERlbGVnYXRlKCkuZ2V0Um9vdE1vZHVsZXMobW9kdWxlKTsKCQl9IGNhdGNoIChDb3JlRXhjZXB0aW9uIHNlKSB7CgkJCS8vVHJhY2UudHJhY2UoVHJhY2UuRklORVIsICJDb3JlRXhjZXB0aW9uIGNhbGxpbmcgZGVsZWdhdGUgZ2V0UGFyZW50TW9kdWxlcygpICIgKyB0b1N0cmluZygpICsgIjogIiArIHNlLmdldE1lc3NhZ2UoKSk7CgkJCXRocm93IHNlOwoJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCVRyYWNlLnRyYWNlKFRyYWNlLlNFVkVSRSwgIkVycm9yIGNhbGxpbmcgZGVsZWdhdGUgZ2V0UGFyZW50TW9kdWxlcygpICIgKyB0b1N0cmluZygpLCBlKTsKCQkJcmV0dXJuIG51bGw7CgkJfQoJfQoJCgkvKgoJICogCgkgKi8KCS8qcHVibGljIGJvb2xlYW4gaGFzUnVudGltZSgpIHsKCQl0cnkgewoJCQlyZXR1cm4gZ2V0RGVsZWdhdGUoKS5yZXF1aXJlc1J1bnRpbWUoKTsKCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQlUcmFjZS50cmFjZShUcmFjZS5TRVZFUkUsICJFcnJvciBjYWxsaW5nIGRlbGVnYXRlIHJlcXVpcmVzUnVudGltZSgpICIgKyB0b1N0cmluZygpLCBlKTsKCQkJcmV0dXJuIGZhbHNlOwoJCX0KCX0qLwoJCgkvKioKCSAqIFJldHVybnMgd2hldGhlciB0aGUgZ2l2ZW4gbW9kdWxlIGNhbiBiZSByZXN0YXJ0ZWQuCgkgKgoJICogQHBhcmFtIG1vZHVsZSB0aGUgbW9kdWxlCgkgKiBAcmV0dXJuIDxjb2RlPnRydWU8L2NvZGU+IGlmIHRoZSBnaXZlbiBtb2R1bGUgY2FuIGJlCgkgKiAgICByZXN0YXJ0ZWQsIGFuZCA8Y29kZT5mYWxzZTwvY29kZT4gb3RoZXJ3aXNlCgkgKiBUT0RPOiBmaXggcmV0dXJuIHN0cmluZ3MKCSAqLwoJcHVibGljIElTdGF0dXMgY2FuUmVzdGFydE1vZHVsZShJTW9kdWxlIG1vZHVsZSkgewoJCXRyeSB7CgkJCWJvb2xlYW4gYiA9IGdldEJlaGF2aW91ckRlbGVnYXRlKCkuY2FuUmVzdGFydE1vZHVsZShtb2R1bGUpOwoJCQlpZiAoYikKCQkJCXJldHVybiBuZXcgU3RhdHVzKElTdGF0dXMuT0ssIFNlcnZlclBsdWdpbi5QTFVHSU5fSUQsIDAsIFNlcnZlclBsdWdpbi5nZXRSZXNvdXJjZSgiJWVycm9yTGF1bmNoTW9kZSIpLCBudWxsKTsKCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQlUcmFjZS50cmFjZShUcmFjZS5TRVZFUkUsICJFcnJvciBjYWxsaW5nIGRlbGVnYXRlIGNhblJlc3RhcnRSdW50aW1lKCkgIiArIHRvU3RyaW5nKCksIGUpOwoJCX0KCQlyZXR1cm4gbmV3IFN0YXR1cyhJU3RhdHVzLkVSUk9SLCBTZXJ2ZXJQbHVnaW4uUExVR0lOX0lELCAwLCBTZXJ2ZXJQbHVnaW4uZ2V0UmVzb3VyY2UoIiVlcnJvckxhdW5jaE1vZGUiKSwgbnVsbCk7Cgl9CgoJLyoqCgkgKiBDaGVjayBpZiB0aGUgZ2l2ZW4gbW9kdWxlIGlzIGluIHN5bmMgb24gdGhlIHNlcnZlci4gSXQgc2hvdWxkCgkgKiByZXR1cm4gdHJ1ZSBpZiB0aGUgbW9kdWxlIHNob3VsZCBiZSByZXN0YXJ0ZWQgKGlzIG91dCBvZgoJICogc3luYykgb3IgZmFsc2UgaWYgdGhlIG1vZHVsZSBkb2VzIG5vdCBuZWVkIHRvIGJlIHJlc3RhcnRlZC4KCSAqCgkgKiBAcGFyYW0gbW9kdWxlIG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIuY29yZS5tb2RlbC5JTW9kdWxlCgkgKiBAcmV0dXJuIGJvb2xlYW4KCSAqLwoJcHVibGljIGJvb2xlYW4gZ2V0TW9kdWxlUmVzdGFydFN0YXRlKElNb2R1bGUgbW9kdWxlKSB7CgkJdHJ5IHsKCQkJQm9vbGVhbiBiID0gKEJvb2xlYW4pIG1vZHVsZVJlc3RhcnRTdGF0ZS5nZXQobW9kdWxlLmdldElkKCkpOwoJCQlpZiAoYiAhPSBudWxsKQoJCQkJcmV0dXJuIGIuYm9vbGVhblZhbHVlKCk7CgkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJLy8gaWdub3JlCgkJfQoJCXJldHVybiBmYWxzZTsKCX0KCgkvKgoJICogQHNlZSBJU2VydmVyI3Jlc3RhcnRNb2R1bGUoSU1vZHVsZSwgSVByb2dyZXNzTW9uaXRvcikKCSAqLwoJcHVibGljIHZvaWQgcmVzdGFydE1vZHVsZShJTW9kdWxlIG1vZHVsZSwgSVByb2dyZXNzTW9uaXRvciBtb25pdG9yKSB0aHJvd3MgQ29yZUV4Y2VwdGlvbiB7CgkJdHJ5IHsKCQkJZ2V0QmVoYXZpb3VyRGVsZWdhdGUoKS5yZXN0YXJ0TW9kdWxlKG1vZHVsZSwgbW9uaXRvcik7CgkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiRXJyb3IgY2FsbGluZyBkZWxlZ2F0ZSByZXN0YXJ0TW9kdWxlKCkgIiArIHRvU3RyaW5nKCksIGUpOwoJCX0KCX0KCQoJLyoqCgkgKiBSZXR1cm5zIGFuIGFycmF5IG9mIElTZXJ2ZXJQb3J0cyB0aGF0IHRoaXMgc2VydmVyIGhhcy4KCSAqCgkgKiBAcmV0dXJuIGEgcG9zc2libHkgZW1wdHkgYXJyYXkgb2Ygc2VydmVycyBwb3J0cwoJICovCglwdWJsaWMgSVNlcnZlclBvcnRbXSBnZXRTZXJ2ZXJQb3J0cygpIHsKCQl0cnkgewoJCQlyZXR1cm4gZ2V0RGVsZWdhdGUoKS5nZXRTZXJ2ZXJQb3J0cygpOwoJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCVRyYWNlLnRyYWNlKFRyYWNlLlNFVkVSRSwgIkVycm9yIGNhbGxpbmcgZGVsZWdhdGUgZ2V0U2VydmVyUG9ydHMoKSAiICsgdG9TdHJpbmcoKSwgZSk7CgkJCXJldHVybiBudWxsOwoJCX0KCX0KCQoJLyoqCgkgKiBWaXNpdCBhbGwgdGhlIG1vZHVsZXMgaW4gdGhlIHNlcnZlciB3aXRoIHRoZSBnaXZlbiBtb2R1bGUgdmlzaXRvci4KCSAqIAoJICogQHBhcmFtIG1vbml0b3IgYSBwcm9ncmVzcyBtb25pdG9yLCBvciA8Y29kZT5udWxsPC9jb2RlPiBpZiBwcm9ncmVzcwoJICogICAgcmVwb3J0aW5nIGFuZCBjYW5jZWxsYXRpb24gYXJlIG5vdCBkZXNpcmVkCgkgKi8KCXB1YmxpYyB2b2lkIHZpc2l0KElNb2R1bGVWaXNpdG9yIHZpc2l0b3IsIElQcm9ncmVzc01vbml0b3IgbW9uaXRvcikgewoJCUlNb2R1bGVbXSBtb2R1bGVzMiA9IGdldE1vZHVsZXMoKTsKCQlpZiAobW9kdWxlczIgIT0gbnVsbCkgeyAKCQkJaW50IHNpemUgPSBtb2R1bGVzMi5sZW5ndGg7CgkJCWZvciAoaW50IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKSB7CgkJCQlpZiAoIXZpc2l0TW9kdWxlKG5ldyBJTW9kdWxlWzBdLCBtb2R1bGVzMltpXSwgdmlzaXRvciwgbW9uaXRvcikpCgkJCQkJcmV0dXJuOwoJCQl9CgkJfQoJfQoKCS8qKgoJICogUmV0dXJucyB0cnVlIHRvIGtlZXAgdmlzaXRpbmcsIGFuZCBmYWxzZSB0byBzdG9wLgoJICogCgkgKiBAcGFyYW0gbW9uaXRvciBhIHByb2dyZXNzIG1vbml0b3IsIG9yIDxjb2RlPm51bGw8L2NvZGU+IGlmIHByb2dyZXNzCgkgKiAgICByZXBvcnRpbmcgYW5kIGNhbmNlbGxhdGlvbiBhcmUgbm90IGRlc2lyZWQKCSAqLwoJcHJpdmF0ZSBib29sZWFuIHZpc2l0TW9kdWxlKElNb2R1bGVbXSBwYXJlbnRzLCBJTW9kdWxlIG1vZHVsZSwgSU1vZHVsZVZpc2l0b3IgdmlzaXRvciwgSVByb2dyZXNzTW9uaXRvciBtb25pdG9yKSB7CgkJaWYgKG1vZHVsZSA9PSBudWxsIHx8IHBhcmVudHMgPT0gbnVsbCkKCQkJcmV0dXJuIHRydWU7CgkJCgkJaWYgKCF2aXNpdG9yLnZpc2l0KHBhcmVudHMsIG1vZHVsZSkpCgkJCXJldHVybiBmYWxzZTsKCQkKCQlJTW9kdWxlW10gY2hpbGRyZW4gPSBnZXRDaGlsZE1vZHVsZXMobW9kdWxlLCBtb25pdG9yKTsKCQlpZiAoY2hpbGRyZW4gIT0gbnVsbCkgewoJCQlpbnQgc2l6ZSA9IGNoaWxkcmVuLmxlbmd0aDsKCQkJZm9yIChpbnQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHsKCQkJCUlNb2R1bGUgbW9kdWxlMiA9IGNoaWxkcmVuW2ldOwoJCQkJSU1vZHVsZVtdIHBhcmVudHMyID0gbmV3IElNb2R1bGVbcGFyZW50cy5sZW5ndGggKyAxXTsKCQkJCVN5c3RlbS5hcnJheWNvcHkocGFyZW50cywgMCwgcGFyZW50czIsIDAsIHBhcmVudHMubGVuZ3RoKTsKCQkJCXBhcmVudHMyW3BhcmVudHMubGVuZ3RoXSA9IG1vZHVsZTsKCQkJCQoJCQkJaWYgKCF2aXNpdE1vZHVsZShwYXJlbnRzMiwgbW9kdWxlMiwgdmlzaXRvciwgbW9uaXRvcikpCgkJCQkJcmV0dXJuIGZhbHNlOwoJCQl9CgkJfQoJCQkKCQlyZXR1cm4gdHJ1ZTsKCX0KfQ==