LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogQ29weXJpZ2h0IChjKSAyMDAzLCAyMDA1IElCTSBDb3Jwb3JhdGlvbiBhbmQgb3RoZXJzLgogKiBBbGwgcmlnaHRzIHJlc2VydmVkLiBUaGlzIHByb2dyYW0gYW5kIHRoZSBhY2NvbXBhbnlpbmcgbWF0ZXJpYWxzCiAqIGFyZSBtYWRlIGF2YWlsYWJsZSB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEVjbGlwc2UgUHVibGljIExpY2Vuc2UgdjEuMAogKiB3aGljaCBhY2NvbXBhbmllcyB0aGlzIGRpc3RyaWJ1dGlvbiwgYW5kIGlzIGF2YWlsYWJsZSBhdAogKiBodHRwOi8vd3d3LmVjbGlwc2Uub3JnL2xlZ2FsL2VwbC12MTAuaHRtbAqgKiAKICogQ29udHJpYnV0b3JzOgogKiAgICAgSUJNIENvcnBvcmF0aW9uIC0gSW5pdGlhbCBBUEkgYW5kIGltcGxlbWVudGF0aW9uCiAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLwpwYWNrYWdlIG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIuY29yZTsKCmltcG9ydCBqYXZhLnV0aWwuKjsKCmltcG9ydCBvcmcuZWNsaXBzZS5jb3JlLnJlc291cmNlcy4qOwppbXBvcnQgb3JnLmVjbGlwc2UuY29yZS5ydW50aW1lLkNvcmVFeGNlcHRpb247CmltcG9ydCBvcmcuZWNsaXBzZS5jb3JlLnJ1bnRpbWUuSVByb2dyZXNzTW9uaXRvcjsKaW1wb3J0IG9yZy5lY2xpcHNlLmNvcmUucnVudGltZS5JU3RhdHVzOwppbXBvcnQgb3JnLmVjbGlwc2UuZGVidWcuY29yZS5JTGF1bmNoQ29uZmlndXJhdGlvbjsKCmltcG9ydCBvcmcuZWNsaXBzZS5vc2dpLnV0aWwuTkxTOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNlcnZlci5jb3JlLmludGVybmFsLio7Ci8qKgogKiBTZXJ2ZXIgdXRpbGl0eSBtZXRob2RzLiBUaGVzZSBzdGF0aWMgbWV0aG9kcyBjYW4gYmUgdXNlZCB0byBwZXJmb3JtCiAqIGNvbW1vbiBvcGVyYXRpb25zIG9uIHNlcnZlciBhcnRpZmFjdHMuCiAqIAogKiBAcGxhbm5lZGZvciAxLjAKICovCnB1YmxpYyBjbGFzcyBTZXJ2ZXJVdGlsIHsKCS8qKgoJICogU3RhdGljIHV0aWxpdHkgY2xhc3MgLSBjYW5ub3QgY3JlYXRlIGFuIGluc3RhbmNlLgoJICovCglwcml2YXRlIFNlcnZlclV0aWwoKSB7CgkJLy8gZG8gbm90aGluZwoJfQoKCS8qKgoJICogUmV0dXJucyB0aGUgcHJvamVjdCBtb2R1bGVzIGF0dGFjaGVkIHRvIGEgcHJvamVjdC4KCSAqIAoJICogQHBhcmFtIHByb2plY3QgYSBwcm9qZWN0CgkgKiBAcmV0dXJuIGEgcG9zc2libHkgZW1wdHkgYXJyYXkgb2YgbW9kdWxlcwoJICovCglwdWJsaWMgc3RhdGljIElNb2R1bGUgZ2V0TW9kdWxlKElQcm9qZWN0IHByb2plY3QpIHsKCQlpZiAocHJvamVjdCA9PSBudWxsKQoJCQl0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7CgoJCUlNb2R1bGVbXSBtb2R1bGVzID0gZ2V0TW9kdWxlcygpOwoJCWlmIChtb2R1bGVzICE9IG51bGwpIHsKCQkJaW50IHNpemUgPSBtb2R1bGVzLmxlbmd0aDsKCQkJZm9yIChpbnQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHsKCQkJCWlmIChtb2R1bGVzW2ldICE9IG51bGwgJiYgcHJvamVjdC5lcXVhbHMobW9kdWxlc1tpXS5nZXRQcm9qZWN0KCkpKQoJCQkJCXJldHVybiBtb2R1bGVzW2ldOwoJCQl9CgkJfQoJCXJldHVybiBudWxsOwoJfQoKCS8qKgoJICogUmV0dXJucyBhIG1vZHVsZSBmcm9tIHRoZSBnaXZlbiBtb2R1bGVJZC4gVGhlIG1vZHVsZUlkIG11c3Qgbm90IGJlIG51bGwuCgkgKiAKCSAqIEBwYXJhbSBtb2R1bGVJZCBhIG1vZHVsZSBpZAoJICogQHJldHVybiB0aGUgbW9kdWxlLCBvciA8Y29kZT5udWxsPC9jb2RlPiBpZiB0aGUgbW9kdWxlIGNvdWxkIG5vdCBiZSBmb3VuZAoJICovCglwdWJsaWMgc3RhdGljIElNb2R1bGUgZ2V0TW9kdWxlKFN0cmluZyBtb2R1bGVJZCkgewoJCWlmIChtb2R1bGVJZCA9PSBudWxsKQoJCQl0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7CgkJCgkJaW50IGluZGV4ID0gbW9kdWxlSWQuaW5kZXhPZigiOiIpOwoJCWlmIChpbmRleCA8PSAwKQoJCQlyZXR1cm4gbnVsbDsKCQkKCQlTdHJpbmcgZmFjdG9yeUlkID0gbW9kdWxlSWQuc3Vic3RyaW5nKDAsIGluZGV4KTsKCQlNb2R1bGVGYWN0b3J5IG1vZHVsZUZhY3RvcnkgPSBTZXJ2ZXJQbHVnaW4uZmluZE1vZHVsZUZhY3RvcnkoZmFjdG9yeUlkKTsKCQlpZiAobW9kdWxlRmFjdG9yeSA9PSBudWxsKQoJCQlyZXR1cm4gbnVsbDsKCgkJU3RyaW5nIG1vZHVsZVN1YklkID0gbW9kdWxlSWQuc3Vic3RyaW5nKGluZGV4KzEpOwoJCUlNb2R1bGUgbW9kdWxlID0gbW9kdWxlRmFjdG9yeS5nZXRNb2R1bGUobW9kdWxlU3ViSWQpOwoJCWlmIChtb2R1bGUgIT0gbnVsbCkKCQkJcmV0dXJuIG1vZHVsZTsKCQlyZXR1cm4gbnVsbDsKCX0KCgkvKioKCSAqIFJldHVybiBhbGwgdGhlIGF2YWlsYWJsZSBtb2R1bGVzIGZyb20gYWxsIGZhY3RvcmllcyB3aG9zZQoJICogdHlwZSBtYXRjaGVzIHRoZSBnaXZlbiBtb2R1bGUgdHlwZXMuCgkgKiAKCSAqIEBwYXJhbSBtb2R1bGVUeXBlcyBhbiBhcnJheSBvZiBtb2R1bGUgdHlwZXMKCSAqIEByZXR1cm4gYSBwb3NzaWJseSBlbXB0eSBhcnJheSBvZiBtb2R1bGVzCgkgKi8KCXB1YmxpYyBzdGF0aWMgSU1vZHVsZVtdIGdldE1vZHVsZXMoSU1vZHVsZVR5cGVbXSBtb2R1bGVUeXBlcykgewoJCUxpc3QgbGlzdCA9IG5ldyBBcnJheUxpc3QoKTsKCgkJTW9kdWxlRmFjdG9yeVtdIGZhY3RvcmllcyA9IFNlcnZlclBsdWdpbi5nZXRNb2R1bGVGYWN0b3JpZXMoKTsKCQlpZiAoZmFjdG9yaWVzICE9IG51bGwpIHsKCQkJaW50IHNpemUgPSBmYWN0b3JpZXMubGVuZ3RoOwoJCQlmb3IgKGludCBpID0gMDsgaSA8IHNpemU7IGkrKykgewoJCQkJaWYgKGlzU3VwcG9ydGVkTW9kdWxlKGZhY3Rvcmllc1tpXS5nZXRNb2R1bGVUeXBlcygpLCBtb2R1bGVUeXBlcykpIHsKCQkJCQlJTW9kdWxlW10gbW9kdWxlcyA9IGZhY3Rvcmllc1tpXS5nZXRNb2R1bGVzKCk7CgkJCQkJaWYgKG1vZHVsZXMgIT0gbnVsbCkgewoJCQkJCQlpbnQgc2l6ZTIgPSBtb2R1bGVzLmxlbmd0aDsKCQkJCQkJZm9yIChpbnQgaiA9IDA7IGogPCBzaXplMjsgaisrKQoJCQkJCQkJbGlzdC5hZGQobW9kdWxlc1tqXSk7CgkJCQkJfQoJCQkJfQoJCQl9CgkJfQoJCUlNb2R1bGVbXSBtb2R1bGVzID0gbmV3IElNb2R1bGVbbGlzdC5zaXplKCldOwoJCWxpc3QudG9BcnJheShtb2R1bGVzKTsKCQlyZXR1cm4gbW9kdWxlczsKCX0KCQoJLyoqCgkgKiBSZXR1cm4gYWxsIHRoZSBhdmFpbGFibGUgbW9kdWxlcyBmcm9tIGFsbCBmYWN0b3JpZXMgd2hvc2UKCSAqIHR5cGUgbWF0Y2hlcyB0aGUgZ2l2ZW4gbW9kdWxlIHR5cGUgaWQuCgkgKiAKCSAqIEBwYXJhbSB0eXBlIGEgbW9kdWxlIHR5cGUKCSAqIEByZXR1cm4gYSBwb3NzaWJseSBlbXB0eSBhcnJheSBvZiBtb2R1bGVzCgkgKi8KCXB1YmxpYyBzdGF0aWMgSU1vZHVsZVtdIGdldE1vZHVsZXMoU3RyaW5nIHR5cGUpIHsKCQlMaXN0IGxpc3QgPSBuZXcgQXJyYXlMaXN0KCk7CgoJCU1vZHVsZUZhY3RvcnlbXSBmYWN0b3JpZXMgPSBTZXJ2ZXJQbHVnaW4uZ2V0TW9kdWxlRmFjdG9yaWVzKCk7CgkJaWYgKGZhY3RvcmllcyAhPSBudWxsKSB7CgkJCWludCBzaXplID0gZmFjdG9yaWVzLmxlbmd0aDsKCQkJZm9yIChpbnQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHsKCQkJCWlmIChpc1N1cHBvcnRlZE1vZHVsZShmYWN0b3JpZXNbaV0uZ2V0TW9kdWxlVHlwZXMoKSwgdHlwZSwgbnVsbCkpIHsKCQkJCQlJTW9kdWxlW10gbW9kdWxlcyA9IGZhY3Rvcmllc1tpXS5nZXRNb2R1bGVzKCk7CgkJCQkJaWYgKG1vZHVsZXMgIT0gbnVsbCkgewoJCQkJCQlpbnQgc2l6ZTIgPSBtb2R1bGVzLmxlbmd0aDsKCQkJCQkJZm9yIChpbnQgaiA9IDA7IGogPCBzaXplMjsgaisrKQoJCQkJCQkJaWYodHlwZS5lcXVhbHMobW9kdWxlc1tqXS5nZXRNb2R1bGVUeXBlKCkuZ2V0SWQoKSkpCgkJCQkJCQkJbGlzdC5hZGQobW9kdWxlc1tqXSk7CgkJCQkJfQoJCQkJfQoJCQl9CgkJfQoJCUlNb2R1bGVbXSBtb2R1bGVzID0gbmV3IElNb2R1bGVbbGlzdC5zaXplKCldOwoJCWxpc3QudG9BcnJheShtb2R1bGVzKTsKCQlyZXR1cm4gbW9kdWxlczsKCX0KCQoJLyoqCgkgKiBSZXR1cm5zIDxjb2RlPnRydWU8L2NvZGU+IGlmIGFueSBvZiB0aGUgZ2l2ZW4gbW9kdWxlVHlwZXMgaGF2ZSB0aGUgZ2l2ZW4KCSAqIG1vZHVsZSB0eXBlIGlkIGFuZCB2ZXJzaW9uIGlkLgoJICogCgkgKiBAcGFyYW0gbW9kdWxlVHlwZXMgYW4gYXJyYXkgb2YgbW9kdWxlIHR5cGVzCgkgKiBAcGFyYW0gdHlwZUlkIGEgbW9kdWxlIHR5cGUKCSAqIEBwYXJhbSB2ZXJzaW9uSWQgYSBtb2R1bGUgdmVyc2lvbgoJICogQHJldHVybiA8Y29kZT50cnVlPC9jb2RlPiBpZiB0aGUgbW9kdWxlIHR5cGUgaXMgc3VwcG9ydGVkLCBhbmQKCSAqICAgIDxjb2RlPmZhbHNlPC9jb2RlPiBvdGhlcndpc2UKCSAqLwoJcHVibGljIHN0YXRpYyBib29sZWFuIGlzU3VwcG9ydGVkTW9kdWxlKElNb2R1bGVUeXBlW10gbW9kdWxlVHlwZXMsIFN0cmluZyB0eXBlSWQsIFN0cmluZyB2ZXJzaW9uSWQpIHsKCQlpZiAobW9kdWxlVHlwZXMgIT0gbnVsbCkgewoJCQlpbnQgc2l6ZSA9IG1vZHVsZVR5cGVzLmxlbmd0aDsKCQkJZm9yIChpbnQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHsKCQkJCWlmIChpc1N1cHBvcnRlZE1vZHVsZShtb2R1bGVUeXBlc1tpXSwgdHlwZUlkLCB2ZXJzaW9uSWQpKQoJCQkJCXJldHVybiB0cnVlOwoJCQl9CgkJfQoJCXJldHVybiBmYWxzZTsKCX0KCglwcml2YXRlIHN0YXRpYyBib29sZWFuIGlzU3VwcG9ydGVkTW9kdWxlKElNb2R1bGVUeXBlW10gbW9kdWxlVHlwZXMsIElNb2R1bGVUeXBlW10gbXQpIHsKCQlpZiAobXQgIT0gbnVsbCkgewoJCQlpbnQgc2l6ZSA9IG10Lmxlbmd0aDsKCQkJZm9yIChpbnQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHsKCQkJCWlmIChpc1N1cHBvcnRlZE1vZHVsZShtb2R1bGVUeXBlcywgbXRbaV0pKQoJCQkJCXJldHVybiB0cnVlOwoJCQl9CgkJfQoJCXJldHVybiBmYWxzZTsKCX0KCgkvKioKCSAqIFJldHVybnMgPGNvZGU+dHJ1ZTwvY29kZT4gaWYgYW55IG9mIHRoZSBnaXZlbiBtb2R1bGVUeXBlcyBtYXRjaCB0aGUgZ2l2ZW4KCSAqIG1vZHVsZSB0eXBlLgoJICogCgkgKiBAcGFyYW0gbW9kdWxlVHlwZXMgYW4gYXJyYXkgb2YgbW9kdWxlcyB0eXBlcwoJICogQHBhcmFtIG10IGEgbW9kdWxlIHR5cGUKCSAqIEByZXR1cm4gPGNvZGU+dHJ1ZTwvY29kZT4gaWYgdGhlIG1vZHVsZSB0eXBlIGlzIHN1cHBvcnRlZCwgYW5kCgkgKiAgICA8Y29kZT5mYWxzZTwvY29kZT4gb3RoZXJ3aXNlCgkgKi8KCXB1YmxpYyBzdGF0aWMgYm9vbGVhbiBpc1N1cHBvcnRlZE1vZHVsZShJTW9kdWxlVHlwZVtdIG1vZHVsZVR5cGVzLCBJTW9kdWxlVHlwZSBtdCkgewoJCWlmIChtb2R1bGVUeXBlcyAhPSBudWxsKSB7CgkJCWludCBzaXplID0gbW9kdWxlVHlwZXMubGVuZ3RoOwoJCQlmb3IgKGludCBpID0gMDsgaSA8IHNpemU7IGkrKykgewoJCQkJaWYgKGlzU3VwcG9ydGVkTW9kdWxlKG1vZHVsZVR5cGVzW2ldLCBtdCkpCgkJCQkJcmV0dXJuIHRydWU7CgkJCX0KCQl9CgkJcmV0dXJuIGZhbHNlOwoJfQoJCglwcml2YXRlIHN0YXRpYyBib29sZWFuIGlzU3VwcG9ydGVkTW9kdWxlKElNb2R1bGVUeXBlIG1vZHVsZVR5cGUsIFN0cmluZyB0eXBlLCBTdHJpbmcgdmVyc2lvbikgewoJCVN0cmluZyB0eXBlMiA9IG1vZHVsZVR5cGUuZ2V0SWQoKTsKCQlpZiAobWF0Y2hlcyh0eXBlLCB0eXBlMikpIHsKCQkJU3RyaW5nIHZlcnNpb24yID0gbW9kdWxlVHlwZS5nZXRWZXJzaW9uKCk7CgkJCWlmIChtYXRjaGVzKHZlcnNpb24sIHZlcnNpb24yKSkKCQkJCXJldHVybiB0cnVlOwoJCX0KCQlyZXR1cm4gZmFsc2U7Cgl9CgoJLyoqCgkgKiBSZXR1cm5zIHRydWUgaWYgdGhlIHR3byBnaXZlbiBtb2R1bGUgdHlwZXMgYXJlIGNvbXBhdGlibGUuIFRoZSBtb2R1bGVUeXBlcyBtYXkgbm90CgkgKiBiZSBudWxsLgoJICogCgkgKiBAcGFyYW0gbW9kdWxlVHlwZSBhIG1vZHVsZSB0eXBlCgkgKiBAcGFyYW0gbXQgYSBtb2R1bGUgdHlwZQoJICogQHJldHVybiA8Y29kZT50cnVlPC9jb2RlPiBpZiB0aGUgbW9kdWxlIHR5cGUgaXMgc3VwcG9ydGVkLCBhbmQKCSAqICAgIDxjb2RlPmZhbHNlPC9jb2RlPiBvdGhlcndpc2UKCSAqLwoJcHVibGljIHN0YXRpYyBib29sZWFuIGlzU3VwcG9ydGVkTW9kdWxlKElNb2R1bGVUeXBlIG1vZHVsZVR5cGUsIElNb2R1bGVUeXBlIG10KSB7CgkJaWYgKG1vZHVsZVR5cGUgPT0gbnVsbCB8fCBtdCA9PSBudWxsKQoJCQl0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7CgkJCgkJU3RyaW5nIHR5cGUyID0gbW9kdWxlVHlwZS5nZXRJZCgpOwoJCWlmIChtYXRjaGVzKG10LmdldElkKCksIHR5cGUyKSkgewoJCQlTdHJpbmcgdmVyc2lvbjIgPSBtb2R1bGVUeXBlLmdldFZlcnNpb24oKTsKCQkJaWYgKG1hdGNoZXMobXQuZ2V0VmVyc2lvbigpLCB2ZXJzaW9uMikpCgkJCQlyZXR1cm4gdHJ1ZTsKCQl9CgkJcmV0dXJuIGZhbHNlOwoJfQoKCXByaXZhdGUgc3RhdGljIGJvb2xlYW4gbWF0Y2hlcyhTdHJpbmcgYSwgU3RyaW5nIGIpIHsKCQlpZiAoYSA9PSBudWxsIHx8IGIgPT0gbnVsbCB8fCAiKiIuZXF1YWxzKGEpIHx8ICIqIi5lcXVhbHMoYikgfHwgYS5zdGFydHNXaXRoKGIpIHx8IGIuc3RhcnRzV2l0aChhKQoJCQl8fCAoYS5lbmRzV2l0aCgiLioiKSAmJiBiLnN0YXJ0c1dpdGgoYS5zdWJzdHJpbmcoMCwgYS5sZW5ndGgoKSAtIDEpKSkKCQkJfHwgKGIuZW5kc1dpdGgoIi4qIikgJiYgYS5zdGFydHNXaXRoKGIuc3Vic3RyaW5nKDAsIGIubGVuZ3RoKCkgLSAxKSkpKQoJCQlyZXR1cm4gdHJ1ZTsKCQlyZXR1cm4gZmFsc2U7Cgl9CgoJLyoqCgkgKiBSZXR1cm4gYWxsIHRoZSBhdmFpbGFibGUgbW9kdWxlcyBmcm9tIGFsbCBmYWN0b3JpZXMuCgkgKiAKCSAqIEByZXR1cm4gYSBwb3NzaWJseSBlbXB0eSBhcnJheSBvZiBtb2R1bGVzCgkgKi8KCXByaXZhdGUgc3RhdGljIElNb2R1bGVbXSBnZXRNb2R1bGVzKCkgewoJCUxpc3QgbGlzdCA9IG5ldyBBcnJheUxpc3QoKTsKCQkKCQlNb2R1bGVGYWN0b3J5W10gZmFjdG9yaWVzID0gU2VydmVyUGx1Z2luLmdldE1vZHVsZUZhY3RvcmllcygpOwoJCWlmIChmYWN0b3JpZXMgIT0gbnVsbCkgewoJCQlpbnQgc2l6ZSA9IGZhY3Rvcmllcy5sZW5ndGg7CgkJCWZvciAoaW50IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKSB7CgkJCQlJTW9kdWxlW10gbW9kdWxlcyA9IGZhY3Rvcmllc1tpXS5nZXRNb2R1bGVzKCk7CgkJCQlpZiAobW9kdWxlcyAhPSBudWxsKSB7CgkJCQkJaW50IHNpemUyID0gbW9kdWxlcy5sZW5ndGg7CgkJCQkJZm9yIChpbnQgaiA9IDA7IGogPCBzaXplMjsgaisrKSB7CgkJCQkJCWlmICghbGlzdC5jb250YWlucyhtb2R1bGVzW2pdKSkKCQkJCQkJCWxpc3QuYWRkKG1vZHVsZXNbal0pOwoJCQkJCX0KCQkJCX0KCQkJfQoJCX0KCQlJTW9kdWxlW10gbW9kdWxlcyA9IG5ldyBJTW9kdWxlW2xpc3Quc2l6ZSgpXTsKCQlsaXN0LnRvQXJyYXkobW9kdWxlcyk7CgkJcmV0dXJuIG1vZHVsZXM7Cgl9CgoJLyoqCgkgKiBBZGRzIG9yIHJlbW92ZXMgbW9kdWxlcyBmcm9tIGEgc2VydmVyLiBXaWxsIHNlYXJjaCBmb3IgdGhlIGZpcnN0IHBhcmVudCBtb2R1bGUKCSAqIG9mIGVhY2ggbW9kdWxlIGFuZCBhZGQgaXQgdG8gdGhlIHNlcnZlciBpbnN0ZWFkLiBUaGlzIG1ldGhvZCB3aWxsIGhhbmRsZSBtdWx0aXBsZQoJICogbW9kdWxlcyBoYXZpbmcgdGhlIHNhbWUgcGFyZW50ICh0aGUgcGFyZW50IHdpbGwgb25seSBiZSBhZGRlZCBvbmNlKSwgYnV0IG1heSBub3QKCSAqIGhhbmRsZSB0aGUgY2FzZSB3aGVyZSB0aGUgc2FtZSBtb2R1bGUgb3IgcGFyZW50IGlzIGJlaW5nIGJvdGggYWRkZWQgYW5kIHJlbW92ZWQuCgkgKiAKCSAqIEBwYXJhbSBzZXJ2ZXIgYSBzZXJ2ZXIKCSAqIEBwYXJhbSBhZGQgYW4gYXJyYXkgb2YgbW9kdWxlcyB0byBhZGQsIG9yIDxjb2RlPm51bGw8L2NvZGU+IHRvIG5vdCBhZGQgYW55CgkgKiBAcGFyYW0gcmVtb3ZlIGFuIGFycmF5IG9mIG1vZHVsZXMgdG8gcmVtb3ZlLCBvciA8Y29kZT5udWxsPC9jb2RlPiB0byBub3QgcmVtb3ZlIGFueQoJICogQHBhcmFtIG1vbml0b3IgYSBwcm9ncmVzcyBtb25pdG9yLCBvciA8Y29kZT5udWxsPC9jb2RlPiBpZiBwcm9ncmVzcwoJICogICAgcmVwb3J0aW5nIGFuZCBjYW5jZWxsYXRpb24gYXJlIG5vdCBkZXNpcmVkCgkgKiBAdGhyb3dzIENvcmVFeGNlcHRpb24KCSAqLwoJcHVibGljIHN0YXRpYyB2b2lkIG1vZGlmeU1vZHVsZXMoSVNlcnZlcldvcmtpbmdDb3B5IHNlcnZlciwgSU1vZHVsZVtdIGFkZCwgSU1vZHVsZVtdIHJlbW92ZSwgSVByb2dyZXNzTW9uaXRvciBtb25pdG9yKSB0aHJvd3MgQ29yZUV4Y2VwdGlvbiB7CgkJaWYgKHNlcnZlciA9PSBudWxsKQoJCQl0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCk7CgkJCgkJaWYgKGFkZCA9PSBudWxsKQoJCQlhZGQgPSBuZXcgSU1vZHVsZVswXTsKCQlpZiAocmVtb3ZlID09IG51bGwpCgkJCXJlbW92ZSA9IG5ldyBJTW9kdWxlWzBdOwoJCQoJCWludCBzaXplID0gYWRkLmxlbmd0aDsKCQlMaXN0IGFkZFBhcmVudE1vZHVsZXMgPSBuZXcgQXJyYXlMaXN0KCk7CgkJZm9yIChpbnQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHsKCQkJYm9vbGVhbiBmb3VuZCA9IGZhbHNlOwoJCQl0cnkgewoJCQkJSU1vZHVsZVtdIHBhcmVudHMgPSBzZXJ2ZXIuZ2V0Um9vdE1vZHVsZXMoYWRkW2ldLCBtb25pdG9yKTsKCQkJCWlmIChwYXJlbnRzICE9IG51bGwpIHsKCQkJCQlmb3VuZCA9IHRydWU7CgkJCQkJaWYgKHBhcmVudHMubGVuZ3RoID4gMCkgewkJCQkKCQkJCQkJT2JqZWN0IHBhcmVudCA9IHBhcmVudHNbMF07CgkJCQkJCWZvdW5kID0gdHJ1ZTsKCQkJCQkJaWYgKCFhZGRQYXJlbnRNb2R1bGVzLmNvbnRhaW5zKHBhcmVudCkpCgkJCQkJCQlhZGRQYXJlbnRNb2R1bGVzLmFkZChwYXJlbnQpOwoJCQkJCX0KCQkJCX0gCgkJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCQlUcmFjZS50cmFjZShUcmFjZS5XQVJOSU5HLCAiQ291bGQgbm90IGZpbmQgcGFyZW50IG1vZHVsZSIsIGUpOwoJCQl9CgkJCQoJCQlpZiAoIWZvdW5kKQoJCQkJYWRkUGFyZW50TW9kdWxlcy5hZGQoYWRkW2ldKTsKCQl9CgkJCgkJc2l6ZSA9IHJlbW92ZS5sZW5ndGg7CgkJTGlzdCByZW1vdmVQYXJlbnRNb2R1bGVzID0gbmV3IEFycmF5TGlzdCgpOwoJCWZvciAoaW50IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKSB7CgkJCWJvb2xlYW4gZm91bmQgPSBmYWxzZTsKCQkJdHJ5IHsKCQkJCUlNb2R1bGVbXSBwYXJlbnRzID0gc2VydmVyLmdldFJvb3RNb2R1bGVzKHJlbW92ZVtpXSwgbW9uaXRvcik7CgkJCQlpZiAocGFyZW50cyAhPSBudWxsKSB7CgkJCQkJZm91bmQgPSB0cnVlOwoJCQkJCWlmIChwYXJlbnRzLmxlbmd0aCA+IDApIHsJCQkJCgkJCQkJCU9iamVjdCBwYXJlbnQgPSBwYXJlbnRzWzBdOwoJCQkJCQlmb3VuZCA9IHRydWU7CgkJCQkJCWlmICghcmVtb3ZlUGFyZW50TW9kdWxlcy5jb250YWlucyhwYXJlbnQpKQoJCQkJCQkJcmVtb3ZlUGFyZW50TW9kdWxlcy5hZGQocGFyZW50KTsKCQkJCQl9CgkJCQl9IAoJCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkJVHJhY2UudHJhY2UoVHJhY2UuV0FSTklORywgIkNvdWxkIG5vdCBmaW5kIHBhcmVudCBtb2R1bGUgMiIsIGUpOwoJCQl9CgkJCQoJCQlpZiAoIWZvdW5kKQoJCQkJcmVtb3ZlUGFyZW50TW9kdWxlcy5hZGQocmVtb3ZlW2ldKTsKCQl9CgkJCgkJSU1vZHVsZVtdIGFkZDIgPSBuZXcgSU1vZHVsZVthZGRQYXJlbnRNb2R1bGVzLnNpemUoKV07CgkJYWRkUGFyZW50TW9kdWxlcy50b0FycmF5KGFkZDIpOwoJCUlNb2R1bGVbXSByZW1vdmUyID0gbmV3IElNb2R1bGVbcmVtb3ZlUGFyZW50TW9kdWxlcy5zaXplKCldOwoJCXJlbW92ZVBhcmVudE1vZHVsZXMudG9BcnJheShyZW1vdmUyKTsKCQkKCQlzZXJ2ZXIubW9kaWZ5TW9kdWxlcyhhZGQyLCByZW1vdmUyLCBtb25pdG9yKTsKCX0KCgkvKioKCSAqIFNldHMgYSBkZWZhdWx0IG5hbWUgb24gdGhlIGdpdmVuIHJ1bnRpbWUuCgkgKiAKCSAqIEBwYXJhbSBydW50aW1lIGEgcnVudGltZQoJICovCglwdWJsaWMgc3RhdGljIHZvaWQgc2V0UnVudGltZURlZmF1bHROYW1lKElSdW50aW1lV29ya2luZ0NvcHkgcnVudGltZSkgewoJCVN0cmluZyB0eXBlTmFtZSA9IHJ1bnRpbWUuZ2V0UnVudGltZVR5cGUoKS5nZXROYW1lKCk7CgkJCgkJU3RyaW5nIG5hbWUgPSBOTFMuYmluZChNZXNzYWdlcy5kZWZhdWx0UnVudGltZU5hbWUsIHR5cGVOYW1lKTsKCQlpbnQgaSA9IDI7CgkJd2hpbGUgKGlzTmFtZUluVXNlKG5hbWUpKSB7CgkJCW5hbWUgPSBOTFMuYmluZChNZXNzYWdlcy5kZWZhdWx0UnVudGltZU5hbWUyLCBuZXcgU3RyaW5nW10ge3R5cGVOYW1lLCBpICsgIiJ9KTsKCQkJaSsrOwoJCX0KCQlydW50aW1lLnNldE5hbWUobmFtZSk7Cgl9CgoJLyoqCgkgKiBTZXRzIGEgZGVmYXVsdCBuYW1lIG9uIHRoZSBnaXZlbiBzZXJ2ZXIuCgkgKiAKCSAqIEBwYXJhbSBzZXJ2ZXIgYSBzZXJ2ZXIKCSAqLwoJcHVibGljIHN0YXRpYyB2b2lkIHNldFNlcnZlckRlZmF1bHROYW1lKElTZXJ2ZXJXb3JraW5nQ29weSBzZXJ2ZXIpIHsKCQlpZiAoc2VydmVyID09IG51bGwpCgkJCXRocm93IG5ldyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oKTsKCQkKCQlTdHJpbmcgdHlwZU5hbWUgPSBzZXJ2ZXIuZ2V0U2VydmVyVHlwZSgpLmdldE5hbWUoKTsKCQlTdHJpbmcgaG9zdCA9IHNlcnZlci5nZXRIb3N0KCk7CgkJCgkJU3RyaW5nIG5hbWUgPSBOTFMuYmluZChNZXNzYWdlcy5kZWZhdWx0U2VydmVyTmFtZSwgbmV3IFN0cmluZ1tdIHt0eXBlTmFtZSwgaG9zdH0pOwoJCWludCBpID0gMjsKCQl3aGlsZSAoaXNOYW1lSW5Vc2UobmFtZSkpIHsKCQkJbmFtZSA9IE5MUy5iaW5kKE1lc3NhZ2VzLmRlZmF1bHRTZXJ2ZXJOYW1lMiwgbmV3IFN0cmluZ1tdIHt0eXBlTmFtZSwgaG9zdCwgaSArICIifSk7CgkJCWkrKzsKCQl9CgkJc2VydmVyLnNldE5hbWUobmFtZSk7Cgl9CgoJcHJpdmF0ZSBzdGF0aWMgYm9vbGVhbiBpc1ZhbGlkRmlsZW5hbWUoU3RyaW5nIG5hbWUpIHsKCQlJU3RhdHVzIHN0YXR1cyA9IFJlc291cmNlc1BsdWdpbi5nZXRXb3Jrc3BhY2UoKS52YWxpZGF0ZU5hbWUobmFtZSwgSVJlc291cmNlLkZJTEUpOwoJCWlmIChzdGF0dXMgIT0gbnVsbCAmJiAhc3RhdHVzLmlzT0soKSkKCQkJcmV0dXJuIGZhbHNlOwoJCQoJCXN0YXR1cyA9IFJlc291cmNlc1BsdWdpbi5nZXRXb3Jrc3BhY2UoKS52YWxpZGF0ZU5hbWUobmFtZSwgSVJlc291cmNlLkZPTERFUik7CgkJaWYgKHN0YXR1cyAhPSBudWxsICYmICFzdGF0dXMuaXNPSygpKQoJCQlyZXR1cm4gZmFsc2U7CgkJCgkJcmV0dXJuIHRydWU7Cgl9CgoJcHJpdmF0ZSBzdGF0aWMgU3RyaW5nIGdldFZhbGlkRmlsZU5hbWUoU3RyaW5nIG5hbWUpIHsKCQlpZiAoaXNWYWxpZEZpbGVuYW1lKG5hbWUpKQoJCQlyZXR1cm4gbmFtZTsKCQoJCS8vIHJlbW92ZSBpbnZhbGlkIGNoYXJhY3RlcnMKCQlTdHJpbmdbXSBzID0gbmV3IFN0cmluZ1tdIHsiLiIsICJcXCIsICIvIiwgIj8iLCAiOiIsICIqIiwgIlwiIiwgInwiLCAiPCIsICI+In07CgkJaW50IGluZCA9IDA7CgkJd2hpbGUgKGluZCA8IHMubGVuZ3RoKSB7CgkJCWludCBpbmRleCA9IG5hbWUuaW5kZXhPZihzW2luZF0pOwoJCQl3aGlsZSAoaW5kZXggPj0gMCkgewoJCQkJbmFtZSA9IG5hbWUuc3Vic3RyaW5nKDAsIGluZGV4KSArIG5hbWUuc3Vic3RyaW5nKGluZGV4KzEpOwoJCQkJaW5kZXggPSBuYW1lLmluZGV4T2Yoc1tpbmRdKTsKCQkJfQoJCQlpbmQrKzsKCQl9CgkJcmV0dXJuIG5hbWU7Cgl9CgoJLyoqCgkgKiBSZXR1cm5zIGFuIHVudXNlZCBmaWxlIGluIHRoZSBnaXZlbiBwcm9qZWN0LgoJICogCgkgKiBAcGFyYW0gcHJvamVjdCBhIHByb2plY3QKCSAqIEBwYXJhbSB0eXBlIGEgc2VydmVyIHR5cGUKCSAqIEByZXR1cm4gYW4gdW51c2VkIGZpbGUgd2l0aGluIHRoZSBnaXZlbiBwcm9qZWN0CgkgKi8KCS8qcHVibGljIHN0YXRpYyBJRmlsZSBnZXRVbnVzZWRTZXJ2ZXJGaWxlKElQcm9qZWN0IHByb2plY3QsIElTZXJ2ZXJUeXBlIHR5cGUpIHsKCQlpZiAocHJvamVjdCA9PSBudWxsIHx8IHR5cGUgPT0gbnVsbCkKCQkJdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwoJCQoJCVN0cmluZyB0eXBlTmFtZSA9IGdldFZhbGlkRmlsZU5hbWUodHlwZS5nZXROYW1lKCkpOwoJCVN0cmluZyBuYW1lID0gTkxTLmJpbmQoTWVzc2FnZXMuZGVmYXVsdFNlcnZlck5hbWUzLCB0eXBlTmFtZSkrICIuIiAgKyBTZXJ2ZXIuRklMRV9FWFRFTlNJT047CgkJaW50IGkgPSAyOwoJCXdoaWxlIChpc0ZpbGVOYW1lSW5Vc2UocHJvamVjdCwgbmFtZSkpIHsKCQkJbmFtZSA9IE5MUy5iaW5kKE1lc3NhZ2VzLmRlZmF1bHRTZXJ2ZXJOYW1lNCwgbmV3IFN0cmluZ1tdIHt0eXBlTmFtZSwgaSArICIifSkgKyAiLiIgICsgU2VydmVyLkZJTEVfRVhURU5TSU9OOwoJCQlpKys7CgkJfQoJCXJldHVybiBwcm9qZWN0LmdldEZpbGUobmFtZSk7Cgl9Ki8KCgkvKioKCSAqIFJldHVybnMgYW4gdW51c2VkIGZpbGUgaW4gdGhlIGdpdmVuIHByb2plY3QuCgkgKiAKCSAqIEBwYXJhbSBwcm9qZWN0IGEgcHJvamVjdAoJICogQHBhcmFtIHNlcnZlciBhIHNlcnZlcgoJICogQHJldHVybiBhbiB1bnVzZWQgZmlsZSB3aXRoaW4gdGhlIGdpdmVuIHByb2plY3QKCSAqLwoJcHVibGljIHN0YXRpYyBJRmlsZSBnZXRVbnVzZWRTZXJ2ZXJGaWxlKElQcm9qZWN0IHByb2plY3QsIElTZXJ2ZXIgc2VydmVyKSB7CgkJaWYgKHByb2plY3QgPT0gbnVsbCB8fCBzZXJ2ZXIgPT0gbnVsbCkKCQkJdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigpOwoJCQoJCVN0cmluZyB0eXBlTmFtZSA9IGdldFZhbGlkRmlsZU5hbWUoc2VydmVyLmdldE5hbWUoKSk7CgkJU3RyaW5nIG5hbWUgPSBOTFMuYmluZChNZXNzYWdlcy5kZWZhdWx0U2VydmVyTmFtZTMsIHR5cGVOYW1lKSsgIi4iICArIFNlcnZlci5GSUxFX0VYVEVOU0lPTjsKCQlpbnQgaSA9IDI7CgkJd2hpbGUgKGlzRmlsZU5hbWVJblVzZShwcm9qZWN0LCBuYW1lKSkgewoJCQluYW1lID0gTkxTLmJpbmQoTWVzc2FnZXMuZGVmYXVsdFNlcnZlck5hbWU0LCBuZXcgU3RyaW5nW10ge3R5cGVOYW1lLCBpICsgIiJ9KSArICIuIiAgKyBTZXJ2ZXIuRklMRV9FWFRFTlNJT047CgkJCWkrKzsKCQl9CgkJcmV0dXJuIHByb2plY3QuZ2V0RmlsZShuYW1lKTsKCX0KCgkvKioKCSAqIFJldHVybnMgdHJ1ZSBpZiBhIHNlcnZlciBvciBydW50aW1lIGV4aXN0cyB3aXRoIHRoZSBnaXZlbiBuYW1lLgoJICoKCSAqIEBwYXJhbSBuYW1lIGEgbmFtZQoJICogQHJldHVybiA8Y29kZT50cnVlPC9jb2RlPiBpZiB0aGUgbmFtZSBpcyBpbiB1c2UsIGFuZCA8Y29kZT5mYWxzZTwvY29kZT4KCSAqICAgIG90aGVyd2lzZQoJICovCglwcml2YXRlIHN0YXRpYyBib29sZWFuIGlzTmFtZUluVXNlKFN0cmluZyBuYW1lKSB7CgkJaWYgKG5hbWUgPT0gbnVsbCkKCQkJcmV0dXJuIHRydWU7CgkKCQlMaXN0IGxpc3QgPSBuZXcgQXJyYXlMaXN0KCk7CgkJCgkJYWRkQWxsKGxpc3QsIFNlcnZlckNvcmUuZ2V0UnVudGltZXMoKSk7CgkJYWRkQWxsKGxpc3QsIFNlcnZlckNvcmUuZ2V0U2VydmVycygpKTsKCgkJSXRlcmF0b3IgaXRlcmF0b3IgPSBsaXN0Lml0ZXJhdG9yKCk7CgkJd2hpbGUgKGl0ZXJhdG9yLmhhc05leHQoKSkgewoJCQlPYmplY3Qgb2JqID0gaXRlcmF0b3IubmV4dCgpOwoJCQlpZiAob2JqIGluc3RhbmNlb2YgSVNlcnZlckF0dHJpYnV0ZXMgJiYgbmFtZS5lcXVhbHNJZ25vcmVDYXNlKCgoSVNlcnZlckF0dHJpYnV0ZXMpb2JqKS5nZXROYW1lKCkpKQoJCQkJcmV0dXJuIHRydWU7CgkJCWlmIChvYmogaW5zdGFuY2VvZiBJUnVudGltZSAmJiBuYW1lLmVxdWFsc0lnbm9yZUNhc2UoKChJUnVudGltZSlvYmopLmdldE5hbWUoKSkpCgkJCQlyZXR1cm4gdHJ1ZTsKCQl9CgoJCXJldHVybiBmYWxzZTsKCX0KCQoJcHJpdmF0ZSBzdGF0aWMgdm9pZCBhZGRBbGwoTGlzdCBsaXN0LCBPYmplY3RbXSBvYmopIHsKCQlpZiAob2JqID09IG51bGwpCgkJCXJldHVybjsKCQkKCQlpbnQgc2l6ZSA9IG9iai5sZW5ndGg7CgkJZm9yIChpbnQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHsKCQkJbGlzdC5hZGQob2JqW2ldKTsKCQl9Cgl9CgkKCS8qKgoJICogUmV0dXJucyB0cnVlIGlmIGFuIGVsZW1lbnQgZXhpc3RzIHdpdGggdGhlIGdpdmVuIG5hbWUuCgkgKgoJICogQHBhcmFtIHByb2plY3QgYSBwcm9qZWN0CgkgKiBAcGFyYW0gbmFtZSBhIGZpbGUgb3IgZm9sZGVyIG5hbWUKCSAqIEByZXR1cm4gYm9vbGVhbiA8Y29kZT50cnVlPC9jb2RlPiBpZiB0aGUgZmlsZSBvciBmb2xkZXIgbmFtZSBpcyBiZWluZwoJICogICAgdXNlZCwgYW5kIDxjb2RlPmZhbHNlPC9jb2RlPiBvdGhlcndpc2UKCSAqLwoJcHJpdmF0ZSBzdGF0aWMgYm9vbGVhbiBpc0ZpbGVOYW1lSW5Vc2UoSVByb2plY3QgcHJvamVjdCwgU3RyaW5nIG5hbWUpIHsKCQlpZiAobmFtZSA9PSBudWxsIHx8IHByb2plY3QgPT0gbnVsbCkKCQkJcmV0dXJuIGZhbHNlOwoJCQoJCWlmIChwcm9qZWN0LmdldEZpbGUobmFtZSkuZXhpc3RzKCkpCgkJCXJldHVybiB0cnVlOwoJCWlmIChwcm9qZWN0LmdldEZvbGRlcihuYW1lKS5leGlzdHMoKSkKCQkJcmV0dXJuIHRydWU7CgkKCQlyZXR1cm4gZmFsc2U7Cgl9CgoJLyoqCgkgKiBSZXR1cm4gYSBsaXN0IG9mIGFsbCBydW50aW1lIHRhcmdldHMgdGhhdCBtYXRjaCB0aGUgZ2l2ZW4gdHlwZSBhbmQgdmVyc2lvbi4KCSAqIElmIHR5cGUgb3IgdmVyc2lvbiBpcyBudWxsLCBpdCBtYXRjaGVzIGFsbCBvZiB0aGF0IHR5cGUgb3IgdmVyc2lvbi4KCSAqIAoJICogQHBhcmFtIHR5cGUgYSBtb2R1bGUgdHlwZQoJICogQHBhcmFtIHZlcnNpb24gYSBtb2R1bGUgdmVyc2lvbgoJICogQHJldHVybiBhIHBvc3NpYmx5LWVtcHR5IGFycmF5IG9mIHJ1bnRpbWUgaW5zdGFuY2VzIHtAbGluayBJUnVudGltZX0KCSAqLwoJcHVibGljIHN0YXRpYyBJUnVudGltZVtdIGdldFJ1bnRpbWVzKFN0cmluZyB0eXBlLCBTdHJpbmcgdmVyc2lvbikgewoJCUxpc3QgbGlzdCA9IG5ldyBBcnJheUxpc3QoKTsKCQlJUnVudGltZVtdIHJ1bnRpbWVzID0gU2VydmVyQ29yZS5nZXRSdW50aW1lcygpOwoJCWlmIChydW50aW1lcyAhPSBudWxsKSB7CgkJCWludCBzaXplID0gcnVudGltZXMubGVuZ3RoOwoJCQlmb3IgKGludCBpID0gMDsgaSA8IHNpemU7IGkrKykgewoJCQkJSVJ1bnRpbWVUeXBlIHJ1bnRpbWVUeXBlID0gcnVudGltZXNbaV0uZ2V0UnVudGltZVR5cGUoKTsKCQkJCWlmIChydW50aW1lVHlwZSAhPSBudWxsICYmIGlzU3VwcG9ydGVkTW9kdWxlKHJ1bnRpbWVUeXBlLmdldE1vZHVsZVR5cGVzKCksIHR5cGUsIHZlcnNpb24pKSB7CgkJCQkJbGlzdC5hZGQocnVudGltZXNbaV0pOwoJCQkJfQoJCQl9CgkJfQoJCQoJCUlSdW50aW1lW10gcnVudGltZXMyID0gbmV3IElSdW50aW1lW2xpc3Quc2l6ZSgpXTsKCQlsaXN0LnRvQXJyYXkocnVudGltZXMyKTsKCQlyZXR1cm4gcnVudGltZXMyOwoJfQoKCS8qKgoJICogUmV0dXJuIGEgbGlzdCBvZiBhbGwgcnVudGltZSB0eXBlcyB0aGF0IG1hdGNoIHRoZSBnaXZlbiB0eXBlIGFuZCB2ZXJzaW9uLgoJICogSWYgdHlwZSBvciB2ZXJzaW9uIGlzIG51bGwsIGl0IG1hdGNoZXMgYWxsIG9mIHRoYXQgdHlwZSBvciB2ZXJzaW9uLgoJICogCgkgKiBAcGFyYW0gdHlwZSBhIG1vZHVsZSB0eXBlCgkgKiBAcGFyYW0gdmVyc2lvbiBhIG1vZHVsZSB2ZXJzaW9uCgkgKiBAcmV0dXJuIGEgcG9zc2libHktZW1wdHkgYXJyYXkgb2YgcnVudGltZSB0eXBlIGluc3RhbmNlcyB7QGxpbmsgSVJ1bnRpbWVUeXBlfQoJICovCglwdWJsaWMgc3RhdGljIElSdW50aW1lVHlwZVtdIGdldFJ1bnRpbWVUeXBlcyhTdHJpbmcgdHlwZSwgU3RyaW5nIHZlcnNpb24pIHsKCQlMaXN0IGxpc3QgPSBuZXcgQXJyYXlMaXN0KCk7CgkJSVJ1bnRpbWVUeXBlW10gcnVudGltZVR5cGVzID0gU2VydmVyQ29yZS5nZXRSdW50aW1lVHlwZXMoKTsKCQlpZiAocnVudGltZVR5cGVzICE9IG51bGwpIHsKCQkJaW50IHNpemUgPSBydW50aW1lVHlwZXMubGVuZ3RoOwoJCQlmb3IgKGludCBpID0gMDsgaSA8IHNpemU7IGkrKykgewoJCQkJaWYgKGlzU3VwcG9ydGVkTW9kdWxlKHJ1bnRpbWVUeXBlc1tpXS5nZXRNb2R1bGVUeXBlcygpLCB0eXBlLCB2ZXJzaW9uKSkgewoJCQkJCWxpc3QuYWRkKHJ1bnRpbWVUeXBlc1tpXSk7CgkJCQl9CgkJCX0KCQl9CgkJCgkJSVJ1bnRpbWVUeXBlW10gcnQgPSBuZXcgSVJ1bnRpbWVUeXBlW2xpc3Quc2l6ZSgpXTsKCQlsaXN0LnRvQXJyYXkocnQpOwoJCXJldHVybiBydDsKCX0KCQoJLyoqCgkgKiBSZXR1cm4gYSBsaXN0IG9mIGFsbCBydW50aW1lIHR5cGVzIHRoYXQgbWF0Y2ggdGhlIGdpdmVuIHR5cGUsIHZlcnNpb24sCgkgKiBhbmQgcGFydGlhbCBydW50aW1lIHR5cGUgaWQuIElmIHR5cGUsIHZlcnNpb24sIG9yIHJ1bnRpbWVUeXBlSWQgaXMgbnVsbCwKCSAqIGl0IG1hdGNoZXMgYWxsIG9mIHRoYXQgdHlwZSBvciB2ZXJzaW9uLgoJICogCgkgKiBAcGFyYW0gdHlwZSBhIG1vZHVsZSB0eXBlCgkgKiBAcGFyYW0gdmVyc2lvbiBhIG1vZHVsZSB2ZXJzaW9uCgkgKiBAcGFyYW0gcnVudGltZVR5cGVJZCB0aGUgaWQgb2YgYSBydW50aW1lIHR5cGUKCSAqIEByZXR1cm4gYSBwb3NzaWJseS1lbXB0eSBhcnJheSBvZiBydW50aW1lIHR5cGUgaW5zdGFuY2VzIHtAbGluayBJUnVudGltZVR5cGV9CgkgKi8KCXB1YmxpYyBzdGF0aWMgSVJ1bnRpbWVUeXBlW10gZ2V0UnVudGltZVR5cGVzKFN0cmluZyB0eXBlLCBTdHJpbmcgdmVyc2lvbiwgU3RyaW5nIHJ1bnRpbWVUeXBlSWQpIHsKCQlMaXN0IGxpc3QgPSBuZXcgQXJyYXlMaXN0KCk7CgkJSVJ1bnRpbWVUeXBlW10gcnVudGltZVR5cGVzID0gU2VydmVyQ29yZS5nZXRSdW50aW1lVHlwZXMoKTsKCQlpZiAocnVudGltZVR5cGVzICE9IG51bGwpIHsKCQkJaW50IHNpemUgPSBydW50aW1lVHlwZXMubGVuZ3RoOwoJCQlmb3IgKGludCBpID0gMDsgaSA8IHNpemU7IGkrKykgewoJCQkJaWYgKGlzU3VwcG9ydGVkTW9kdWxlKHJ1bnRpbWVUeXBlc1tpXS5nZXRNb2R1bGVUeXBlcygpLCB0eXBlLCB2ZXJzaW9uKSkgewoJCQkJCWlmIChydW50aW1lVHlwZUlkID09IG51bGwgfHwgcnVudGltZVR5cGVzW2ldLmdldElkKCkuc3RhcnRzV2l0aChydW50aW1lVHlwZUlkKSkKCQkJCQkJbGlzdC5hZGQocnVudGltZVR5cGVzW2ldKTsKCQkJCX0KCQkJfQoJCX0KCQkKCQlJUnVudGltZVR5cGVbXSBydCA9IG5ldyBJUnVudGltZVR5cGVbbGlzdC5zaXplKCldOwoJCWxpc3QudG9BcnJheShydCk7CgkJcmV0dXJuIHJ0OwoJfQoKCS8qKgoJICogUmV0dXJucyBhIGxpc3Qgb2YgYWxsIHNlcnZlcnMgdGhhdCB0aGlzIGRlcGxveWFibGUgaXMgbm90IGN1cnJlbnRseQoJICogY29uZmlndXJlZCBvbiwgYnV0IGNvdWxkIGJlIGFkZGVkIHRvLiBJZiBpbmNsdWRlRXJyb3JzIGlzIHRydWUsIHRoaXMKCSAqIG1ldGhvZCByZXR1cm4gc2VydmVycyB3aGVyZSB0aGUgcGFyZW50IGRlcGxveWFibGUgbWF5IHRocm93IGVycm9ycy4gRm9yCgkgKiBpbnN0YW5jZSwgdGhpcyBkZXBsb3lhYmxlIG1heSBiZSB0aGUgd3Jvbmcgc3BlYyBsZXZlbC4KCSAqCgkgKiBAcGFyYW0gbW9kdWxlIGEgbW9kdWxlCgkgKiBAcGFyYW0gaW5jbHVkZUVycm9ycyA8Y29kZT50cnVlPC9jb2RlPiB0byBpbmNsdWRlIHNlcnZlcnMgdGhhdCByZXR1cm5lZAoJICogICAgZXJyb3JzIHdoZW4gdHJ5aW5nIHRvIGFkZCB0aGUgbW9kdWxlLCBhbmQgPGNvZGU+ZmFsc2U8L2NvZGU+IG90aGVyd2lzZQoJICogQHBhcmFtIG1vbml0b3IgYSBwcm9ncmVzcyBtb25pdG9yLCBvciA8Y29kZT5udWxsPC9jb2RlPiBpZiBwcm9ncmVzcwoJICogICAgcmVwb3J0aW5nIGFuZCBjYW5jZWxsYXRpb24gYXJlIG5vdCBkZXNpcmVkCgkgKiBAcmV0dXJuIGEgcG9zc2libHkgZW1wdHkgYXJyYXkgb2Ygc2VydmVycwoJICovCglwdWJsaWMgc3RhdGljIElTZXJ2ZXJbXSBnZXRBdmFpbGFibGVTZXJ2ZXJzRm9yTW9kdWxlKElNb2R1bGUgbW9kdWxlLCBib29sZWFuIGluY2x1ZGVFcnJvcnMsIElQcm9ncmVzc01vbml0b3IgbW9uaXRvcikgewoJCWlmIChtb2R1bGUgPT0gbnVsbCkKCQkJcmV0dXJuIG5ldyBJU2VydmVyWzBdOwoKCQkvLyBkbyBpdCB0aGUgc2xvdyB3YXkgLSBnbyB0aHJvdWdoIGFsbCBzZXJ2ZXJzIGFuZAoJCS8vIHNlZSBpZiB0aGlzIGRlcGxveWFibGUgaXMgbm90IGNvbmZpZ3VyZWQgaW4gaXQKCQkvLyBidXQgY291bGQgYmUgYWRkZWQKCQlMaXN0IGxpc3QgPSBuZXcgQXJyYXlMaXN0KCk7CgkJSVNlcnZlcltdIHNlcnZlcnMgPSBTZXJ2ZXJDb3JlLmdldFNlcnZlcnMoKTsKCQlpZiAoc2VydmVycyAhPSBudWxsKSB7CgkJCWludCBzaXplID0gc2VydmVycy5sZW5ndGg7CgkJCWZvciAoaW50IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKSB7CgkJCQlpZiAoIWNvbnRhaW5zTW9kdWxlKHNlcnZlcnNbaV0sIG1vZHVsZSwgbW9uaXRvcikpIHsKCQkJCQl0cnkgewoJCQkJCQlJTW9kdWxlW10gcGFyZW50cyA9IHNlcnZlcnNbaV0uZ2V0Um9vdE1vZHVsZXMobW9kdWxlLCBtb25pdG9yKTsKCQkJCQkJaWYgKHBhcmVudHMgIT0gbnVsbCAmJiBwYXJlbnRzLmxlbmd0aCA+IDApIHsKCQkJCQkJCWJvb2xlYW4gZm91bmQgPSBmYWxzZTsKCQkJCQkJCWlmIChwYXJlbnRzICE9IG51bGwpIHsKCQkJCQkJCQlpbnQgc2l6ZTIgPSBwYXJlbnRzLmxlbmd0aDsKCQkJCQkJCQlmb3IgKGludCBqID0gMDsgIWZvdW5kICYmIGogPCBzaXplMjsgaisrKSB7CgkJCQkJCQkJCUlNb2R1bGUgcGFyZW50ID0gcGFyZW50c1tqXTsKCQkJCQkJCQkJSVN0YXR1cyBzdGF0dXMgPSBzZXJ2ZXJzW2ldLmNhbk1vZGlmeU1vZHVsZXMobmV3IElNb2R1bGVbXSB7IHBhcmVudCB9LCBuZXcgSU1vZHVsZVswXSwgbW9uaXRvcik7CgkJCQkJCQkJCWlmIChzdGF0dXMgPT0gbnVsbCB8fCBzdGF0dXMuaXNPSygpKXsKCQkJCQkJCQkJCWxpc3QuYWRkKHNlcnZlcnNbaV0pOwoJCQkJCQkJCQkJZm91bmQgPSB0cnVlOwoJCQkJCQkJCQl9CgkJCQkJCQkJfQoJCQkJCQkJfQoJCQkJCQl9CgkJCQkJfSBjYXRjaCAoRXhjZXB0aW9uIHNlKSB7CgkJCQkJCWlmIChpbmNsdWRlRXJyb3JzKQoJCQkJCQkJbGlzdC5hZGQoc2VydmVyc1tpXSk7CgkJCQkJfQoJCQkJfQoJCQl9CgkJfQoJCQoJCS8vIG1ha2Ugc3VyZSB0aGF0IHRoZSBwcmVmZXJyZWQgc2VydmVyIGlzIHRoZSBmaXJzdCBvbmUKCQkvL0lTZXJ2ZXIgc2VydmVyID0gU2VydmVyQ29yZS5nZXRTZXJ2ZXJQcmVmZXJlbmNlcygpLmdldERlcGxveWFibGVTZXJ2ZXJQcmVmZXJlbmNlKGRlcGxveWFibGUpOwoJCS8vaWYgKHNlcnZlciAhPSBudWxsICYmIGxpc3QuY29udGFpbnMoc2VydmVyKSAmJiBsaXN0LmluZGV4T2Yoc2VydmVyKSAhPSAwKSB7CgkJLy8JbGlzdC5yZW1vdmUoc2VydmVyKTsKCQkvLwlsaXN0LmFkZCgwLCBzZXJ2ZXIpOwoJCS8vfQoKCQlJU2VydmVyW10gYWxsU2VydmVycyA9IG5ldyBJU2VydmVyW2xpc3Quc2l6ZSgpXTsKCQlsaXN0LnRvQXJyYXkoYWxsU2VydmVycyk7CgkJcmV0dXJuIGFsbFNlcnZlcnM7Cgl9CgoJLyoqCgkgKiBSZXR1cm5zIGEgbGlzdCBvZiBhbGwgc2VydmVycyB0aGF0IHRoaXMgbW9kdWxlIGlzIGNvbmZpZ3VyZWQgb24uCgkgKiAKCSAqIEBwYXJhbSBtb2R1bGUgYSBtb2R1bGUKCSAqIEBwYXJhbSBtb25pdG9yIGEgcHJvZ3Jlc3MgbW9uaXRvciwgb3IgPGNvZGU+bnVsbDwvY29kZT4gaWYgcHJvZ3Jlc3MKCSAqICAgIHJlcG9ydGluZyBhbmQgY2FuY2VsbGF0aW9uIGFyZSBub3QgZGVzaXJlZAoJICogQHJldHVybiBhIHBvc3NpYmx5LWVtcHR5IGFycmF5IG9mIHNlcnZlciBpbnN0YW5jZXMge0BsaW5rIElTZXJ2ZXJ9CgkgKi8KCXB1YmxpYyBzdGF0aWMgSVNlcnZlcltdIGdldFNlcnZlcnNCeU1vZHVsZShJTW9kdWxlIG1vZHVsZSwgSVByb2dyZXNzTW9uaXRvciBtb25pdG9yKSB7CgkJaWYgKG1vZHVsZSA9PSBudWxsKQoJCQlyZXR1cm4gbmV3IElTZXJ2ZXJbMF07CgoJCS8vIGRvIGl0IHRoZSBzbG93IHdheSAtIGdvIHRocm91Z2ggYWxsIHNlcnZlcnMgYW5kCgkJLy8gc2VlIGlmIHRoaXMgbW9kdWxlIGlzIGNvbmZpZ3VyZWQgaW4gaXQKCQlMaXN0IGxpc3QgPSBuZXcgQXJyYXlMaXN0KCk7CgkJSVNlcnZlcltdIHNlcnZlcnMgPSBTZXJ2ZXJDb3JlLmdldFNlcnZlcnMoKTsKCQlpZiAoc2VydmVycyAhPSBudWxsKSB7CgkJCWludCBzaXplID0gc2VydmVycy5sZW5ndGg7CgkJCWZvciAoaW50IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKSB7CgkJCQlpZiAoY29udGFpbnNNb2R1bGUoc2VydmVyc1tpXSwgbW9kdWxlLCBtb25pdG9yKSkKCQkJCQlsaXN0LmFkZChzZXJ2ZXJzW2ldKTsKCQkJfQoJCX0KCQkKCQlJU2VydmVyW10gYWxsU2VydmVycyA9IG5ldyBJU2VydmVyW2xpc3Quc2l6ZSgpXTsKCQlsaXN0LnRvQXJyYXkoYWxsU2VydmVycyk7CgkJcmV0dXJuIGFsbFNlcnZlcnM7Cgl9CgoJLyoqCgkgKiBSZXR1cm5zIHRydWUgaWYgdGhlIGdpdmVuIHNlcnZlciBjdXJyZW50bHkgY29udGFpbnMgdGhlIGdpdmVuIG1vZHVsZS4KCSAqCgkgKiBAcGFyYW0gc2VydmVyIGEgc2VydmVyCgkgKiBAcGFyYW0gbW9kdWxlIGEgbW9kdWxlCgkgKiBAcGFyYW0gbW9uaXRvciBhIHByb2dyZXNzIG1vbml0b3IsIG9yIDxjb2RlPm51bGw8L2NvZGU+IGlmIHByb2dyZXNzCgkgKiAgICByZXBvcnRpbmcgYW5kIGNhbmNlbGxhdGlvbiBhcmUgbm90IGRlc2lyZWQKCSAqIEByZXR1cm4gYm9vbGVhbiA8Y29kZT50cnVlPC9jb2RlPiBpZiB0aGUgbW9kdWxlIGlzIGNvbnRhaW5lZCBvbiB0aGUgc2VydmVyLAoJICogICAgb3IgPGNvZGU+ZmFsc2U8L2NvZGU+IG90aGVyd2lzZQoJICovCglwdWJsaWMgc3RhdGljIGJvb2xlYW4gY29udGFpbnNNb2R1bGUoSVNlcnZlciBzZXJ2ZXIsIGZpbmFsIElNb2R1bGUgbW9kdWxlLCBJUHJvZ3Jlc3NNb25pdG9yIG1vbml0b3IpIHsKCQlpZiAoc2VydmVyID09IG51bGwpCgkJCXJldHVybiBmYWxzZTsKCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICJjb250YWluc01vZHVsZSgpICIgKyBzZXJ2ZXIgKyAiICIgKyBtb2R1bGUpOwoJCQoJCWNsYXNzIEhlbHBlciB7CgkJCWJvb2xlYW4gYjsKCQl9CgkJZmluYWwgSGVscGVyIGggPSBuZXcgSGVscGVyKCk7CgoJCSgoU2VydmVyKXNlcnZlcikudmlzaXQobmV3IElNb2R1bGVWaXNpdG9yKCkgewoJCQlwdWJsaWMgYm9vbGVhbiB2aXNpdChJTW9kdWxlW10gbW9kdWxlcykgewoJCQkJaW50IHNpemUgPSBtb2R1bGVzLmxlbmd0aDsKCQkJCWlmIChtb2R1bGVzW3NpemUgLSAxXS5lcXVhbHMobW9kdWxlKSkgewoJCQkJCWguYiA9IHRydWU7CgkJCQkJcmV0dXJuIGZhbHNlOwoJCQkJfQoJCQkJcmV0dXJuIHRydWU7CgkJCX0KCQl9LCBudWxsKTsKCQlyZXR1cm4gaC5iOwoJfQoKCS8qKgoJICogUmV0dXJucyB0aGUgc2VydmVyIGFzc29jaWF0ZWQgd2l0aCB0aGUgZ2l2ZW4gbGF1bmNoIGNvbmZpZ3VyYXRpb24uCgkgKiAKCSAqIEBwYXJhbSBjb25maWd1cmF0aW9uIGEgbGF1bmNoIGNvbmZpZ3VyYXRpb24KCSAqIEByZXR1cm4gdGhlIHNlcnZlciBhc3NvY2lhdGVkIHdpdGggdGhlIGxhdW5jaCBjb25maWd1cmF0aW9uLCBvcgoJICogICAgPGNvZGU+bnVsbDwvY29kZT4gaWYgbm8gc2VydmVyIGNvdWxkIGJlIGZvdW5kCgkgKiBAdGhyb3dzIENvcmVFeGNlcHRpb24gaWYgdGhlcmUgaXMgYSBwcm9ibGVtIGdldHRpbmcgdGhlIGF0dHJpYnV0ZSBmcm9tCgkgKiAgICB0aGUgbGF1bmNoIGNvbmZpZ3VyYXRpb24KCSAqLwoJcHVibGljIHN0YXRpYyBJU2VydmVyIGdldFNlcnZlcihJTGF1bmNoQ29uZmlndXJhdGlvbiBjb25maWd1cmF0aW9uKSB0aHJvd3MgQ29yZUV4Y2VwdGlvbiB7CgkJU3RyaW5nIHNlcnZlcklkID0gY29uZmlndXJhdGlvbi5nZXRBdHRyaWJ1dGUoU2VydmVyLkFUVFJfU0VSVkVSX0lELCAoU3RyaW5nKSBudWxsKTsKCgkJaWYgKHNlcnZlcklkICE9IG51bGwpCgkJCXJldHVybiBTZXJ2ZXJDb3JlLmZpbmRTZXJ2ZXIoc2VydmVySWQpOwoJCXJldHVybiBudWxsOwoJfQoKCS8qKgoJICogVmFsaWRhdGVzIHdoZXRoZXIgdGhpcyBzZXJ2ZXIgY2FuIGJlIGVkaXR0ZWQuCgkgKiAKCSAqIEBwYXJhbSBjb250ZXh0IHRoZSBjb250ZXh0IChTaGVsbCkKCSAqIEBwYXJhbSBzZXJ2ZXIgdGhlIHNlcnZlcgoJICogQHJldHVybiBhIHN0YXR1cyBvYmplY3Qgd2l0aCBjb2RlIDxjb2RlPklTdGF0dXMuT0s8L2NvZGU+IGlmIHRoZSBzZXJ2ZXIKCSAqICAgY2FuIGJlIGVkaXRlZCwgb3RoZXJ3aXNlIGEgc3RhdHVzIG9iamVjdCBpbmRpY2F0aW5nIHdoYXQgd2hlbiB3cm9uZwoJICogICB3aXRoIHRoZSBjaGVja291dAoJICovCglwdWJsaWMgc3RhdGljIElTdGF0dXMgdmFsaWRhdGVFZGl0KE9iamVjdCBjb250ZXh0LCBJU2VydmVyIHNlcnZlcikgewoJCXJldHVybiAoKFNlcnZlcilzZXJ2ZXIpLnZhbGlkYXRlRWRpdChjb250ZXh0KTsKCX0KCgkvKioKCSAqIFJldHVybnMgdGhlIHBvcnQgdGhhdCBpcyBiZWluZyB1c2VkIHRvIG1vbml0b3IgdGhlIGdpdmVuIHBvcnQgb24gdGhlIHNlcnZlci4KCSAqIFRoaXMgbWV0aG9kIGNhbiBiZSB1c2VkIHdoZW5ldmVyIGNyZWF0aW5nIGEgJ2NsaWVudCcgZm9yIHRoZSBzZXJ2ZXIsIGFuZCBhbGxvd3MKCSAqIHRoZSBjbGllbnQgdG8gc2VhbWxlc3NseSB1c2UgYSBtb25pdG9yZWQgcG9ydCBpbnN0ZWFkIG9mIGdvaW5nIGRpcmVjdGx5IHRvIHRoZQoJICogc2VydmVyLgoJICogCgkgKiA8Yj5Qcm92aXNpb25hbCBBUEk6PC9iPiBUaGlzIGNsYXNzL2ludGVyZmFjZSBpcyBwYXJ0IG9mIGFuIGludGVyaW0gQVBJIHRoYXQgaXMgc3RpbGwgdW5kZXIgZGV2ZWxvcG1lbnQgYW5kIGV4cGVjdGVkIHRvIAoJICogY2hhbmdlIHNpZ25pZmljYW50bHkgYmVmb3JlIHJlYWNoaW5nIHN0YWJpbGl0eS4gSXQgaXMgYmVpbmcgbWFkZSBhdmFpbGFibGUgYXQgdGhpcyBlYXJseSBzdGFnZSB0byBzb2xpY2l0IGZlZWRiYWNrIAoJICogZnJvbSBwaW9uZWVyaW5nIGFkb3B0ZXJzIG9uIHRoZSB1bmRlcnN0YW5kaW5nIHRoYXQgYW55IGNvZGUgdGhhdCB1c2VzIHRoaXMgQVBJIHdpbGwgYWxtb3N0IGNlcnRhaW5seSBiZSBicm9rZW4gCgkgKiAocmVwZWF0ZWRseSkgYXMgdGhlIEFQSSBldm9sdmVzLgoJICogPC9wPgoJICogCgkgKiBAcGFyYW0gc2VydmVyIGEgc2VydmVyCgkgKiBAcGFyYW0gcG9ydCBhIHBvcnQgb24gdGhlIHNlcnZlcgoJICogQHBhcmFtIGNvbnRlbnRUeXBlIHRoZSBjb250ZW50IHR5cGUsIGUuZy4gIndlYiIKCSAqIEByZXR1cm4gdGhlIG1vbml0b3JlZCBwb3J0LCBvciB0aGUgb3JpZ2luYWwgcG9ydCBudW1iZXIgaWYgdGhlIHBvcnQgaXMgbm90CgkgKiAgICBjdXJyZW50bHkgYmVpbmcgbW9uaXRvcmVkCgkgKi8KCXB1YmxpYyBzdGF0aWMgaW50IGdldE1vbml0b3JlZFBvcnQoSVNlcnZlciBzZXJ2ZXIsIGludCBwb3J0LCBTdHJpbmcgY29udGVudFR5cGUpIHsKCQlyZXR1cm4gU2VydmVyTW9uaXRvck1hbmFnZXIuZ2V0SW5zdGFuY2UoKS5nZXRNb25pdG9yZWRQb3J0KHNlcnZlciwgcG9ydCwgY29udGVudFR5cGUpOwoJfQp9