LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogQ29weXJpZ2h0IChjKSAyMDAzIElCTSBDb3Jwb3JhdGlvbiBhbmQgb3RoZXJzLgogKiBBbGwgcmlnaHRzIHJlc2VydmVkLiBUaGlzIHByb2dyYW0gYW5kIHRoZSBhY2NvbXBhbnlpbmcgbWF0ZXJpYWxzCiAqIGFyZSBtYWRlIGF2YWlsYWJsZSB1bmRlciB0aGUgdGVybXMgb2YgdGhlIENvbW1vbiBQdWJsaWMgTGljZW5zZSB2MS4wCiAqIHdoaWNoIGFjY29tcGFuaWVzIHRoaXMgZGlzdHJpYnV0aW9uLCBhbmQgaXMgYXZhaWxhYmxlIGF0CiAqIGh0dHA6Ly93d3cuZWNsaXBzZS5vcmcvbGVnYWwvY3BsLXYxMC5odG1sCqAqCiAqIENvbnRyaWJ1dG9yczoKICogICAgIElCTSBDb3Jwb3JhdGlvbiAtIEluaXRpYWwgQVBJIGFuZCBpbXBsZW1lbnRhdGlvbgogKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KcGFja2FnZSBvcmcuZWNsaXBzZS53c3Quc2VydmVyLmNvcmUuaW50ZXJuYWw7CgppbXBvcnQgamF2YS51dGlsLio7CgppbXBvcnQgb3JnLmVjbGlwc2UuY29yZS5ydW50aW1lLkNvcmVFeGNlcHRpb247CmltcG9ydCBvcmcuZWNsaXBzZS5jb3JlLnJ1bnRpbWUuSVN0YXR1czsKaW1wb3J0IG9yZy5lY2xpcHNlLmNvcmUucnVudGltZS5TdGF0dXM7CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc2VydmVyLmNvcmUuKjsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIuY29yZS5tb2RlbC5JTW9uaXRvcmFibGVTZXJ2ZXI7CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc2VydmVyLmNvcmUubW9kZWwuSVNlcnZlclBvcnQ7Ci8qKgogKiAKICovCnB1YmxpYyBjbGFzcyBTZXJ2ZXJNb25pdG9yTWFuYWdlciBpbXBsZW1lbnRzIElTZXJ2ZXJNb25pdG9yTWFuYWdlciB7Cglwcml2YXRlIHN0YXRpYyBmaW5hbCBTdHJpbmcgTU9OSVRPUl9EQVRBX0ZJTEUgPSAibW9uaXRvcnMueG1sIjsKCQoJcHJvdGVjdGVkIHN0YXRpYyBTZXJ2ZXJNb25pdG9yTWFuYWdlciBpbnN0YW5jZTsKCglwcm90ZWN0ZWQgTGlzdCBwb3J0cyA9IG5ldyBBcnJheUxpc3QoKTsgCglwcm90ZWN0ZWQgSVNlcnZlck1vbml0b3IgbW9uaXRvcjsKCQoJY2xhc3MgTW9uaXRvcmVkUG9ydCBpbXBsZW1lbnRzIElNb25pdG9yZWRTZXJ2ZXJQb3J0IHsKCQlwcm90ZWN0ZWQgSVNlcnZlciBzZXJ2ZXI7CgkJcHJvdGVjdGVkIElTZXJ2ZXJQb3J0IHBvcnQ7CgkJcHJvdGVjdGVkIGludCBuZXdQb3J0ID0gLTE7CgkJcHJvdGVjdGVkIFN0cmluZ1tdIGNvbnRlbnQ7CgkJcHVibGljIGJvb2xlYW4gc3RhcnRlZDsKCQkKCQlwdWJsaWMgTW9uaXRvcmVkUG9ydChJU2VydmVyIHNlcnZlciwgSVNlcnZlclBvcnQgcG9ydCwgaW50IG5ld1BvcnQsIFN0cmluZ1tdIGNvbnRlbnQpIHsKCQkJdGhpcy5zZXJ2ZXIgPSBzZXJ2ZXI7CgkJCXRoaXMucG9ydCA9IHBvcnQ7CgkJCXRoaXMubmV3UG9ydCA9IG5ld1BvcnQ7CgkJCXRoaXMuY29udGVudCA9IGNvbnRlbnQ7CgkJfQoJCQoJCXB1YmxpYyBNb25pdG9yZWRQb3J0KElNZW1lbnRvIG1lbWVudG8pIHsKCQkJbG9hZChtZW1lbnRvKTsKCQl9CgkJCgkJcHVibGljIElTZXJ2ZXIgZ2V0U2VydmVyKCkgewoJCQlyZXR1cm4gc2VydmVyOwoJCX0KCQkKCQlwdWJsaWMgSVNlcnZlclBvcnQgZ2V0U2VydmVyUG9ydCgpIHsKCQkJcmV0dXJuIHBvcnQ7CgkJfQoJCQoJCXB1YmxpYyBpbnQgZ2V0TW9uaXRvclBvcnQoKSB7CgkJCXJldHVybiBuZXdQb3J0OwoJCX0KCQkKCQlwdWJsaWMgdm9pZCBzZXRNb25pdG9yUG9ydChpbnQgcCkgewoJCQluZXdQb3J0ID0gcDsKCQl9CgkJCgkJcHVibGljIFN0cmluZ1tdIGdldENvbnRlbnRUeXBlcygpIHsKCQkJcmV0dXJuIGNvbnRlbnQ7CgkJfQoJCQoJCXB1YmxpYyBib29sZWFuIGlzU3RhcnRlZCgpIHsKCQkJcmV0dXJuIHN0YXJ0ZWQ7CgkJfQoJCQoJCXByb3RlY3RlZCB2b2lkIHNldFN0YXJ0ZWQoYm9vbGVhbiBzKSB7CgkJCXN0YXJ0ZWQgPSBzOwoJCX0KCQkKCQlwdWJsaWMgYm9vbGVhbiBlcXVhbHMoT2JqZWN0IG9iaikgewoJCQlpZiAoIShvYmogaW5zdGFuY2VvZiBNb25pdG9yZWRQb3J0KSkKCQkJCXJldHVybiBmYWxzZTsKCQkJTW9uaXRvcmVkUG9ydCBtcCA9IChNb25pdG9yZWRQb3J0KSBvYmo7CgkJCWlmICghbXAuc2VydmVyLmVxdWFscyhzZXJ2ZXIpKQoJCQkJcmV0dXJuIGZhbHNlOwoJCQlpZiAoIW1wLnBvcnQuZXF1YWxzKHBvcnQpKQoJCQkJcmV0dXJuIGZhbHNlOwoJCQlpZiAobmV3UG9ydCAhPSBtcC5uZXdQb3J0KQoJCQkJcmV0dXJuIGZhbHNlOwoJCQlpZiAoY29udGVudCA9PSBudWxsICYmIG1wLmNvbnRlbnQgIT0gbnVsbCkKCQkJCXJldHVybiBmYWxzZTsKCQkJaWYgKGNvbnRlbnQgIT0gbnVsbCAmJiBtcC5jb250ZW50ID09IG51bGwpCgkJCQlyZXR1cm4gZmFsc2U7CgkJCWlmIChjb250ZW50ICE9IG51bGwpIHsKCQkJCWludCBzaXplID0gY29udGVudC5sZW5ndGg7CgkJCQlpZiAoc2l6ZSAhPSBtcC5jb250ZW50Lmxlbmd0aCkKCQkJCQlyZXR1cm4gZmFsc2U7CgkJCQlmb3IgKGludCBpID0gMDsgaSA8IHNpemU7IGkrKykKCQkJCQlpZiAoIWNvbnRlbnRbaV0uZXF1YWxzKG1wLmNvbnRlbnRbaV0pKQoJCQkJCQlyZXR1cm4gZmFsc2U7CgkJCX0KCQkJcmV0dXJuIHRydWU7CgkJfQoJCQoJCXByb3RlY3RlZCBib29sZWFuIGNhblNhdmUoKSB7CgkJCXJldHVybiAocG9ydC5nZXRJZCgpICE9IG51bGwpOwoJCX0KCQkKCQlwcm90ZWN0ZWQgdm9pZCBzYXZlKElNZW1lbnRvIG1lbWVudG8pIHsKCQkJbWVtZW50by5wdXRTdHJpbmcoInNlcnZlcklkIiwgc2VydmVyLmdldElkKCkpOwoJCQlpZiAobmV3UG9ydCAhPSAtMSkKCQkJCW1lbWVudG8ucHV0U3RyaW5nKCJwb3J0IiwgbmV3UG9ydCArICIiKTsKCQkJbWVtZW50by5wdXRTdHJpbmcoInBvcnRJZCIsIHBvcnQuZ2V0SWQoKSk7CgkJCW1lbWVudG8ucHV0Qm9vbGVhbigic3RhcnRlZCIsIHN0YXJ0ZWQpOwoJCQkKCQkJaWYgKGNvbnRlbnQgIT0gbnVsbCkgewoJCQkJU3RyaW5nQnVmZmVyIHNiID0gbmV3IFN0cmluZ0J1ZmZlcigpOwoJCQkJaW50IHNpemUgPSBjb250ZW50Lmxlbmd0aDsKCQkJCWZvciAoaW50IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKSB7CgkJCQkJaWYgKGkgPiAwKQoJCQkJCQlzYi5hcHBlbmQoIiwiKTsKCQkJCQlzYi5hcHBlbmQoY29udGVudFtpXSk7CgkJCQl9CgkJCQltZW1lbnRvLnB1dFN0cmluZygiY29udGVudFR5cGVzIiwgc2IudG9TdHJpbmcoKSk7CgkJCX0KCQl9CgkJCgkJcHJvdGVjdGVkIHZvaWQgbG9hZChJTWVtZW50byBtZW1lbnRvKSB7CgkJCVN0cmluZyBzZXJ2ZXJJZCA9IG1lbWVudG8uZ2V0U3RyaW5nKCJzZXJ2ZXJJZCIpOwoJCQlzZXJ2ZXIgPSBTZXJ2ZXJDb3JlLmdldFJlc291cmNlTWFuYWdlcigpLmdldFNlcnZlcihzZXJ2ZXJJZCk7CgkJCWlmIChzZXJ2ZXIgPT0gbnVsbCkKCQkJCXRocm93IG5ldyBSdW50aW1lRXhjZXB0aW9uKCJTZXJ2ZXIgY291bGQgbm90IGJlIGZvdW5kOiAiICsgc2VydmVySWQgKyAiICIgKyBzZXJ2ZXIpOwoJCQlTdHJpbmcgbmV3UG9ydFN0ciA9IG1lbWVudG8uZ2V0U3RyaW5nKCJwb3J0Iik7CgkJCWlmIChuZXdQb3J0U3RyICE9IG51bGwgJiYgbmV3UG9ydFN0ci5sZW5ndGgoKSA+IDApCgkJCQluZXdQb3J0ID0gSW50ZWdlci5wYXJzZUludChuZXdQb3J0U3RyKTsKCQkJU3RyaW5nIHBvcnRJZCA9IG1lbWVudG8uZ2V0U3RyaW5nKCJwb3J0SWQiKTsKCQkJCgkJCUlNb25pdG9yYWJsZVNlcnZlciBtcyA9IChJTW9uaXRvcmFibGVTZXJ2ZXIpIHNlcnZlci5nZXREZWxlZ2F0ZSgpOwoJCQlJdGVyYXRvciBpdGVyYXRvciA9IG1zLmdldFNlcnZlclBvcnRzKCkuaXRlcmF0b3IoKTsKCQkJd2hpbGUgKHBvcnQgPT0gbnVsbCAmJiBpdGVyYXRvci5oYXNOZXh0KCkpIHsKCQkJCUlTZXJ2ZXJQb3J0IHNwID0gKElTZXJ2ZXJQb3J0KSBpdGVyYXRvci5uZXh0KCk7CgkJCQlpZiAoc3AuZ2V0SWQoKSAhPSBudWxsICYmIHNwLmdldElkKCkuZXF1YWxzKHBvcnRJZCkpCgkJCQkJcG9ydCA9IHNwOwoJCQl9CgkJCWlmIChwb3J0ID09IG51bGwpCgkJCQl0aHJvdyBuZXcgUnVudGltZUV4Y2VwdGlvbigiQ291bGQgbm90IHJlbG9jYXRlIHBvcnQ6ICIgKyBzZXJ2ZXJJZCArICIgIiArIHNlcnZlciArICIgIiArIHBvcnRJZCk7CgkJCQoJCQlTdHJpbmcgcyA9IG1lbWVudG8uZ2V0U3RyaW5nKCJjb250ZW50VHlwZXMiKTsKCQkJaWYgKHMgIT0gbnVsbCkKCQkJCWNvbnRlbnQgPSBTZXJ2ZXJQbHVnaW4udG9rZW5pemUocywgIiwiKTsKCQkJCgkJCUJvb2xlYW4gYiA9IG1lbWVudG8uZ2V0Qm9vbGVhbigic3RhcnRlZCIpOwoJCQlpZiAoYiAhPSBudWxsICYmIGIuYm9vbGVhblZhbHVlKCkpIHsKCQkJCXRyeSB7CgkJCQkJbmV3UG9ydCA9IG1vbml0b3Iuc3RhcnRNb25pdG9yaW5nKHNlcnZlciwgcG9ydCwgbmV3UG9ydCk7CgkJCQkJc3RhcnRlZCA9IHRydWU7CgkJCQl9IGNhdGNoIChDb3JlRXhjZXB0aW9uIGUpIHsKCQkJCQlUcmFjZS50cmFjZShUcmFjZS5XQVJOSU5HLCAiQ291bGQgbm90IHJlc3RhcnQgc2VydmVyIG1vbml0b3IiLCBlKTsKCQkJCX0KCQkJfQoJCX0KCX0KCglwdWJsaWMgU2VydmVyTW9uaXRvck1hbmFnZXIoKSB7CgkJTGlzdCBtb25pdG9ycyA9IFNlcnZlckNvcmUuZ2V0U2VydmVyTW9uaXRvcnMoKTsKCQlpZiAoIW1vbml0b3JzLmlzRW1wdHkoKSkKCQkJbW9uaXRvciA9IChJU2VydmVyTW9uaXRvcikgbW9uaXRvcnMuZ2V0KDApOwoJCQoJCWluc3RhbmNlID0gdGhpczsKCQlsb2FkTW9uaXRvcnMoKTsKCX0KCQoJcHVibGljIHN0YXRpYyBTZXJ2ZXJNb25pdG9yTWFuYWdlciBnZXRJbnN0YW5jZSgpIHsKCQlpZiAoaW5zdGFuY2UgPT0gbnVsbCkKCQkJbmV3IFNlcnZlck1vbml0b3JNYW5hZ2VyKCk7CgkJcmV0dXJuIGluc3RhbmNlOwoJfQoJCglwdWJsaWMgc3RhdGljIHZvaWQgc2h1dGRvd24oKSB7CgkJaWYgKGluc3RhbmNlID09IG51bGwpCgkJCXJldHVybjsKCQlpbnN0YW5jZS5zYXZlTW9uaXRvcnMoKTsKCX0KCgkvKioKCSAqIFJldHVybnMgdGhlIG1vbml0b3IgdGhhdCBpcyBjdXJyZW50bHkgYmVpbmcgdXNlZC4KCSAqICAKCSAqIEByZXR1cm4KCSAqLwoJcHVibGljIElTZXJ2ZXJNb25pdG9yIGdldEN1cnJlbnRTZXJ2ZXJNb25pdG9yKCkgewoJCXJldHVybiBtb25pdG9yOwoJfQoKCS8qKgoJICogU3dpdGNoIHRvIHVzZSBhIGRpZmZlcmVudCBzZXJ2ZXIgbW9uaXRvci4gQWxsIGV4aXN0aW5nIG1vbml0b3JzIHdpbGwgYmUKCSAqIHJlbW92ZWQgZnJvbSB0aGUgY3VycmVudCBtb25pdG9yIGFuZCBhZGRlZCB0byB0aGUgbmV3IG1vbml0b3IuCgkgKiAKCSAqIEBwYXJhbSBuZXdNb25pdG9yCgkgKiBAdGhyb3dzIG9yZy5lY2xpcHNlLmNvcmUucnVudGltZS5Db3JlRXhjZXB0aW9uCgkgKi8KCXB1YmxpYyB2b2lkIHNldFNlcnZlck1vbml0b3IoSVNlcnZlck1vbml0b3IgbmV3TW9uaXRvcikgdGhyb3dzIENvcmVFeGNlcHRpb24gewoJCXRocm93IG5ldyBDb3JlRXhjZXB0aW9uKG5ldyBTdGF0dXMoSVN0YXR1cy5FUlJPUiwgU2VydmVyQ29yZS5QTFVHSU5fSUQsIDAsICJOb3QgaW1wbGVtZW50ZWQgeWV0IiwgbnVsbCkpOwoJfQoKCS8qKgoJICogUmV0dXJucyB0aGUgbGlzdCBvZiBwb3J0cyB0aGF0IGFyZSBjdXJyZW50bHkgYmVpbmcgbW9uaXRvcmVkLgoJICoKCSAqIEByZXR1cm4KCSAqLwoJcHVibGljIExpc3QgZ2V0TW9uaXRvcmVkUG9ydHMoSVNlcnZlciBzZXJ2ZXIpIHsKCQlMaXN0IGxpc3QgPSBuZXcgQXJyYXlMaXN0KCk7CgkJSXRlcmF0b3IgaXRlcmF0b3IgPSBwb3J0cy5pdGVyYXRvcigpOwoJCXdoaWxlIChpdGVyYXRvci5oYXNOZXh0KCkpIHsKCQkJTW9uaXRvcmVkUG9ydCBtcCA9IChNb25pdG9yZWRQb3J0KSBpdGVyYXRvci5uZXh0KCk7CgkJCWlmIChtcC5zZXJ2ZXIuZXF1YWxzKHNlcnZlcikpCgkJCQlsaXN0LmFkZChtcCk7CgkJfQoJCXJldHVybiBsaXN0OwoJfQoKCS8qKgoJICogU3RhcnRzIG1vbml0b3JpbmcgdGhlIGdpdmVuIHBvcnQsIGFuZCByZXR1cm5zIHRoZSBuZXcgcG9ydCAjIHRvIHVzZSB0aGF0IHdpbGwKCSAqIHJvdXRlIHRvIHRoZSBtb25pdG9yZWQgcG9ydC4KCSAqIAoJICogQHBhcmFtIHBvcnQKCSAqIEByZXR1cm4KCSAqIEB0aHJvd3Mgb3JnLmVjbGlwc2UuY29yZS5ydW50aW1lLkNvcmVFeGNlcHRpb24KCSAqLwoJcHVibGljIElNb25pdG9yZWRTZXJ2ZXJQb3J0IGNyZWF0ZU1vbml0b3IoSVNlcnZlciBzZXJ2ZXIsIElTZXJ2ZXJQb3J0IHBvcnQsIGludCBtb25pdG9yUG9ydCwgU3RyaW5nW10gY29udGVudCkgewoJCWlmIChwb3J0ID09IG51bGwgfHwgbW9uaXRvciA9PSBudWxsKQoJCQlyZXR1cm4gbnVsbDsKCQkKCQkvL2ludCBtcG9ydCA9IG1vbml0b3Iuc3RhcnRNb25pdG9yaW5nKHNlcnZlciwgcG9ydCwgbW9uaXRvclBvcnQpOwoJCU1vbml0b3JlZFBvcnQgbXAgPSBuZXcgTW9uaXRvcmVkUG9ydChzZXJ2ZXIsIHBvcnQsIG1vbml0b3JQb3J0LCBjb250ZW50KTsKCQlwb3J0cy5hZGQobXApOwoJCXJldHVybiBtcDsKCQkvKn0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCVRyYWNlLnRyYWNlKFRyYWNlLlNFVkVSRSwgIkNvdWxkIG5vdCBtb25pdG9yIiwgZSk7CgkJCXRocm93IG5ldyBDb3JlRXhjZXB0aW9uKG5ldyBTdGF0dXMoSVN0YXR1cy5FUlJPUiwgU2VydmVyQ29yZS5QTFVHSU5fSUQsIDAsICJFcnJvciBjcmVhdGluZyBtb25pdG9yIiwgbnVsbCkpOwoJCX0qLwoJfQoKCS8qKgoJICogU3RvcCBtb25pdG9yaW5nIHRoZSBnaXZlbiBwb3J0LiBUaHJvd3MgYSBDb3JlRXhjZXB0aW9uIGlmIHRoZXJlIHdhcyBhIHByb2JsZW0KCSAqIHN0b3BwaW5nIHRoZSBtb25pdG9yaW5nCgkgKgoJICogQHBhcmFtIHBvcnQKCSAqIEB0aHJvd3Mgb3JnLmVjbGlwc2UuY29yZS5ydW50aW1lLkNvcmVFeGNlcHRpb24KCSAqLwoJcHVibGljIHZvaWQgcmVtb3ZlTW9uaXRvcihJTW9uaXRvcmVkU2VydmVyUG9ydCBwb3J0KSB7CgkJaWYgKHBvcnQgPT0gbnVsbCkKCQkJcmV0dXJuOwoKCQl0cnkgewoJCQlwb3J0cy5yZW1vdmUocG9ydCk7CgkJCWlmIChwb3J0LmlzU3RhcnRlZCgpKQoJCQkJbW9uaXRvci5zdG9wTW9uaXRvcmluZyhwb3J0LmdldFNlcnZlcigpLCBwb3J0LmdldFNlcnZlclBvcnQoKSk7CgkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiQ291bGQgbm90IHJlbW92ZSBtb25pdG9yIiwgZSk7CgkJfQoJfQoKCS8qKgoJICogU3RhcnQgdGhlIG1vbml0b3IuIElmIHRoZSBtc3AgcG9ydCBpcyAtMSwgaXQgd2lsbCBiZSB1cGRhdGVkIHRvIHRoZSBwb3J0IHRoYXQgaXMgYWN0dWFsbHkgaW4gdXNlLgoJICogCgkgKiBAcGFyYW0gcG9ydAoJICogQHRocm93cyBDb3JlRXhjZXB0aW9uCgkgKi8KCXB1YmxpYyB2b2lkIHN0YXJ0TW9uaXRvcihJTW9uaXRvcmVkU2VydmVyUG9ydCBtc3ApIHRocm93cyBDb3JlRXhjZXB0aW9uIHsKCQlpZiAobXNwID09IG51bGwgfHwgbXNwLmlzU3RhcnRlZCgpKQoJCQlyZXR1cm47CgkJCgkJTW9uaXRvcmVkUG9ydCBwb3J0ID0gKE1vbml0b3JlZFBvcnQpIG1zcDsKCQlwb3J0LnNldE1vbml0b3JQb3J0KG1vbml0b3Iuc3RhcnRNb25pdG9yaW5nKG1zcC5nZXRTZXJ2ZXIoKSwgbXNwLmdldFNlcnZlclBvcnQoKSwgbXNwLmdldE1vbml0b3JQb3J0KCkpKTsKCQlwb3J0LnNldFN0YXJ0ZWQodHJ1ZSk7Cgl9CgoJLyoqCgkgKiBTdG9wIG1vbml0b3JpbmcuCgkgKiAKCSAqIEBwYXJhbSBwb3J0CgkgKi8KCXB1YmxpYyB2b2lkIHN0b3BNb25pdG9yKElNb25pdG9yZWRTZXJ2ZXJQb3J0IG1zcCkgewoJCWlmIChtc3AgPT0gbnVsbCB8fCAhbXNwLmlzU3RhcnRlZCgpKQoJCQlyZXR1cm47CgkJTW9uaXRvcmVkUG9ydCBwb3J0ID0gKE1vbml0b3JlZFBvcnQpIG1zcDsKCQltb25pdG9yLnN0b3BNb25pdG9yaW5nKG1zcC5nZXRTZXJ2ZXIoKSwgbXNwLmdldFNlcnZlclBvcnQoKSk7CgkJcG9ydC5zZXRTdGFydGVkKGZhbHNlKTsKCX0KCgkvKioKCSAqIFJldHVybnMgdGhlIG1hcHBlZCBwb3J0IHRvIHVzZSB3aGVuIG1ha2luZyByZXF1ZXN0cyB0byB0aGUgZ2l2ZW4gc2VydmVyCgkgKiBhbmQgcG9ydCBudW1iZXIuIFJldHVybnMgdGhlIGV4aXN0aW5nIHBvcnQgbnVtYmVyIGlmIHRoZSBwb3J0IGlzIG5vdCBiZWluZwoJICogbW9uaXRvcmVkLgoJICogCgkgKiBAcGFyYW0gcG9ydAoJICogQHJldHVybgoJICovCglwdWJsaWMgaW50IGdldE1vbml0b3JlZFBvcnQoSVNlcnZlciBzZXJ2ZXIsIGludCBwb3J0LCBTdHJpbmcgY29udGVudCkgewoJCXRyeSB7CgkJCUl0ZXJhdG9yIGl0ZXJhdG9yID0gcG9ydHMuaXRlcmF0b3IoKTsKCQkJd2hpbGUgKGl0ZXJhdG9yLmhhc05leHQoKSkgewoJCQkJTW9uaXRvcmVkUG9ydCBtcCA9IChNb25pdG9yZWRQb3J0KSBpdGVyYXRvci5uZXh0KCk7CgkJCQlpZiAobXAuaXNTdGFydGVkKCkgJiYgbXAuc2VydmVyLmVxdWFscyhzZXJ2ZXIpICYmIG1wLnBvcnQuZ2V0UG9ydCgpID09IHBvcnQpIHsKCQkJCQlTdHJpbmdbXSBjb250ZW50VHlwZXMgPSBtcC5nZXRDb250ZW50VHlwZXMoKTsKCQkJCQlib29sZWFuIGZvdW5kID0gZmFsc2U7CgkJCQkJaWYgKGNvbnRlbnQgPT0gbnVsbCB8fCBjb250ZW50VHlwZXMgIT0gbnVsbCkgewoJCQkJCQlpbnQgc2l6ZSA9IGNvbnRlbnRUeXBlcy5sZW5ndGg7CgkJCQkJCWZvciAoaW50IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKQoJCQkJCQkJaWYgKGNvbnRlbnQuZXF1YWxzKGNvbnRlbnRUeXBlc1tpXSkpCgkJCQkJCQkJZm91bmQgPSB0cnVlOwoJCQkJCX0gZWxzZQoJCQkJCQlmb3VuZCA9IHRydWU7CgkJCQkJaWYgKGZvdW5kICYmIG1wLm5ld1BvcnQgIT0gLTEpCgkJCQkJCXJldHVybiBtcC5uZXdQb3J0OwoJCQkJfQoJCQl9CgkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsgfQoJCXJldHVybiBwb3J0OwoJfQoJCglwcm90ZWN0ZWQgdm9pZCBzYXZlTW9uaXRvcnMoKSB7CgkJU3RyaW5nIGZpbGVuYW1lID0gU2VydmVyUGx1Z2luLmdldEluc3RhbmNlKCkuZ2V0U3RhdGVMb2NhdGlvbigpLmFwcGVuZChNT05JVE9SX0RBVEFfRklMRSkudG9PU1N0cmluZygpOwoJCXRyeSB7CgkJCVhNTE1lbWVudG8gbWVtZW50byA9IFhNTE1lbWVudG8uY3JlYXRlV3JpdGVSb290KCJtb25pdG9ycyIpOwoKCQkJSXRlcmF0b3IgaXRlcmF0b3IgPSBwb3J0cy5pdGVyYXRvcigpOwoJCQl3aGlsZSAoaXRlcmF0b3IuaGFzTmV4dCgpKSB7CgkJCQlNb25pdG9yZWRQb3J0IG1wID0gKE1vbml0b3JlZFBvcnQpIGl0ZXJhdG9yLm5leHQoKTsKCQkJCWlmIChtcC5jYW5TYXZlKCkpIHsKCQkJCQlJTWVtZW50byBjaGlsZCA9IG1lbWVudG8uY3JlYXRlQ2hpbGQoIm1vbml0b3IiKTsKCQkJCQltcC5zYXZlKGNoaWxkKTsKCQkJCX0KCQkJfQoJCQkKCQkJbWVtZW50by5zYXZlVG9GaWxlKGZpbGVuYW1lKTsKCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQlUcmFjZS50cmFjZShUcmFjZS5TRVZFUkUsICJFcnJvciBzYXZpbmcgbW9uaXRvciBpbmZvIiwgZSk7CgkJfQoJfQoJCglwcm90ZWN0ZWQgdm9pZCBsb2FkTW9uaXRvcnMoKSB7CgkJVHJhY2UudHJhY2UoVHJhY2UuRklORVNULCAiTG9hZGluZyBtb25pdG9yIGluZm8iKTsKCQlTdHJpbmcgZmlsZW5hbWUgPSBTZXJ2ZXJQbHVnaW4uZ2V0SW5zdGFuY2UoKS5nZXRTdGF0ZUxvY2F0aW9uKCkuYXBwZW5kKE1PTklUT1JfREFUQV9GSUxFKS50b09TU3RyaW5nKCk7CgkJCgkJdHJ5IHsKCQkJSU1lbWVudG8gbWVtZW50byA9IFhNTE1lbWVudG8ubG9hZE1lbWVudG8oZmlsZW5hbWUpOwoJCQkKCQkJSU1lbWVudG9bXSBjaGlsZHJlbiA9IG1lbWVudG8uZ2V0Q2hpbGRyZW4oIm1vbml0b3IiKTsKCQkJaW50IHNpemUgPSBjaGlsZHJlbi5sZW5ndGg7CgkJCQoJCQlmb3IgKGludCBpID0gMDsgaSA8IHNpemU7IGkrKykgewoJCQkJdHJ5IHsKCQkJCQlNb25pdG9yZWRQb3J0IG1wID0gbmV3IE1vbml0b3JlZFBvcnQoY2hpbGRyZW5baV0pOwoJCQkJCXBvcnRzLmFkZChtcCk7CgkJCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkJCVRyYWNlLnRyYWNlKFRyYWNlLldBUk5JTkcsICJDb3VsZCBub3QgbG9hZCBtb25pdG9yOiAiICsgZSk7CgkJCQl9CgkJCX0KCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQlUcmFjZS50cmFjZShUcmFjZS5XQVJOSU5HLCAiQ291bGQgbm90IGxvYWQgbW9uaXRvciBpbmZvOiAiICsgZS5nZXRNZXNzYWdlKCkpOwoJCX0KCX0KfQ==