LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogQ29weXJpZ2h0IChjKSAyMDAzLCAyMDA1IElCTSBDb3Jwb3JhdGlvbiBhbmQgb3RoZXJzLgogKiBBbGwgcmlnaHRzIHJlc2VydmVkLiBUaGlzIHByb2dyYW0gYW5kIHRoZSBhY2NvbXBhbnlpbmcgbWF0ZXJpYWxzCiAqIGFyZSBtYWRlIGF2YWlsYWJsZSB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEVjbGlwc2UgUHVibGljIExpY2Vuc2UgdjEuMAogKiB3aGljaCBhY2NvbXBhbmllcyB0aGlzIGRpc3RyaWJ1dGlvbiwgYW5kIGlzIGF2YWlsYWJsZSBhdAogKiBodHRwOi8vd3d3LmVjbGlwc2Uub3JnL2xlZ2FsL2VwbC12MTAuaHRtbAqgKiAKICogQ29udHJpYnV0b3JzOgogKiAgICAgSUJNIENvcnBvcmF0aW9uIC0gSW5pdGlhbCBBUEkgYW5kIGltcGxlbWVudGF0aW9uCiAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLwpwYWNrYWdlIG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIuY29yZTsKCmltcG9ydCBqYXZhLnV0aWwuKjsKCmltcG9ydCBvcmcuZWNsaXBzZS5jb3JlLnJlc291cmNlcy4qOwppbXBvcnQgb3JnLmVjbGlwc2UuY29yZS5ydW50aW1lLkNvcmVFeGNlcHRpb247CmltcG9ydCBvcmcuZWNsaXBzZS5jb3JlLnJ1bnRpbWUuSVByb2dyZXNzTW9uaXRvcjsKaW1wb3J0IG9yZy5lY2xpcHNlLmNvcmUucnVudGltZS5JU3RhdHVzOwppbXBvcnQgb3JnLmVjbGlwc2UuZGVidWcuY29yZS5JTGF1bmNoQ29uZmlndXJhdGlvbjsKCmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc2VydmVyLmNvcmUuaW50ZXJuYWwuSU1vZHVsZVZpc2l0b3I7CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc2VydmVyLmNvcmUuaW50ZXJuYWwuTW9kdWxlRmFjdG9yeTsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIuY29yZS5pbnRlcm5hbC5TZXJ2ZXI7CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc2VydmVyLmNvcmUuaW50ZXJuYWwuU2VydmVyUGx1Z2luOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNlcnZlci5jb3JlLmludGVybmFsLlRyYWNlOwovKioKICogU2VydmVyIHV0aWxpdHkgbWV0aG9kcy4gVGhlc2Ugc3RhdGljIG1ldGhvZHMgY2FuIGJlIHVzZWQgdG8gcGVyZm9ybQogKiBjb21tb24gb3BlcmF0aW9ucyBvbiBzZXJ2ZXIgYXJ0aWZhY3RzLgogKiAKICogQHNpbmNlIDEuMAogKi8KcHVibGljIGNsYXNzIFNlcnZlclV0aWwgewoJLyoqCgkgKiBTdGF0aWMgdXRpbGl0eSBjbGFzcyAtIGNhbm5vdCBjcmVhdGUgYW4gaW5zdGFuY2UuCgkgKi8KCXByaXZhdGUgU2VydmVyVXRpbCgpIHsKCQkvLyBkbyBub3RoaW5nCgl9CgoJLyoqCgkgKiBSZXR1cm5zIHRoZSBwcm9qZWN0IG1vZHVsZXMgYXR0YWNoZWQgdG8gYSBwcm9qZWN0LgoJICogCgkgKiBAcGFyYW0gcHJvamVjdCBhIHByb2plY3QKCSAqIEByZXR1cm4gYSBwb3NzaWJseSBlbXB0eSBhcnJheSBvZiBtb2R1bGVzCgkgKi8KCXB1YmxpYyBzdGF0aWMgSU1vZHVsZVtdIGdldE1vZHVsZXMoSVByb2plY3QgcHJvamVjdCkgewoJCWlmIChwcm9qZWN0ID09IG51bGwpCgkJCXJldHVybiBudWxsOwoKCQlMaXN0IGxpc3QgPSBuZXcgQXJyYXlMaXN0KCk7CgkJSU1vZHVsZVtdIG1vZHVsZXMgPSBnZXRNb2R1bGVzKCk7CgkJaWYgKG1vZHVsZXMgIT0gbnVsbCkgewoJCQlpbnQgc2l6ZSA9IG1vZHVsZXMubGVuZ3RoOwoJCQlmb3IgKGludCBpID0gMDsgaSA8IHNpemU7IGkrKykgewoJCQkJaWYgKG1vZHVsZXNbaV0gIT0gbnVsbCAmJiBwcm9qZWN0LmVxdWFscyhtb2R1bGVzW2ldLmdldFByb2plY3QoKSkpCgkJCQkJbGlzdC5hZGQobW9kdWxlc1tpXSk7CgkJCX0KCQl9CgkJCgkJSU1vZHVsZVtdIG1vZHVsZXMyID0gbmV3IElNb2R1bGVbbGlzdC5zaXplKCldOwoJCWxpc3QudG9BcnJheShtb2R1bGVzMik7CgkJcmV0dXJuIG1vZHVsZXMyOwoJfQoKCS8qKgoJICogUmV0dXJucyBhIG1vZHVsZSBmcm9tIHRoZSBnaXZlbiBtb2R1bGVJZC4gVGhlIG1vZHVsZUlkIG11c3Qgbm90IGJlIG51bGwuCgkgKiAKCSAqIEBwYXJhbSBtb2R1bGVJZCBhIG1vZHVsZSBpZAoJICogQHJldHVybiB0aGUgbW9kdWxlLCBvciA8Y29kZT5udWxsPC9jb2RlPiBpZiB0aGUgbW9kdWxlIGNvdWxkIG5vdCBiZSBmb3VuZAoJICovCglwdWJsaWMgc3RhdGljIElNb2R1bGUgZ2V0TW9kdWxlKFN0cmluZyBtb2R1bGVJZCkgewoJCWlmIChtb2R1bGVJZCA9PSBudWxsKQoJCQl0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7CgkJCgkJaW50IGluZGV4ID0gbW9kdWxlSWQuaW5kZXhPZigiOiIpOwoJCWlmIChpbmRleCA8PSAwKQoJCQlyZXR1cm4gbnVsbDsKCQkKCQlTdHJpbmcgZmFjdG9yeUlkID0gbW9kdWxlSWQuc3Vic3RyaW5nKDAsIGluZGV4KTsKCQlNb2R1bGVGYWN0b3J5IG1vZHVsZUZhY3RvcnkgPSBTZXJ2ZXJQbHVnaW4uZmluZE1vZHVsZUZhY3RvcnkoZmFjdG9yeUlkKTsKCQlpZiAobW9kdWxlRmFjdG9yeSA9PSBudWxsKQoJCQlyZXR1cm4gbnVsbDsKCgkJU3RyaW5nIG1vZHVsZVN1YklkID0gbW9kdWxlSWQuc3Vic3RyaW5nKGluZGV4KzEpOwoJCUlNb2R1bGUgbW9kdWxlID0gbW9kdWxlRmFjdG9yeS5nZXRNb2R1bGUobW9kdWxlU3ViSWQpOwoJCWlmIChtb2R1bGUgIT0gbnVsbCkKCQkJcmV0dXJuIG1vZHVsZTsKCQlyZXR1cm4gbnVsbDsKCX0KCgkvKioKCSAqIFJldHVybiBhbGwgdGhlIGF2YWlsYWJsZSBtb2R1bGVzIGZyb20gYWxsIGZhY3RvcmllcyB3aG9zZQoJICogdHlwZSBtYXRjaGVzIHRoZSBnaXZlbiBtb2R1bGUgdHlwZXMuCgkgKiAKCSAqIEBwYXJhbSBtb2R1bGVUeXBlcyBhbiBhcnJheSBvZiBtb2R1bGUgdHlwZXMKCSAqIEByZXR1cm4gYSBwb3NzaWJseSBlbXB0eSBhcnJheSBvZiBtb2R1bGVzCgkgKi8KCXB1YmxpYyBzdGF0aWMgSU1vZHVsZVtdIGdldE1vZHVsZXMoSU1vZHVsZVR5cGVbXSBtb2R1bGVUeXBlcykgewoJCUxpc3QgbGlzdCA9IG5ldyBBcnJheUxpc3QoKTsKCgkJTW9kdWxlRmFjdG9yeVtdIGZhY3RvcmllcyA9IFNlcnZlclBsdWdpbi5nZXRNb2R1bGVGYWN0b3JpZXMoKTsKCQlpZiAoZmFjdG9yaWVzICE9IG51bGwpIHsKCQkJaW50IHNpemUgPSBmYWN0b3JpZXMubGVuZ3RoOwoJCQlmb3IgKGludCBpID0gMDsgaSA8IHNpemU7IGkrKykgewoJCQkJaWYgKGlzU3VwcG9ydGVkTW9kdWxlKGZhY3Rvcmllc1tpXS5nZXRNb2R1bGVUeXBlcygpLCBtb2R1bGVUeXBlcykpIHsKCQkJCQlJTW9kdWxlW10gbW9kdWxlcyA9IGZhY3Rvcmllc1tpXS5nZXRNb2R1bGVzKCk7CgkJCQkJaWYgKG1vZHVsZXMgIT0gbnVsbCkgewoJCQkJCQlpbnQgc2l6ZTIgPSBtb2R1bGVzLmxlbmd0aDsKCQkJCQkJZm9yIChpbnQgaiA9IDA7IGogPCBzaXplMjsgaisrKQoJCQkJCQkJbGlzdC5hZGQobW9kdWxlc1tqXSk7CgkJCQkJfQoJCQkJfQoJCQl9CgkJfQoJCUlNb2R1bGVbXSBtb2R1bGVzID0gbmV3IElNb2R1bGVbbGlzdC5zaXplKCldOwoJCWxpc3QudG9BcnJheShtb2R1bGVzKTsKCQlyZXR1cm4gbW9kdWxlczsKCX0KCQoJLyoqCgkgKiBSZXR1cm4gYWxsIHRoZSBhdmFpbGFibGUgbW9kdWxlcyBmcm9tIGFsbCBmYWN0b3JpZXMgd2hvc2UKCSAqIHR5cGUgbWF0Y2hlcyB0aGUgZ2l2ZW4gbW9kdWxlIHR5cGUgaWQuCgkgKiAKCSAqIEBwYXJhbSB0eXBlIGEgbW9kdWxlIHR5cGUKCSAqIEByZXR1cm4gYSBwb3NzaWJseSBlbXB0eSBhcnJheSBvZiBtb2R1bGVzCgkgKi8KCXB1YmxpYyBzdGF0aWMgSU1vZHVsZVtdIGdldE1vZHVsZXMoU3RyaW5nIHR5cGUpIHsKCQlMaXN0IGxpc3QgPSBuZXcgQXJyYXlMaXN0KCk7CgoJCU1vZHVsZUZhY3RvcnlbXSBmYWN0b3JpZXMgPSBTZXJ2ZXJQbHVnaW4uZ2V0TW9kdWxlRmFjdG9yaWVzKCk7CgkJaWYgKGZhY3RvcmllcyAhPSBudWxsKSB7CgkJCWludCBzaXplID0gZmFjdG9yaWVzLmxlbmd0aDsKCQkJZm9yIChpbnQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHsKCQkJCWlmIChpc1N1cHBvcnRlZE1vZHVsZShmYWN0b3JpZXNbaV0uZ2V0TW9kdWxlVHlwZXMoKSwgdHlwZSwgbnVsbCkpIHsKCQkJCQlJTW9kdWxlW10gbW9kdWxlcyA9IGZhY3Rvcmllc1tpXS5nZXRNb2R1bGVzKCk7CgkJCQkJaWYgKG1vZHVsZXMgIT0gbnVsbCkgewoJCQkJCQlpbnQgc2l6ZTIgPSBtb2R1bGVzLmxlbmd0aDsKCQkJCQkJZm9yIChpbnQgaiA9IDA7IGogPCBzaXplMjsgaisrKQoJCQkJCQkJbGlzdC5hZGQobW9kdWxlc1tqXSk7CgkJCQkJfQoJCQkJfQoJCQl9CgkJfQoJCUlNb2R1bGVbXSBtb2R1bGVzID0gbmV3IElNb2R1bGVbbGlzdC5zaXplKCldOwoJCWxpc3QudG9BcnJheShtb2R1bGVzKTsKCQlyZXR1cm4gbW9kdWxlczsKCX0KCQoJLyoqCgkgKiBSZXR1cm5zIDxjb2RlPnRydWU8L2NvZGU+IGlmIGFueSBvZiB0aGUgZ2l2ZW4gbW9kdWxlVHlwZXMgaGF2ZSB0aGUgZ2l2ZW4KCSAqIG1vZHVsZSB0eXBlIGlkIGFuZCB2ZXJzaW9uIGlkLgoJICogCgkgKiBAcGFyYW0gbW9kdWxlVHlwZXMgYW4gYXJyYXkgb2YgbW9kdWxlIHR5cGVzCgkgKiBAcGFyYW0gdHlwZUlkIGEgbW9kdWxlIHR5cGUKCSAqIEBwYXJhbSB2ZXJzaW9uSWQgYSBtb2R1bGUgdmVyc2lvbgoJICogQHJldHVybiA8Y29kZT50cnVlPC9jb2RlPiBpZiB0aGUgbW9kdWxlIHR5cGUgaXMgc3VwcG9ydGVkLCBhbmQKCSAqICAgIDxjb2RlPmZhbHNlPC9jb2RlPiBvdGhlcndpc2UKCSAqLwoJcHVibGljIHN0YXRpYyBib29sZWFuIGlzU3VwcG9ydGVkTW9kdWxlKElNb2R1bGVUeXBlW10gbW9kdWxlVHlwZXMsIFN0cmluZyB0eXBlSWQsIFN0cmluZyB2ZXJzaW9uSWQpIHsKCQlpZiAobW9kdWxlVHlwZXMgIT0gbnVsbCkgewoJCQlpbnQgc2l6ZSA9IG1vZHVsZVR5cGVzLmxlbmd0aDsKCQkJZm9yIChpbnQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHsKCQkJCWlmIChpc1N1cHBvcnRlZE1vZHVsZShtb2R1bGVUeXBlc1tpXSwgdHlwZUlkLCB2ZXJzaW9uSWQpKQoJCQkJCXJldHVybiB0cnVlOwoJCQl9CgkJfQoJCXJldHVybiBmYWxzZTsKCX0KCglwcml2YXRlIHN0YXRpYyBib29sZWFuIGlzU3VwcG9ydGVkTW9kdWxlKElNb2R1bGVUeXBlW10gbW9kdWxlVHlwZXMsIElNb2R1bGVUeXBlW10gbXQpIHsKCQlpZiAobXQgIT0gbnVsbCkgewoJCQlpbnQgc2l6ZSA9IG10Lmxlbmd0aDsKCQkJZm9yIChpbnQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHsKCQkJCWlmIChpc1N1cHBvcnRlZE1vZHVsZShtb2R1bGVUeXBlcywgbXRbaV0pKQoJCQkJCXJldHVybiB0cnVlOwoJCQl9CgkJfQoJCXJldHVybiBmYWxzZTsKCX0KCgkvKioKCSAqIFJldHVybnMgPGNvZGU+dHJ1ZTwvY29kZT4gaWYgYW55IG9mIHRoZSBnaXZlbiBtb2R1bGVUeXBlcyBtYXRjaCB0aGUgZ2l2ZW4KCSAqIG1vZHVsZSB0eXBlLgoJICogCgkgKiBAcGFyYW0gbW9kdWxlVHlwZXMgYW4gYXJyYXkgb2YgbW9kdWxlcyB0eXBlcwoJICogQHBhcmFtIG10IGEgbW9kdWxlIHR5cGUKCSAqIEByZXR1cm4gPGNvZGU+dHJ1ZTwvY29kZT4gaWYgdGhlIG1vZHVsZSB0eXBlIGlzIHN1cHBvcnRlZCwgYW5kCgkgKiAgICA8Y29kZT5mYWxzZTwvY29kZT4gb3RoZXJ3aXNlCgkgKi8KCXB1YmxpYyBzdGF0aWMgYm9vbGVhbiBpc1N1cHBvcnRlZE1vZHVsZShJTW9kdWxlVHlwZVtdIG1vZHVsZVR5cGVzLCBJTW9kdWxlVHlwZSBtdCkgewoJCWlmIChtb2R1bGVUeXBlcyAhPSBudWxsKSB7CgkJCWludCBzaXplID0gbW9kdWxlVHlwZXMubGVuZ3RoOwoJCQlmb3IgKGludCBpID0gMDsgaSA8IHNpemU7IGkrKykgewoJCQkJaWYgKGlzU3VwcG9ydGVkTW9kdWxlKG1vZHVsZVR5cGVzW2ldLCBtdCkpCgkJCQkJcmV0dXJuIHRydWU7CgkJCX0KCQl9CgkJcmV0dXJuIGZhbHNlOwoJfQoJCglwcml2YXRlIHN0YXRpYyBib29sZWFuIGlzU3VwcG9ydGVkTW9kdWxlKElNb2R1bGVUeXBlIG1vZHVsZVR5cGUsIFN0cmluZyB0eXBlLCBTdHJpbmcgdmVyc2lvbikgewoJCVN0cmluZyB0eXBlMiA9IG1vZHVsZVR5cGUuZ2V0SWQoKTsKCQlpZiAobWF0Y2hlcyh0eXBlLCB0eXBlMikpIHsKCQkJU3RyaW5nIHZlcnNpb24yID0gbW9kdWxlVHlwZS5nZXRWZXJzaW9uKCk7CgkJCWlmIChtYXRjaGVzKHZlcnNpb24sIHZlcnNpb24yKSkKCQkJCXJldHVybiB0cnVlOwoJCX0KCQlyZXR1cm4gZmFsc2U7Cgl9CgoJLyoqCgkgKiBSZXR1cm5zIHRydWUgaWYgdGhlIHR3byBnaXZlbiBtb2R1bGUgdHlwZXMgYXJlIGNvbXBhdGlibGUuIFRoZSBtb2R1bGVUeXBlcyBtYXkgbm90CgkgKiBiZSBudWxsLgoJICogCgkgKiBAcGFyYW0gbW9kdWxlVHlwZSBhIG1vZHVsZSB0eXBlCgkgKiBAcGFyYW0gbXQgYSBtb2R1bGUgdHlwZQoJICogQHJldHVybiA8Y29kZT50cnVlPC9jb2RlPiBpZiB0aGUgbW9kdWxlIHR5cGUgaXMgc3VwcG9ydGVkLCBhbmQKCSAqICAgIDxjb2RlPmZhbHNlPC9jb2RlPiBvdGhlcndpc2UKCSAqLwoJcHVibGljIHN0YXRpYyBib29sZWFuIGlzU3VwcG9ydGVkTW9kdWxlKElNb2R1bGVUeXBlIG1vZHVsZVR5cGUsIElNb2R1bGVUeXBlIG10KSB7CgkJaWYgKG1vZHVsZVR5cGUgPT0gbnVsbCB8fCBtdCA9PSBudWxsKQoJCQl0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7CgkJCgkJU3RyaW5nIHR5cGUyID0gbW9kdWxlVHlwZS5nZXRJZCgpOwoJCWlmIChtYXRjaGVzKG10LmdldElkKCksIHR5cGUyKSkgewoJCQlTdHJpbmcgdmVyc2lvbjIgPSBtb2R1bGVUeXBlLmdldFZlcnNpb24oKTsKCQkJaWYgKG1hdGNoZXMobXQuZ2V0VmVyc2lvbigpLCB2ZXJzaW9uMikpCgkJCQlyZXR1cm4gdHJ1ZTsKCQl9CgkJcmV0dXJuIGZhbHNlOwoJfQoKCXByaXZhdGUgc3RhdGljIGJvb2xlYW4gbWF0Y2hlcyhTdHJpbmcgYSwgU3RyaW5nIGIpIHsKCQlpZiAoYSA9PSBudWxsIHx8IGIgPT0gbnVsbCB8fCAiKiIuZXF1YWxzKGEpIHx8ICIqIi5lcXVhbHMoYikgfHwgYS5zdGFydHNXaXRoKGIpIHx8IGIuc3RhcnRzV2l0aChhKSkKCQkJcmV0dXJuIHRydWU7CgkJcmV0dXJuIGZhbHNlOwoJfQoKCS8qKgoJICogUmV0dXJuIGFsbCB0aGUgYXZhaWxhYmxlIG1vZHVsZXMgZnJvbSBhbGwgZmFjdG9yaWVzLgoJICogCgkgKiBAcmV0dXJuIGEgcG9zc2libHkgZW1wdHkgYXJyYXkgb2YgbW9kdWxlcwoJICovCglwcml2YXRlIHN0YXRpYyBJTW9kdWxlW10gZ2V0TW9kdWxlcygpIHsKCQlMaXN0IGxpc3QgPSBuZXcgQXJyYXlMaXN0KCk7CgkJCgkJTW9kdWxlRmFjdG9yeVtdIGZhY3RvcmllcyA9IFNlcnZlclBsdWdpbi5nZXRNb2R1bGVGYWN0b3JpZXMoKTsKCQlpZiAoZmFjdG9yaWVzICE9IG51bGwpIHsKCQkJaW50IHNpemUgPSBmYWN0b3JpZXMubGVuZ3RoOwoJCQlmb3IgKGludCBpID0gMDsgaSA8IHNpemU7IGkrKykgewoJCQkJSU1vZHVsZVtdIG1vZHVsZXMgPSBmYWN0b3JpZXNbaV0uZ2V0TW9kdWxlcygpOwoJCQkJaWYgKG1vZHVsZXMgIT0gbnVsbCkgewoJCQkJCWludCBzaXplMiA9IG1vZHVsZXMubGVuZ3RoOwoJCQkJCWZvciAoaW50IGogPSAwOyBqIDwgc2l6ZTI7IGorKykgewoJCQkJCQlpZiAoIWxpc3QuY29udGFpbnMobW9kdWxlc1tqXSkpCgkJCQkJCQlsaXN0LmFkZChtb2R1bGVzW2pdKTsKCQkJCQl9CgkJCQl9CgkJCX0KCQl9CgkJSU1vZHVsZVtdIG1vZHVsZXMgPSBuZXcgSU1vZHVsZVtsaXN0LnNpemUoKV07CgkJbGlzdC50b0FycmF5KG1vZHVsZXMpOwoJCXJldHVybiBtb2R1bGVzOwoJfQoKCS8qKgoJICogQWRkcyBvciByZW1vdmVzIG1vZHVsZXMgZnJvbSBhIHNlcnZlci4gV2lsbCBzZWFyY2ggZm9yIHRoZSBmaXJzdCBwYXJlbnQgbW9kdWxlCgkgKiBvZiBlYWNoIG1vZHVsZSBhbmQgYWRkIGl0IHRvIHRoZSBzZXJ2ZXIgaW5zdGVhZC4gVGhpcyBtZXRob2Qgd2lsbCBoYW5kbGUgbXVsdGlwbGUKCSAqIG1vZHVsZXMgaGF2aW5nIHRoZSBzYW1lIHBhcmVudCAodGhlIHBhcmVudCB3aWxsIG9ubHkgYmUgYWRkZWQgb25jZSksIGJ1dCBtYXkgbm90CgkgKiBoYW5kbGUgdGhlIGNhc2Ugd2hlcmUgdGhlIHNhbWUgbW9kdWxlIG9yIHBhcmVudCBpcyBiZWluZyBib3RoIGFkZGVkIGFuZCByZW1vdmVkLgoJICogCgkgKiBAcGFyYW0gc2VydmVyIGEgc2VydmVyCgkgKiBAcGFyYW0gYWRkIGFuIGFycmF5IG9mIG1vZHVsZXMgdG8gYWRkLCBvciA8Y29kZT5udWxsPC9jb2RlPiB0byBub3QgYWRkIGFueQoJICogQHBhcmFtIHJlbW92ZSBhbiBhcnJheSBvZiBtb2R1bGVzIHRvIHJlbW92ZSwgb3IgPGNvZGU+bnVsbDwvY29kZT4gdG8gbm90IHJlbW92ZSBhbnkKCSAqIEBwYXJhbSBtb25pdG9yIGEgcHJvZ3Jlc3MgbW9uaXRvciwgb3IgPGNvZGU+bnVsbDwvY29kZT4gaWYgcHJvZ3Jlc3MKCSAqICAgIHJlcG9ydGluZyBhbmQgY2FuY2VsbGF0aW9uIGFyZSBub3QgZGVzaXJlZAoJICogQHRocm93cyBDb3JlRXhjZXB0aW9uCgkgKi8KCXB1YmxpYyBzdGF0aWMgdm9pZCBtb2RpZnlNb2R1bGVzKElTZXJ2ZXJXb3JraW5nQ29weSBzZXJ2ZXIsIElNb2R1bGVbXSBhZGQsIElNb2R1bGVbXSByZW1vdmUsIElQcm9ncmVzc01vbml0b3IgbW9uaXRvcikgdGhyb3dzIENvcmVFeGNlcHRpb24gewoJCWlmIChzZXJ2ZXIgPT0gbnVsbCkKCQkJdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwoJCQoJCWlmIChhZGQgPT0gbnVsbCkKCQkJYWRkID0gbmV3IElNb2R1bGVbMF07CgkJaWYgKHJlbW92ZSA9PSBudWxsKQoJCQlyZW1vdmUgPSBuZXcgSU1vZHVsZVswXTsKCQkKCQlpbnQgc2l6ZSA9IGFkZC5sZW5ndGg7CgkJTGlzdCBhZGRQYXJlbnRNb2R1bGVzID0gbmV3IEFycmF5TGlzdCgpOwoJCWZvciAoaW50IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKSB7CgkJCWJvb2xlYW4gZm91bmQgPSBmYWxzZTsKCQkJdHJ5IHsKCQkJCUlNb2R1bGVbXSBwYXJlbnRzID0gc2VydmVyLmdldFJvb3RNb2R1bGVzKGFkZFtpXSwgbW9uaXRvcik7CgkJCQlpZiAocGFyZW50cyAhPSBudWxsKSB7CgkJCQkJZm91bmQgPSB0cnVlOwoJCQkJCWlmIChwYXJlbnRzLmxlbmd0aCA+IDApIHsJCQkJCgkJCQkJCU9iamVjdCBwYXJlbnQgPSBwYXJlbnRzWzBdOwoJCQkJCQlmb3VuZCA9IHRydWU7CgkJCQkJCWlmICghYWRkUGFyZW50TW9kdWxlcy5jb250YWlucyhwYXJlbnQpKQoJCQkJCQkJYWRkUGFyZW50TW9kdWxlcy5hZGQocGFyZW50KTsKCQkJCQl9CgkJCQl9IAoJCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkJVHJhY2UudHJhY2UoVHJhY2UuV0FSTklORywgIkNvdWxkIG5vdCBmaW5kIHBhcmVudCBtb2R1bGUiLCBlKTsKCQkJfQoJCQkKCQkJaWYgKCFmb3VuZCkKCQkJCWFkZFBhcmVudE1vZHVsZXMuYWRkKGFkZFtpXSk7CgkJfQoJCQoJCXNpemUgPSByZW1vdmUubGVuZ3RoOwoJCUxpc3QgcmVtb3ZlUGFyZW50TW9kdWxlcyA9IG5ldyBBcnJheUxpc3QoKTsKCQlmb3IgKGludCBpID0gMDsgaSA8IHNpemU7IGkrKykgewoJCQlib29sZWFuIGZvdW5kID0gZmFsc2U7CgkJCXRyeSB7CgkJCQlJTW9kdWxlW10gcGFyZW50cyA9IHNlcnZlci5nZXRSb290TW9kdWxlcyhyZW1vdmVbaV0sIG1vbml0b3IpOwoJCQkJaWYgKHBhcmVudHMgIT0gbnVsbCkgewoJCQkJCWZvdW5kID0gdHJ1ZTsKCQkJCQlpZiAocGFyZW50cy5sZW5ndGggPiAwKSB7CQkJCQoJCQkJCQlPYmplY3QgcGFyZW50ID0gcGFyZW50c1swXTsKCQkJCQkJZm91bmQgPSB0cnVlOwoJCQkJCQlpZiAoIXJlbW92ZVBhcmVudE1vZHVsZXMuY29udGFpbnMocGFyZW50KSkKCQkJCQkJCXJlbW92ZVBhcmVudE1vZHVsZXMuYWRkKHBhcmVudCk7CgkJCQkJfQoJCQkJfSAKCQkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJCVRyYWNlLnRyYWNlKFRyYWNlLldBUk5JTkcsICJDb3VsZCBub3QgZmluZCBwYXJlbnQgbW9kdWxlIDIiLCBlKTsKCQkJfQoJCQkKCQkJaWYgKCFmb3VuZCkKCQkJCXJlbW92ZVBhcmVudE1vZHVsZXMuYWRkKHJlbW92ZVtpXSk7CgkJfQoJCQoJCUlNb2R1bGVbXSBhZGQyID0gbmV3IElNb2R1bGVbYWRkUGFyZW50TW9kdWxlcy5zaXplKCldOwoJCWFkZFBhcmVudE1vZHVsZXMudG9BcnJheShhZGQyKTsKCQlJTW9kdWxlW10gcmVtb3ZlMiA9IG5ldyBJTW9kdWxlW3JlbW92ZVBhcmVudE1vZHVsZXMuc2l6ZSgpXTsKCQlyZW1vdmVQYXJlbnRNb2R1bGVzLnRvQXJyYXkocmVtb3ZlMik7CgkJCgkJc2VydmVyLm1vZGlmeU1vZHVsZXMoYWRkMiwgcmVtb3ZlMiwgbW9uaXRvcik7Cgl9CgoJLyoqCgkgKiBTZXRzIGEgZGVmYXVsdCBuYW1lIG9uIHRoZSBnaXZlbiBydW50aW1lLgoJICogCgkgKiBAcGFyYW0gcnVudGltZSBhIHJ1bnRpbWUKCSAqLwoJcHVibGljIHN0YXRpYyB2b2lkIHNldFJ1bnRpbWVEZWZhdWx0TmFtZShJUnVudGltZVdvcmtpbmdDb3B5IHJ1bnRpbWUpIHsKCQlTdHJpbmcgdHlwZU5hbWUgPSBydW50aW1lLmdldFJ1bnRpbWVUeXBlKCkuZ2V0TmFtZSgpOwoJCQoJCVN0cmluZyBuYW1lID0gU2VydmVyUGx1Z2luLmdldFJlc291cmNlKCIlZGVmYXVsdFJ1bnRpbWVOYW1lIiwgbmV3IFN0cmluZ1tdIHt0eXBlTmFtZX0pOwoJCWludCBpID0gMjsKCQl3aGlsZSAoaXNOYW1lSW5Vc2UobmFtZSkpIHsKCQkJbmFtZSA9IFNlcnZlclBsdWdpbi5nZXRSZXNvdXJjZSgiJWRlZmF1bHRSdW50aW1lTmFtZTIiLCBuZXcgU3RyaW5nW10ge3R5cGVOYW1lLCBpICsgIiJ9KTsKCQkJaSsrOwoJCX0KCQlydW50aW1lLnNldE5hbWUobmFtZSk7Cgl9CgoJLyoqCgkgKiBTZXRzIGEgZGVmYXVsdCBuYW1lIG9uIHRoZSBnaXZlbiBzZXJ2ZXIuCgkgKiAKCSAqIEBwYXJhbSBzZXJ2ZXIgYSBzZXJ2ZXIKCSAqLwoJcHVibGljIHN0YXRpYyB2b2lkIHNldFNlcnZlckRlZmF1bHROYW1lKElTZXJ2ZXJXb3JraW5nQ29weSBzZXJ2ZXIpIHsKCQlpZiAoc2VydmVyID09IG51bGwpCgkJCXRocm93IG5ldyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKCQkKCQlTdHJpbmcgdHlwZU5hbWUgPSBzZXJ2ZXIuZ2V0U2VydmVyVHlwZSgpLmdldE5hbWUoKTsKCQlTdHJpbmcgaG9zdCA9IHNlcnZlci5nZXRIb3N0KCk7CgkJCgkJU3RyaW5nIG5hbWUgPSBTZXJ2ZXJQbHVnaW4uZ2V0UmVzb3VyY2UoIiVkZWZhdWx0U2VydmVyTmFtZSIsIG5ldyBTdHJpbmdbXSB7dHlwZU5hbWUsIGhvc3R9KTsKCQlpbnQgaSA9IDI7CgkJd2hpbGUgKGlzTmFtZUluVXNlKG5hbWUpKSB7CgkJCW5hbWUgPSBTZXJ2ZXJQbHVnaW4uZ2V0UmVzb3VyY2UoIiVkZWZhdWx0U2VydmVyTmFtZTIiLCBuZXcgU3RyaW5nW10ge3R5cGVOYW1lLCBob3N0LCBpICsgIiJ9KTsKCQkJaSsrOwoJCX0KCQlzZXJ2ZXIuc2V0TmFtZShuYW1lKTsKCX0KCglwcml2YXRlIHN0YXRpYyBib29sZWFuIGlzVmFsaWRGaWxlbmFtZShTdHJpbmcgbmFtZSkgewoJCUlTdGF0dXMgc3RhdHVzID0gUmVzb3VyY2VzUGx1Z2luLmdldFdvcmtzcGFjZSgpLnZhbGlkYXRlTmFtZShuYW1lLCBJUmVzb3VyY2UuRklMRSk7CgkJaWYgKHN0YXR1cyAhPSBudWxsICYmICFzdGF0dXMuaXNPSygpKQoJCQlyZXR1cm4gZmFsc2U7CgkJCgkJc3RhdHVzID0gUmVzb3VyY2VzUGx1Z2luLmdldFdvcmtzcGFjZSgpLnZhbGlkYXRlTmFtZShuYW1lLCBJUmVzb3VyY2UuRk9MREVSKTsKCQlpZiAoc3RhdHVzICE9IG51bGwgJiYgIXN0YXR1cy5pc09LKCkpCgkJCXJldHVybiBmYWxzZTsKCQkKCQlyZXR1cm4gdHJ1ZTsKCX0KCglwcml2YXRlIHN0YXRpYyBTdHJpbmcgZ2V0VmFsaWRGaWxlTmFtZShTdHJpbmcgbmFtZSkgewoJCWlmIChpc1ZhbGlkRmlsZW5hbWUobmFtZSkpCgkJCXJldHVybiBuYW1lOwoJCgkJLy8gcmVtb3ZlIGludmFsaWQgY2hhcmFjdGVycwoJCVN0cmluZ1tdIHMgPSBuZXcgU3RyaW5nW10geyIuIiwgIlxcIiwgIi8iLCAiPyIsICI6IiwgIioiLCAiXCIiLCAifCIsICI8IiwgIj4ifTsKCQlpbnQgaW5kID0gMDsKCQl3aGlsZSAoaW5kIDwgcy5sZW5ndGgpIHsKCQkJaW50IGluZGV4ID0gbmFtZS5pbmRleE9mKHNbaW5kXSk7CgkJCXdoaWxlIChpbmRleCA+PSAwKSB7CgkJCQluYW1lID0gbmFtZS5zdWJzdHJpbmcoMCwgaW5kZXgpICsgbmFtZS5zdWJzdHJpbmcoaW5kZXgrMSk7CgkJCQlpbmRleCA9IG5hbWUuaW5kZXhPZihzW2luZF0pOwoJCQl9CgkJCWluZCsrOwoJCX0KCQlyZXR1cm4gbmFtZTsKCX0KCgkvKioKCSAqIFJldHVybnMgYW4gdW51c2VkIGZpbGUgaW4gdGhlIGdpdmVuIHByb2plY3QuCgkgKiAKCSAqIEBwYXJhbSBwcm9qZWN0IGEgcHJvamVjdAoJICogQHBhcmFtIHR5cGUgYSBzZXJ2ZXIgdHlwZQoJICogQHJldHVybiBhbiB1bnVzZWQgZmlsZSB3aXRoaW4gdGhlIGdpdmVuIHByb2plY3QKCSAqLwoJcHVibGljIHN0YXRpYyBJRmlsZSBnZXRVbnVzZWRTZXJ2ZXJGaWxlKElQcm9qZWN0IHByb2plY3QsIElTZXJ2ZXJUeXBlIHR5cGUpIHsKCQlpZiAocHJvamVjdCA9PSBudWxsIHx8IHR5cGUgPT0gbnVsbCkKCQkJdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwoJCQoJCVN0cmluZyB0eXBlTmFtZSA9IGdldFZhbGlkRmlsZU5hbWUodHlwZS5nZXROYW1lKCkpOwoJCVN0cmluZyBuYW1lID0gU2VydmVyUGx1Z2luLmdldFJlc291cmNlKCIlZGVmYXVsdFNlcnZlck5hbWUzIiwgbmV3IFN0cmluZ1tdIHt0eXBlTmFtZX0pKyAiLiIgICsgU2VydmVyLkZJTEVfRVhURU5TSU9OOwoJCWludCBpID0gMjsKCQl3aGlsZSAoaXNGaWxlTmFtZUluVXNlKHByb2plY3QsIG5hbWUpKSB7CgkJCW5hbWUgPSBTZXJ2ZXJQbHVnaW4uZ2V0UmVzb3VyY2UoIiVkZWZhdWx0U2VydmVyTmFtZTQiLCBuZXcgU3RyaW5nW10ge3R5cGVOYW1lLCBpICsgIiJ9KSArICIuIiAgKyBTZXJ2ZXIuRklMRV9FWFRFTlNJT047CgkJCWkrKzsKCQl9CgkJcmV0dXJuIHByb2plY3QuZ2V0RmlsZShuYW1lKTsKCX0KCgkvKioKCSAqIFJldHVybnMgdHJ1ZSBpZiBhIHNlcnZlciBvciBydW50aW1lIGV4aXN0cyB3aXRoIHRoZSBnaXZlbiBuYW1lLgoJICoKCSAqIEBwYXJhbSBuYW1lIGEgbmFtZQoJICogQHJldHVybiA8Y29kZT50cnVlPC9jb2RlPiBpZiB0aGUgbmFtZSBpcyBpbiB1c2UsIGFuZCA8Y29kZT5mYWxzZTwvY29kZT4KCSAqICAgIG90aGVyd2lzZQoJICovCglwcml2YXRlIHN0YXRpYyBib29sZWFuIGlzTmFtZUluVXNlKFN0cmluZyBuYW1lKSB7CgkJaWYgKG5hbWUgPT0gbnVsbCkKCQkJcmV0dXJuIHRydWU7CgkKCQlMaXN0IGxpc3QgPSBuZXcgQXJyYXlMaXN0KCk7CgkJCgkJYWRkQWxsKGxpc3QsIFNlcnZlckNvcmUuZ2V0UnVudGltZXMoKSk7CgkJYWRkQWxsKGxpc3QsIFNlcnZlckNvcmUuZ2V0U2VydmVycygpKTsKCgkJSXRlcmF0b3IgaXRlcmF0b3IgPSBsaXN0Lml0ZXJhdG9yKCk7CgkJd2hpbGUgKGl0ZXJhdG9yLmhhc05leHQoKSkgewoJCQlPYmplY3Qgb2JqID0gaXRlcmF0b3IubmV4dCgpOwoJCQlpZiAob2JqIGluc3RhbmNlb2YgSVNlcnZlckF0dHJpYnV0ZXMgJiYgbmFtZS5lcXVhbHNJZ25vcmVDYXNlKCgoSVNlcnZlckF0dHJpYnV0ZXMpb2JqKS5nZXROYW1lKCkpKQoJCQkJcmV0dXJuIHRydWU7CgkJCWlmIChvYmogaW5zdGFuY2VvZiBJUnVudGltZSAmJiBuYW1lLmVxdWFsc0lnbm9yZUNhc2UoKChJUnVudGltZSlvYmopLmdldE5hbWUoKSkpCgkJCQlyZXR1cm4gdHJ1ZTsKCQl9CgoJCXJldHVybiBmYWxzZTsKCX0KCQoJcHJpdmF0ZSBzdGF0aWMgdm9pZCBhZGRBbGwoTGlzdCBsaXN0LCBPYmplY3RbXSBvYmopIHsKCQlpZiAob2JqID09IG51bGwpCgkJCXJldHVybjsKCQkKCQlpbnQgc2l6ZSA9IG9iai5sZW5ndGg7CgkJZm9yIChpbnQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHsKCQkJbGlzdC5hZGQob2JqW2ldKTsKCQl9Cgl9CgkKCS8qKgoJICogUmV0dXJucyB0cnVlIGlmIGFuIGVsZW1lbnQgZXhpc3RzIHdpdGggdGhlIGdpdmVuIG5hbWUuCgkgKgoJICogQHBhcmFtIHByb2plY3QgYSBwcm9qZWN0CgkgKiBAcGFyYW0gbmFtZSBhIGZpbGUgb3IgZm9sZGVyIG5hbWUKCSAqIEByZXR1cm4gYm9vbGVhbiA8Y29kZT50cnVlPC9jb2RlPiBpZiB0aGUgZmlsZSBvciBmb2xkZXIgbmFtZSBpcyBiZWluZwoJICogICAgdXNlZCwgYW5kIDxjb2RlPmZhbHNlPC9jb2RlPiBvdGhlcndpc2UKCSAqLwoJcHJpdmF0ZSBzdGF0aWMgYm9vbGVhbiBpc0ZpbGVOYW1lSW5Vc2UoSVByb2plY3QgcHJvamVjdCwgU3RyaW5nIG5hbWUpIHsKCQlpZiAobmFtZSA9PSBudWxsIHx8IHByb2plY3QgPT0gbnVsbCkKCQkJcmV0dXJuIGZhbHNlOwoJCQoJCWlmIChwcm9qZWN0LmdldEZpbGUobmFtZSkuZXhpc3RzKCkpCgkJCXJldHVybiB0cnVlOwoJCWlmIChwcm9qZWN0LmdldEZvbGRlcihuYW1lKS5leGlzdHMoKSkKCQkJcmV0dXJuIHRydWU7CgkKCQlyZXR1cm4gZmFsc2U7Cgl9CgoJLyoqCgkgKiBSZXR1cm4gYSBsaXN0IG9mIGFsbCBydW50aW1lIHRhcmdldHMgdGhhdCBtYXRjaCB0aGUgZ2l2ZW4gdHlwZSBhbmQgdmVyc2lvbi4KCSAqIElmIHR5cGUgb3IgdmVyc2lvbiBpcyBudWxsLCBpdCBtYXRjaGVzIGFsbCBvZiB0aGF0IHR5cGUgb3IgdmVyc2lvbi4KCSAqIAoJICogQHBhcmFtIHR5cGUgYSBtb2R1bGUgdHlwZQoJICogQHBhcmFtIHZlcnNpb24gYSBtb2R1bGUgdmVyc2lvbgoJICogQHJldHVybiBhIHBvc3NpYmx5LWVtcHR5IGFycmF5IG9mIHJ1bnRpbWUgaW5zdGFuY2VzIHtAbGluayBJUnVudGltZX0KCSAqLwoJcHVibGljIHN0YXRpYyBJUnVudGltZVtdIGdldFJ1bnRpbWVzKFN0cmluZyB0eXBlLCBTdHJpbmcgdmVyc2lvbikgewoJCUxpc3QgbGlzdCA9IG5ldyBBcnJheUxpc3QoKTsKCQlJUnVudGltZVtdIHJ1bnRpbWVzID0gU2VydmVyQ29yZS5nZXRSdW50aW1lcygpOwoJCWlmIChydW50aW1lcyAhPSBudWxsKSB7CgkJCWludCBzaXplID0gcnVudGltZXMubGVuZ3RoOwoJCQlmb3IgKGludCBpID0gMDsgaSA8IHNpemU7IGkrKykgewoJCQkJSVJ1bnRpbWVUeXBlIHJ1bnRpbWVUeXBlID0gcnVudGltZXNbaV0uZ2V0UnVudGltZVR5cGUoKTsKCQkJCWlmIChydW50aW1lVHlwZSAhPSBudWxsICYmIGlzU3VwcG9ydGVkTW9kdWxlKHJ1bnRpbWVUeXBlLmdldE1vZHVsZVR5cGVzKCksIHR5cGUsIHZlcnNpb24pKSB7CgkJCQkJbGlzdC5hZGQocnVudGltZXNbaV0pOwoJCQkJfQoJCQl9CgkJfQoJCQoJCUlSdW50aW1lW10gcnVudGltZXMyID0gbmV3IElSdW50aW1lW2xpc3Quc2l6ZSgpXTsKCQlsaXN0LnRvQXJyYXkocnVudGltZXMyKTsKCQlyZXR1cm4gcnVudGltZXMyOwoJfQoKCS8qKgoJICogUmV0dXJuIGEgbGlzdCBvZiBhbGwgcnVudGltZSB0eXBlcyB0aGF0IG1hdGNoIHRoZSBnaXZlbiB0eXBlIGFuZCB2ZXJzaW9uLgoJICogSWYgdHlwZSBvciB2ZXJzaW9uIGlzIG51bGwsIGl0IG1hdGNoZXMgYWxsIG9mIHRoYXQgdHlwZSBvciB2ZXJzaW9uLgoJICogCgkgKiBAcGFyYW0gdHlwZSBhIG1vZHVsZSB0eXBlCgkgKiBAcGFyYW0gdmVyc2lvbiBhIG1vZHVsZSB2ZXJzaW9uCgkgKiBAcmV0dXJuIGEgcG9zc2libHktZW1wdHkgYXJyYXkgb2YgcnVudGltZSB0eXBlIGluc3RhbmNlcyB7QGxpbmsgSVJ1bnRpbWVUeXBlfQoJICovCglwdWJsaWMgc3RhdGljIElSdW50aW1lVHlwZVtdIGdldFJ1bnRpbWVUeXBlcyhTdHJpbmcgdHlwZSwgU3RyaW5nIHZlcnNpb24pIHsKCQlMaXN0IGxpc3QgPSBuZXcgQXJyYXlMaXN0KCk7CgkJSVJ1bnRpbWVUeXBlW10gcnVudGltZVR5cGVzID0gU2VydmVyQ29yZS5nZXRSdW50aW1lVHlwZXMoKTsKCQlpZiAocnVudGltZVR5cGVzICE9IG51bGwpIHsKCQkJaW50IHNpemUgPSBydW50aW1lVHlwZXMubGVuZ3RoOwoJCQlmb3IgKGludCBpID0gMDsgaSA8IHNpemU7IGkrKykgewoJCQkJaWYgKGlzU3VwcG9ydGVkTW9kdWxlKHJ1bnRpbWVUeXBlc1tpXS5nZXRNb2R1bGVUeXBlcygpLCB0eXBlLCB2ZXJzaW9uKSkgewoJCQkJCWxpc3QuYWRkKHJ1bnRpbWVUeXBlc1tpXSk7CgkJCQl9CgkJCX0KCQl9CgkJCgkJSVJ1bnRpbWVUeXBlW10gcnQgPSBuZXcgSVJ1bnRpbWVUeXBlW2xpc3Quc2l6ZSgpXTsKCQlsaXN0LnRvQXJyYXkocnQpOwoJCXJldHVybiBydDsKCX0KCQoJLyoqCgkgKiBSZXR1cm4gYSBsaXN0IG9mIGFsbCBydW50aW1lIHR5cGVzIHRoYXQgbWF0Y2ggdGhlIGdpdmVuIHR5cGUsIHZlcnNpb24sCgkgKiBhbmQgcGFydGlhbCBydW50aW1lIHR5cGUgaWQuIElmIHR5cGUsIHZlcnNpb24sIG9yIHJ1bnRpbWVUeXBlSWQgaXMgbnVsbCwKCSAqIGl0IG1hdGNoZXMgYWxsIG9mIHRoYXQgdHlwZSBvciB2ZXJzaW9uLgoJICogCgkgKiBAcGFyYW0gdHlwZSBhIG1vZHVsZSB0eXBlCgkgKiBAcGFyYW0gdmVyc2lvbiBhIG1vZHVsZSB2ZXJzaW9uCgkgKiBAcGFyYW0gcnVudGltZVR5cGVJZCB0aGUgaWQgb2YgYSBydW50aW1lIHR5cGUKCSAqIEByZXR1cm4gYSBwb3NzaWJseS1lbXB0eSBhcnJheSBvZiBydW50aW1lIHR5cGUgaW5zdGFuY2VzIHtAbGluayBJUnVudGltZVR5cGV9CgkgKi8KCXB1YmxpYyBzdGF0aWMgSVJ1bnRpbWVUeXBlW10gZ2V0UnVudGltZVR5cGVzKFN0cmluZyB0eXBlLCBTdHJpbmcgdmVyc2lvbiwgU3RyaW5nIHJ1bnRpbWVUeXBlSWQpIHsKCQlMaXN0IGxpc3QgPSBuZXcgQXJyYXlMaXN0KCk7CgkJSVJ1bnRpbWVUeXBlW10gcnVudGltZVR5cGVzID0gU2VydmVyQ29yZS5nZXRSdW50aW1lVHlwZXMoKTsKCQlpZiAocnVudGltZVR5cGVzICE9IG51bGwpIHsKCQkJaW50IHNpemUgPSBydW50aW1lVHlwZXMubGVuZ3RoOwoJCQlmb3IgKGludCBpID0gMDsgaSA8IHNpemU7IGkrKykgewoJCQkJaWYgKGlzU3VwcG9ydGVkTW9kdWxlKHJ1bnRpbWVUeXBlc1tpXS5nZXRNb2R1bGVUeXBlcygpLCB0eXBlLCB2ZXJzaW9uKSkgewoJCQkJCWlmIChydW50aW1lVHlwZUlkID09IG51bGwgfHwgcnVudGltZVR5cGVzW2ldLmdldElkKCkuc3RhcnRzV2l0aChydW50aW1lVHlwZUlkKSkKCQkJCQkJbGlzdC5hZGQocnVudGltZVR5cGVzW2ldKTsKCQkJCX0KCQkJfQoJCX0KCQkKCQlJUnVudGltZVR5cGVbXSBydCA9IG5ldyBJUnVudGltZVR5cGVbbGlzdC5zaXplKCldOwoJCWxpc3QudG9BcnJheShydCk7CgkJcmV0dXJuIHJ0OwoJfQoKCS8qKgoJICogUmV0dXJucyBhIGxpc3Qgb2YgYWxsIHNlcnZlcnMgdGhhdCB0aGlzIGRlcGxveWFibGUgaXMgbm90IGN1cnJlbnRseQoJICogY29uZmlndXJlZCBvbiwgYnV0IGNvdWxkIGJlIGFkZGVkIHRvLiBJZiBpbmNsdWRlRXJyb3JzIGlzIHRydWUsIHRoaXMKCSAqIG1ldGhvZCByZXR1cm4gc2VydmVycyB3aGVyZSB0aGUgcGFyZW50IGRlcGxveWFibGUgbWF5IHRocm93IGVycm9ycy4gRm9yCgkgKiBpbnN0YW5jZSwgdGhpcyBkZXBsb3lhYmxlIG1heSBiZSB0aGUgd3Jvbmcgc3BlYyBsZXZlbC4KCSAqCgkgKiBAcGFyYW0gbW9kdWxlIGEgbW9kdWxlCgkgKiBAcGFyYW0gaW5jbHVkZUVycm9ycyA8Y29kZT50cnVlPC9jb2RlPiB0byBpbmNsdWRlIHNlcnZlcnMgdGhhdCByZXR1cm5lZAoJICogICAgZXJyb3JzIHdoZW4gdHJ5aW5nIHRvIGFkZCB0aGUgbW9kdWxlLCBhbmQgPGNvZGU+ZmFsc2U8L2NvZGU+IG90aGVyd2lzZQoJICogQHBhcmFtIG1vbml0b3IgYSBwcm9ncmVzcyBtb25pdG9yLCBvciA8Y29kZT5udWxsPC9jb2RlPiBpZiBwcm9ncmVzcwoJICogICAgcmVwb3J0aW5nIGFuZCBjYW5jZWxsYXRpb24gYXJlIG5vdCBkZXNpcmVkCgkgKiBAcmV0dXJuIGEgcG9zc2libHkgZW1wdHkgYXJyYXkgb2Ygc2VydmVycwoJICovCglwdWJsaWMgc3RhdGljIElTZXJ2ZXJbXSBnZXRBdmFpbGFibGVTZXJ2ZXJzRm9yTW9kdWxlKElNb2R1bGUgbW9kdWxlLCBib29sZWFuIGluY2x1ZGVFcnJvcnMsIElQcm9ncmVzc01vbml0b3IgbW9uaXRvcikgewoJCWlmIChtb2R1bGUgPT0gbnVsbCkKCQkJcmV0dXJuIG5ldyBJU2VydmVyWzBdOwoKCQkvLyBkbyBpdCB0aGUgc2xvdyB3YXkgLSBnbyB0aHJvdWdoIGFsbCBzZXJ2ZXJzIGFuZAoJCS8vIHNlZSBpZiB0aGlzIGRlcGxveWFibGUgaXMgbm90IGNvbmZpZ3VyZWQgaW4gaXQKCQkvLyBidXQgY291bGQgYmUgYWRkZWQKCQlMaXN0IGxpc3QgPSBuZXcgQXJyYXlMaXN0KCk7CgkJSVNlcnZlcltdIHNlcnZlcnMgPSBTZXJ2ZXJDb3JlLmdldFNlcnZlcnMoKTsKCQlpZiAoc2VydmVycyAhPSBudWxsKSB7CgkJCWludCBzaXplID0gc2VydmVycy5sZW5ndGg7CgkJCWZvciAoaW50IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKSB7CgkJCQlpZiAoIWNvbnRhaW5zTW9kdWxlKHNlcnZlcnNbaV0sIG1vZHVsZSwgbW9uaXRvcikpIHsKCQkJCQl0cnkgewoJCQkJCQlJTW9kdWxlW10gcGFyZW50cyA9IHNlcnZlcnNbaV0uZ2V0Um9vdE1vZHVsZXMobW9kdWxlLCBtb25pdG9yKTsKCQkJCQkJaWYgKHBhcmVudHMgIT0gbnVsbCAmJiBwYXJlbnRzLmxlbmd0aCA+IDApIHsKCQkJCQkJCWJvb2xlYW4gZm91bmQgPSBmYWxzZTsKCQkJCQkJCWlmIChwYXJlbnRzICE9IG51bGwpIHsKCQkJCQkJCQlpbnQgc2l6ZTIgPSBwYXJlbnRzLmxlbmd0aDsKCQkJCQkJCQlmb3IgKGludCBqID0gMDsgIWZvdW5kICYmIGogPCBzaXplMjsgaisrKSB7CgkJCQkJCQkJCUlNb2R1bGUgcGFyZW50ID0gcGFyZW50c1tqXTsKCQkJCQkJCQkJSVN0YXR1cyBzdGF0dXMgPSBzZXJ2ZXJzW2ldLmNhbk1vZGlmeU1vZHVsZXMobmV3IElNb2R1bGVbXSB7IHBhcmVudCB9LCBuZXcgSU1vZHVsZVswXSwgbW9uaXRvcik7CgkJCQkJCQkJCWlmIChzdGF0dXMgPT0gbnVsbCB8fCBzdGF0dXMuaXNPSygpKXsKCQkJCQkJCQkJCWxpc3QuYWRkKHNlcnZlcnNbaV0pOwoJCQkJCQkJCQkJZm91bmQgPSB0cnVlOwoJCQkJCQkJCQl9CgkJCQkJCQkJfQoJCQkJCQkJfQoJCQkJCQl9CgkJCQkJfSBjYXRjaCAoRXhjZXB0aW9uIHNlKSB7CgkJCQkJCWlmIChpbmNsdWRlRXJyb3JzKQoJCQkJCQkJbGlzdC5hZGQoc2VydmVyc1tpXSk7CgkJCQkJfQoJCQkJfQoJCQl9CgkJfQoJCQoJCS8vIG1ha2Ugc3VyZSB0aGF0IHRoZSBwcmVmZXJyZWQgc2VydmVyIGlzIHRoZSBmaXJzdCBvbmUKCQkvL0lTZXJ2ZXIgc2VydmVyID0gU2VydmVyQ29yZS5nZXRTZXJ2ZXJQcmVmZXJlbmNlcygpLmdldERlcGxveWFibGVTZXJ2ZXJQcmVmZXJlbmNlKGRlcGxveWFibGUpOwoJCS8vaWYgKHNlcnZlciAhPSBudWxsICYmIGxpc3QuY29udGFpbnMoc2VydmVyKSAmJiBsaXN0LmluZGV4T2Yoc2VydmVyKSAhPSAwKSB7CgkJLy8JbGlzdC5yZW1vdmUoc2VydmVyKTsKCQkvLwlsaXN0LmFkZCgwLCBzZXJ2ZXIpOwoJCS8vfQoKCQlJU2VydmVyW10gYWxsU2VydmVycyA9IG5ldyBJU2VydmVyW2xpc3Quc2l6ZSgpXTsKCQlsaXN0LnRvQXJyYXkoYWxsU2VydmVycyk7CgkJcmV0dXJuIGFsbFNlcnZlcnM7Cgl9CgoJLyoqCgkgKiBSZXR1cm5zIGEgbGlzdCBvZiBhbGwgc2VydmVycyB0aGF0IHRoaXMgbW9kdWxlIGlzIGNvbmZpZ3VyZWQgb24uCgkgKiAKCSAqIEBwYXJhbSBtb2R1bGUgYSBtb2R1bGUKCSAqIEBwYXJhbSBtb25pdG9yIGEgcHJvZ3Jlc3MgbW9uaXRvciwgb3IgPGNvZGU+bnVsbDwvY29kZT4gaWYgcHJvZ3Jlc3MKCSAqICAgIHJlcG9ydGluZyBhbmQgY2FuY2VsbGF0aW9uIGFyZSBub3QgZGVzaXJlZAoJICogQHJldHVybiBhIHBvc3NpYmx5LWVtcHR5IGFycmF5IG9mIHNlcnZlciBpbnN0YW5jZXMge0BsaW5rIElTZXJ2ZXJ9CgkgKi8KCXB1YmxpYyBzdGF0aWMgSVNlcnZlcltdIGdldFNlcnZlcnNCeU1vZHVsZShJTW9kdWxlIG1vZHVsZSwgSVByb2dyZXNzTW9uaXRvciBtb25pdG9yKSB7CgkJaWYgKG1vZHVsZSA9PSBudWxsKQoJCQlyZXR1cm4gbmV3IElTZXJ2ZXJbMF07CgoJCS8vIGRvIGl0IHRoZSBzbG93IHdheSAtIGdvIHRocm91Z2ggYWxsIHNlcnZlcnMgYW5kCgkJLy8gc2VlIGlmIHRoaXMgbW9kdWxlIGlzIGNvbmZpZ3VyZWQgaW4gaXQKCQlMaXN0IGxpc3QgPSBuZXcgQXJyYXlMaXN0KCk7CgkJSVNlcnZlcltdIHNlcnZlcnMgPSBTZXJ2ZXJDb3JlLmdldFNlcnZlcnMoKTsKCQlpZiAoc2VydmVycyAhPSBudWxsKSB7CgkJCWludCBzaXplID0gc2VydmVycy5sZW5ndGg7CgkJCWZvciAoaW50IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKSB7CgkJCQlpZiAoY29udGFpbnNNb2R1bGUoc2VydmVyc1tpXSwgbW9kdWxlLCBtb25pdG9yKSkKCQkJCQlsaXN0LmFkZChzZXJ2ZXJzW2ldKTsKCQkJfQoJCX0KCQkKCQlJU2VydmVyW10gYWxsU2VydmVycyA9IG5ldyBJU2VydmVyW2xpc3Quc2l6ZSgpXTsKCQlsaXN0LnRvQXJyYXkoYWxsU2VydmVycyk7CgkJcmV0dXJuIGFsbFNlcnZlcnM7Cgl9CgoJLyoqCgkgKiBSZXR1cm5zIHRydWUgaWYgdGhlIGdpdmVuIHNlcnZlciBjdXJyZW50bHkgY29udGFpbnMgdGhlIGdpdmVuIG1vZHVsZS4KCSAqCgkgKiBAcGFyYW0gc2VydmVyIGEgc2VydmVyCgkgKiBAcGFyYW0gbW9kdWxlIGEgbW9kdWxlCgkgKiBAcGFyYW0gbW9uaXRvciBhIHByb2dyZXNzIG1vbml0b3IsIG9yIDxjb2RlPm51bGw8L2NvZGU+IGlmIHByb2dyZXNzCgkgKiAgICByZXBvcnRpbmcgYW5kIGNhbmNlbGxhdGlvbiBhcmUgbm90IGRlc2lyZWQKCSAqIEByZXR1cm4gYm9vbGVhbiA8Y29kZT50cnVlPC9jb2RlPiBpZiB0aGUgbW9kdWxlIGlzIGNvbnRhaW5lZCBvbiB0aGUgc2VydmVyLAoJICogICAgb3IgPGNvZGU+ZmFsc2U8L2NvZGU+IG90aGVyd2lzZQoJICovCglwdWJsaWMgc3RhdGljIGJvb2xlYW4gY29udGFpbnNNb2R1bGUoSVNlcnZlciBzZXJ2ZXIsIGZpbmFsIElNb2R1bGUgbW9kdWxlLCBJUHJvZ3Jlc3NNb25pdG9yIG1vbml0b3IpIHsKCQlpZiAoc2VydmVyID09IG51bGwpCgkJCXJldHVybiBmYWxzZTsKCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICJjb250YWluc01vZHVsZSgpICIgKyBzZXJ2ZXIgKyAiICIgKyBtb2R1bGUpOwoJCQoJCWNsYXNzIEhlbHBlciB7CgkJCWJvb2xlYW4gYjsKCQl9CgkJZmluYWwgSGVscGVyIGggPSBuZXcgSGVscGVyKCk7CgoJCSgoU2VydmVyKXNlcnZlcikudmlzaXQobmV3IElNb2R1bGVWaXNpdG9yKCkgewoJCQlwdWJsaWMgYm9vbGVhbiB2aXNpdChJTW9kdWxlW10gbW9kdWxlcykgewoJCQkJaW50IHNpemUgPSBtb2R1bGVzLmxlbmd0aDsKCQkJCWlmIChtb2R1bGVzW3NpemUgLSAxXS5lcXVhbHMobW9kdWxlKSkgewoJCQkJCWguYiA9IHRydWU7CgkJCQkJcmV0dXJuIGZhbHNlOwoJCQkJfQoJCQkJcmV0dXJuIHRydWU7CgkJCX0KCQl9LCBudWxsKTsKCQlyZXR1cm4gaC5iOwoJfQoKCS8qKgoJICogUmV0dXJucyB0aGUgc2VydmVyIGFzc29jaWF0ZWQgd2l0aCB0aGUgZ2l2ZW4gbGF1bmNoIGNvbmZpZ3VyYXRpb24uCgkgKiAKCSAqIEBwYXJhbSBjb25maWd1cmF0aW9uIGEgbGF1bmNoIGNvbmZpZ3VyYXRpb24KCSAqIEByZXR1cm4gdGhlIHNlcnZlciBhc3NvY2lhdGVkIHdpdGggdGhlIGxhdW5jaCBjb25maWd1cmF0aW9uLCBvcgoJICogICAgPGNvZGU+bnVsbDwvY29kZT4gaWYgbm8gc2VydmVyIGNvdWxkIGJlIGZvdW5kCgkgKiBAdGhyb3dzIENvcmVFeGNlcHRpb24gaWYgdGhlcmUgaXMgYSBwcm9ibGVtIGdldHRpbmcgdGhlIGF0dHJpYnV0ZSBmcm9tCgkgKiAgICB0aGUgbGF1bmNoIGNvbmZpZ3VyYXRpb24KCSAqLwoJcHVibGljIHN0YXRpYyBJU2VydmVyIGdldFNlcnZlcihJTGF1bmNoQ29uZmlndXJhdGlvbiBjb25maWd1cmF0aW9uKSB0aHJvd3MgQ29yZUV4Y2VwdGlvbiB7CgkJU3RyaW5nIHNlcnZlcklkID0gY29uZmlndXJhdGlvbi5nZXRBdHRyaWJ1dGUoU2VydmVyLkFUVFJfU0VSVkVSX0lELCAoU3RyaW5nKSBudWxsKTsKCgkJaWYgKHNlcnZlcklkICE9IG51bGwpCgkJCXJldHVybiBTZXJ2ZXJDb3JlLmZpbmRTZXJ2ZXIoc2VydmVySWQpOwoJCXJldHVybiBudWxsOwoJfQoKCS8qKgoJICogVmFsaWRhdGVzIHdoZXRoZXIgdGhpcyBzZXJ2ZXIgY2FuIGJlIGVkaXR0ZWQuCgkgKiAKCSAqIEBwYXJhbSBjb250ZXh0IHRoZSBjb250ZXh0IChTaGVsbCkKCSAqIEBwYXJhbSBzZXJ2ZXIgdGhlIHNlcnZlcgoJICogQHJldHVybiBhIHN0YXR1cyBvYmplY3Qgd2l0aCBjb2RlIDxjb2RlPklTdGF0dXMuT0s8L2NvZGU+IGlmIHRoZSBzZXJ2ZXIKCSAqICAgY2FuIGJlIGVkaXRlZCwgb3RoZXJ3aXNlIGEgc3RhdHVzIG9iamVjdCBpbmRpY2F0aW5nIHdoYXQgd2hlbiB3cm9uZwoJICogICB3aXRoIHRoZSBjaGVja291dAoJICovCglwdWJsaWMgc3RhdGljIElTdGF0dXMgdmFsaWRhdGVFZGl0KE9iamVjdCBjb250ZXh0LCBJU2VydmVyIHNlcnZlcikgewoJCXJldHVybiAoKFNlcnZlcilzZXJ2ZXIpLnZhbGlkYXRlRWRpdChjb250ZXh0KTsKCX0KfQ==