LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogQ29weXJpZ2h0IChjKSAyMDAzLCAyMDA1IElCTSBDb3Jwb3JhdGlvbiBhbmQgb3RoZXJzLgogKiBBbGwgcmlnaHRzIHJlc2VydmVkLiBUaGlzIHByb2dyYW0gYW5kIHRoZSBhY2NvbXBhbnlpbmcgbWF0ZXJpYWxzCiAqIGFyZSBtYWRlIGF2YWlsYWJsZSB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEVjbGlwc2UgUHVibGljIExpY2Vuc2UgdjEuMAogKiB3aGljaCBhY2NvbXBhbmllcyB0aGlzIGRpc3RyaWJ1dGlvbiwgYW5kIGlzIGF2YWlsYWJsZSBhdAogKiBodHRwOi8vd3d3LmVjbGlwc2Uub3JnL2xlZ2FsL2VwbC12MTAuaHRtbAqgKiAKICogQ29udHJpYnV0b3JzOgogKiAgICAgSUJNIENvcnBvcmF0aW9uIC0gSW5pdGlhbCBBUEkgYW5kIGltcGxlbWVudGF0aW9uCiAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLwpwYWNrYWdlIG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIudWkuaW50ZXJuYWwuYWN0aW9uczsKCmltcG9ydCBqYXZhLnV0aWwuQXJyYXlMaXN0OwppbXBvcnQgamF2YS51dGlsLkhhc2hNYXA7CmltcG9ydCBqYXZhLnV0aWwuSXRlcmF0b3I7CmltcG9ydCBqYXZhLnV0aWwuTWFwOwoKaW1wb3J0IG9yZy5lY2xpcHNlLmNvcmUucnVudGltZS4qOwppbXBvcnQgb3JnLmVjbGlwc2UuZGVidWcuY29yZS5JTGF1bmNoTWFuYWdlcjsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLmFjdGlvbi5JQWN0aW9uOwppbXBvcnQgb3JnLmVjbGlwc2UuamZhY2UuZGlhbG9ncy5FcnJvckRpYWxvZzsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLmRpYWxvZ3MuSURpYWxvZ0NvbnN0YW50czsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLmRpYWxvZ3MuTWVzc2FnZURpYWxvZzsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLnZpZXdlcnMuSVNlbGVjdGlvbjsKaW1wb3J0IG9yZy5lY2xpcHNlLmpmYWNlLnZpZXdlcnMuSVN0cnVjdHVyZWRTZWxlY3Rpb247CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS53aW5kb3cuV2luZG93OwppbXBvcnQgb3JnLmVjbGlwc2UuamZhY2Uud2l6YXJkLldpemFyZERpYWxvZzsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIuY29yZS4qOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNlcnZlci5jb3JlLmludGVybmFsLklDbGllbnQ7CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc2VydmVyLmNvcmUuaW50ZXJuYWwuSUxhdW5jaGFibGVBZGFwdGVyOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNlcnZlci5jb3JlLmludGVybmFsLlB1Ymxpc2hTZXJ2ZXJKb2I7CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc2VydmVyLmNvcmUuaW50ZXJuYWwuUmVzdGFydFNlcnZlckpvYjsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIuY29yZS5pbnRlcm5hbC5TZXJ2ZXJQbHVnaW47CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc2VydmVyLmNvcmUuaW50ZXJuYWwuU2VydmVyVHlwZTsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIuY29yZS5pbnRlcm5hbC5TdGFydFNlcnZlckpvYjsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIudWkuaW50ZXJuYWwuKjsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIudWkuaW50ZXJuYWwud2l6YXJkLio7CmltcG9ydCBvcmcuZWNsaXBzZS5zd3Qud2lkZ2V0cy5EaXNwbGF5OwppbXBvcnQgb3JnLmVjbGlwc2Uuc3d0LndpZGdldHMuU2hlbGw7CmltcG9ydCBvcmcuZWNsaXBzZS51aS5JV29ya2JlbmNoV2luZG93OwppbXBvcnQgb3JnLmVjbGlwc2UudWkuSVdvcmtiZW5jaFdpbmRvd0FjdGlvbkRlbGVnYXRlOwovKioKICogU3VwcG9ydCBmb3Igc3RhcnRpbmcvc3RvcHBpbmcgc2VydmVyIGFuZCBjbGllbnRzIGZvciByZXNvdXJjZXMgcnVubmluZyBvbiBhIHNlcnZlci4KICovCnB1YmxpYyBjbGFzcyBSdW5PblNlcnZlckFjdGlvbkRlbGVnYXRlIGltcGxlbWVudHMgSVdvcmtiZW5jaFdpbmRvd0FjdGlvbkRlbGVnYXRlIHsKCXByb3RlY3RlZCBzdGF0aWMgZmluYWwgU3RyaW5nW10gbGF1bmNoTW9kZXMgPSB7CgkJSUxhdW5jaE1hbmFnZXIuUlVOX01PREUsIElMYXVuY2hNYW5hZ2VyLkRFQlVHX01PREUsIElMYXVuY2hNYW5hZ2VyLlBST0ZJTEVfTU9ERSB9OwoKCXByb3RlY3RlZCBPYmplY3Qgc2VsZWN0aW9uOwoKCXByb3RlY3RlZCBJV29ya2JlbmNoV2luZG93IHdpbmRvdzsKCglwcm90ZWN0ZWQgc3RhdGljIE9iamVjdCBnbG9iYWxTZWxlY3Rpb247CgoJcHJvdGVjdGVkIHN0YXRpYyBNYXAgZ2xvYmFsTGF1bmNoTW9kZTsKCQoJcHJvdGVjdGVkIGJvb2xlYW4gdGFza3NSdW47CgoJLyoqCgkgKiBSdW5PblNlcnZlckFjdGlvbkRlbGVnYXRlIGNvbnN0cnVjdG9yIGNvbW1lbnQuCgkgKi8KCXB1YmxpYyBSdW5PblNlcnZlckFjdGlvbkRlbGVnYXRlKCkgewoJCXN1cGVyKCk7Cgl9CgoJLyoqCgkgKiBEaXNwb3NlcyB0aGlzIGFjdGlvbiBkZWxlZ2F0ZS4gIFRoZSBpbXBsZW1lbnRvciBzaG91bGQgdW5ob29rIGFueSByZWZlcmVuY2VzCgkgKiB0byBpdHNlbGYgc28gdGhhdCBnYXJiYWdlIGNvbGxlY3Rpb24gY2FuIG9jY3VyLgoJICovCglwdWJsaWMgdm9pZCBkaXNwb3NlKCkgewoJCXdpbmRvdyA9IG51bGw7Cgl9CgoJLyoqCgkgKiBJbml0aWFsaXplcyB0aGlzIGFjdGlvbiBkZWxlZ2F0ZSB3aXRoIHRoZSB3b3JrYmVuY2ggd2luZG93IGl0IHdpbGwgd29yayBpbi4KCSAqCgkgKiBAcGFyYW0gbmV3V2luZG93IHRoZSB3aW5kb3cgdGhhdCBwcm92aWRlcyB0aGUgY29udGV4dCBmb3IgdGhpcyBkZWxlZ2F0ZQoJICovCglwdWJsaWMgdm9pZCBpbml0KElXb3JrYmVuY2hXaW5kb3cgbmV3V2luZG93KSB7CgkJd2luZG93ID0gbmV3V2luZG93OwoJfQoJCglwdWJsaWMgSVNlcnZlciBnZXRTZXJ2ZXIoSU1vZHVsZSBtb2R1bGUsIFN0cmluZyBsYXVuY2hNb2RlLCBJUHJvZ3Jlc3NNb25pdG9yIG1vbml0b3IpIHsKCQlJU2VydmVyIHNlcnZlciA9IFNlcnZlckNvcmUuZ2V0RGVmYXVsdFNlcnZlcihtb2R1bGUpOwoJCQoJCS8vIGlnbm9yZSBwcmVmZXJlbmNlIGlmIHRoZSBzZXJ2ZXIgZG9lc24ndCBzdXBwb3J0IHRoaXMgbW9kZS4KCQlpZiAoc2VydmVyICE9IG51bGwgJiYgIVNlcnZlclVJUGx1Z2luLmlzQ29tcGF0aWJsZVdpdGhMYXVuY2hNb2RlKHNlcnZlciwgbGF1bmNoTW9kZSkpCgkJCXNlcnZlciA9IG51bGw7CgkJCgkJaWYgKHNlcnZlciAhPSBudWxsICYmICFTZXJ2ZXJVdGlsLmNvbnRhaW5zTW9kdWxlKHNlcnZlciwgbW9kdWxlLCBtb25pdG9yKSkgewoJCQlJU2VydmVyV29ya2luZ0NvcHkgd2MgPSBzZXJ2ZXIuY3JlYXRlV29ya2luZ0NvcHkoKTsKCQkJdHJ5IHsKCQkJCVNlcnZlclV0aWwubW9kaWZ5TW9kdWxlcyh3YywgbmV3IElNb2R1bGVbXSB7IG1vZHVsZSB9LCBuZXcgSU1vZHVsZVswXSwgbW9uaXRvcik7CgkJCQl3Yy5zYXZlKGZhbHNlLCBtb25pdG9yKTsKCQkJfSBjYXRjaCAoQ29yZUV4Y2VwdGlvbiBjZSkgewoJCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiQ291bGQgbm90IGFkZCBtb2R1bGUgdG8gc2VydmVyIiwgY2UpOwoJCQkJc2VydmVyID0gbnVsbDsKCQkJfQoJCX0KCQkKCQlTaGVsbCBzaGVsbDsKCQlpZiAod2luZG93ICE9IG51bGwpCgkJCXNoZWxsID0gd2luZG93LmdldFNoZWxsKCk7CgkJZWxzZQoJCQlzaGVsbCA9IFNlcnZlclVJUGx1Z2luLmdldEluc3RhbmNlKCkuZ2V0V29ya2JlbmNoKCkuZ2V0QWN0aXZlV29ya2JlbmNoV2luZG93KCkuZ2V0U2hlbGwoKTsKCgkJaWYgKHNlcnZlciA9PSBudWxsKSB7CgkJCS8vIHRyeSB0aGUgZnVsbCB3aXphcmQKCQkJUnVuT25TZXJ2ZXJXaXphcmQgd2l6YXJkID0gbmV3IFJ1bk9uU2VydmVyV2l6YXJkKG1vZHVsZSwgbGF1bmNoTW9kZSk7CgkJCUNsb3NhYmxlV2l6YXJkRGlhbG9nIGRpYWxvZyA9IG5ldyBDbG9zYWJsZVdpemFyZERpYWxvZyhzaGVsbCwgd2l6YXJkKTsKCQkJaWYgKGRpYWxvZy5vcGVuKCkgPT0gV2luZG93LkNBTkNFTCkgewoJCQkJbW9uaXRvci5zZXRDYW5jZWxlZCh0cnVlKTsKCQkJCXJldHVybiBudWxsOwoJCQl9CgoJCQl0cnkgewoJCQkJUGxhdGZvcm0uZ2V0Sm9iTWFuYWdlcigpLmpvaW4oIm9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIudWkuZmFtaWx5IiwgbnVsbCk7CgkJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCQlUcmFjZS50cmFjZShUcmFjZS5XQVJOSU5HLCAiRXJyb3Igd2FpdGluZyBmb3Igam9iIiwgZSk7CgkJCX0KCQkJc2VydmVyID0gd2l6YXJkLmdldFNlcnZlcigpOwoJCQlib29sZWFuIHByZWZlcnJlZCA9IHdpemFyZC5pc1ByZWZlcnJlZFNlcnZlcigpOwoJCQl0YXNrc1J1biA9IHRydWU7CgoJCQkvLyBzZXQgcHJlZmVycmVkIHNlcnZlciBpZiByZXF1ZXN0ZWQKCQkJaWYgKHNlcnZlciAhPSBudWxsICYmIHByZWZlcnJlZCkgewoJCQkJdHJ5IHsKCQkJCQlTZXJ2ZXJDb3JlLnNldERlZmF1bHRTZXJ2ZXIobW9kdWxlLCBzZXJ2ZXIsIG1vbml0b3IpOwoJCQkJfSBjYXRjaCAoQ29yZUV4Y2VwdGlvbiBjZSkgewoJCQkJCVN0cmluZyBtZXNzYWdlID0gTWVzc2FnZXMuZXJyb3JDb3VsZE5vdFNhdmVQcmVmZXJlbmNlOwoJCQkJCUVycm9yRGlhbG9nLm9wZW5FcnJvcihzaGVsbCwgTWVzc2FnZXMuZXJyb3JEaWFsb2dUaXRsZSwgbWVzc2FnZSwgY2UuZ2V0U3RhdHVzKCkpOwoJCQkJfQoJCQl9CgkJfQoJCQoJCXRyeSB7CgkJCVBsYXRmb3JtLmdldEpvYk1hbmFnZXIoKS5qb2luKCJvcmcuZWNsaXBzZS53c3Quc2VydmVyLnVpLmZhbWlseSIsIG5ldyBOdWxsUHJvZ3Jlc3NNb25pdG9yKCkpOwoJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCVRyYWNlLnRyYWNlKFRyYWNlLldBUk5JTkcsICJFcnJvciB3YWl0aW5nIGZvciBqb2IiLCBlKTsKCQl9CgkJCgkJcmV0dXJuIHNlcnZlcjsKCX0KCgkvKioKCSAqIFJ1biB0aGUgcmVzb3VyY2Ugb24gYSBzZXJ2ZXIuCgkgKgoJICogQHBhcmFtIG1vbml0b3Igb3JnLmVjbGlwc2UuY29yZS5ydW50aW1lLklQcm9ncmVzc01vbml0b3IKCSAqLwoJcHJvdGVjdGVkIHZvaWQgcnVuKElQcm9ncmVzc01vbml0b3IgbW9uaXRvcikgewoJCWZpbmFsIFN0cmluZyBsYXVuY2hNb2RlMiA9IGdldExhdW5jaE1vZGUoKTsKCQlmaW5hbCBJTW9kdWxlQXJ0aWZhY3QgbW9kdWxlQXJ0aWZhY3QgPSBTZXJ2ZXJQbHVnaW4ubG9hZE1vZHVsZUFydGlmYWN0KHNlbGVjdGlvbik7CgkJCgkJU2hlbGwgc2hlbGwyID0gbnVsbDsKCQlpZiAod2luZG93ICE9IG51bGwpCgkJCXNoZWxsMiA9IHdpbmRvdy5nZXRTaGVsbCgpOwoJCWVsc2UgewoJCQl0cnkgewoJCQkJc2hlbGwyID0gU2VydmVyVUlQbHVnaW4uZ2V0SW5zdGFuY2UoKS5nZXRXb3JrYmVuY2goKS5nZXRBY3RpdmVXb3JrYmVuY2hXaW5kb3coKS5nZXRTaGVsbCgpOwoJCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkJLy8gaWdub3JlCgkJCX0KCQkJaWYgKHNoZWxsMiA9PSBudWxsKQoJCQkJc2hlbGwyID0gRGlzcGxheS5nZXREZWZhdWx0KCkuZ2V0QWN0aXZlU2hlbGwoKTsKCQl9CgkJZmluYWwgU2hlbGwgc2hlbGwgPSBzaGVsbDI7CgoJCWlmIChtb2R1bGVBcnRpZmFjdCA9PSBudWxsIHx8IG1vZHVsZUFydGlmYWN0LmdldE1vZHVsZSgpID09IG51bGwpIHsKCQkJRWNsaXBzZVV0aWwub3BlbkVycm9yKE1lc3NhZ2VzLmVycm9yTm9Nb2R1bGVzKTsKCQkJVHJhY2UudHJhY2UoVHJhY2UuRklORVNULCAiTm8gbW9kdWxlcyIpOwoJCQlyZXR1cm47CgkJfQoJCWZpbmFsIElNb2R1bGUgbW9kdWxlID0gbW9kdWxlQXJ0aWZhY3QuZ2V0TW9kdWxlKCk7CgoJCS8vIGNoZWNrIGZvciBzZXJ2ZXJzIHdpdGggdGhlIGdpdmVuIHN0YXJ0IG1vZGUKCQlJU2VydmVyW10gc2VydmVycyA9IFNlcnZlckNvcmUuZ2V0U2VydmVycygpOwoJCWJvb2xlYW4gZm91bmQgPSBmYWxzZTsKCQlpZiAoc2VydmVycyAhPSBudWxsKSB7CgkJCWludCBzaXplID0gc2VydmVycy5sZW5ndGg7CgkJCWZvciAoaW50IGkgPSAwOyBpIDwgc2l6ZSAmJiAhZm91bmQ7IGkrKykgewoJCQkJaWYgKFNlcnZlclVJUGx1Z2luLmlzQ29tcGF0aWJsZVdpdGhMYXVuY2hNb2RlKHNlcnZlcnNbaV0sIGxhdW5jaE1vZGUyKSkgewoJCQkJCXRyeSB7CgkJCQkJCUlNb2R1bGVbXSBwYXJlbnRzID0gc2VydmVyc1tpXS5nZXRSb290TW9kdWxlcyhtb2R1bGUsIG1vbml0b3IpOwoJCQkJCQlpZiAocGFyZW50cyAhPSBudWxsICYmIHBhcmVudHMubGVuZ3RoID4gMCkKCQkJCQkJCWZvdW5kID0gdHJ1ZTsKCQkJCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkJCQkvLyBpZ25vcmUKCQkJCQl9CgkJCQl9CgkJCX0KCQl9CgoJCWlmICghZm91bmQpIHsKCQkJLy8gbm8gZXhpc3Rpbmcgc2VydmVyIHN1cHBvcnRzIHRoZSBwcm9qZWN0IGFuZCBzdGFydCBtb2RlIQoJCQkvLyBjaGVjayBpZiB0aGVyZSBtaWdodCBiZSBhbm90aGVyIG9uZSB0aGF0IGNhbiBiZSBjcmVhdGVkCgkJCUlTZXJ2ZXJUeXBlW10gc2VydmVyVHlwZXMgPSBTZXJ2ZXJDb3JlLmdldFNlcnZlclR5cGVzKCk7CgkJCWJvb2xlYW4gZm91bmQyID0gZmFsc2U7CgkJCWlmIChzZXJ2ZXJUeXBlcyAhPSBudWxsKSB7CgkJCQlpbnQgc2l6ZSA9IHNlcnZlclR5cGVzLmxlbmd0aDsKCQkJCWZvciAoaW50IGkgPSAwOyBpIDwgc2l6ZSAmJiAhZm91bmQyOyBpKyspIHsKCQkJCQlJU2VydmVyVHlwZSB0eXBlID0gc2VydmVyVHlwZXNbaV07CgkJCQkJSU1vZHVsZVR5cGVbXSBtb2R1bGVUeXBlcyA9IHR5cGUuZ2V0UnVudGltZVR5cGUoKS5nZXRNb2R1bGVUeXBlcygpOwoJCQkJCWlmICh0eXBlLnN1cHBvcnRzTGF1bmNoTW9kZShsYXVuY2hNb2RlMikgJiYgU2VydmVyVXRpbC5pc1N1cHBvcnRlZE1vZHVsZShtb2R1bGVUeXBlcywgbW9kdWxlLmdldE1vZHVsZVR5cGUoKSkpIHsKCQkJCQkJZm91bmQyID0gdHJ1ZTsKCQkJCQl9CgkJCQl9CgkJCX0KCQkJaWYgKCFmb3VuZDIpIHsKCQkJCUVjbGlwc2VVdGlsLm9wZW5FcnJvcihNZXNzYWdlcy5lcnJvck5vU2VydmVyKTsKCQkJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgIk5vIHNlcnZlciBmb3Igc3RhcnQgbW9kZSIpOwoJCQkJcmV0dXJuOwoJCQl9CgkJfQoJCQoJCWlmICghU2VydmVyVUlQbHVnaW4uc2F2ZUVkaXRvcnMoKSkKCQkJcmV0dXJuOwoKCQl0YXNrc1J1biA9IGZhbHNlOwoJCWZpbmFsIElTZXJ2ZXIgc2VydmVyID0gZ2V0U2VydmVyKG1vZHVsZSwgbGF1bmNoTW9kZTIsIG1vbml0b3IpOwoJCWlmIChtb25pdG9yLmlzQ2FuY2VsZWQoKSkKCQkJcmV0dXJuOwoJCQoJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgIlNlcnZlcjogIiArIHNlcnZlcik7CgkJCgkJaWYgKHNlcnZlciA9PSBudWxsKSB7CgkJCUVjbGlwc2VVdGlsLm9wZW5FcnJvcihNZXNzYWdlcy5lcnJvck5vU2VydmVyKTsKCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiTm8gc2VydmVyIGZvdW5kIik7CgkJCXJldHVybjsKCQl9CgoJCWlmICghU2VydmVyVUlQbHVnaW4ucHJvbXB0SWZEaXJ0eShzaGVsbCwgc2VydmVyKSkKCQkJcmV0dXJuOwoJCQoJCWlmICghdGFza3NSdW4pIHsKCQkJU2VsZWN0VGFza3NXaXphcmQgd2l6YXJkID0gbmV3IFNlbGVjdFRhc2tzV2l6YXJkKHNlcnZlcik7CgkJCXdpemFyZC5hZGRQYWdlcygpOwoJCQlpZiAod2l6YXJkLmhhc1Rhc2tzKCkgJiYgd2l6YXJkLmhhc09wdGlvbmFsVGFza3MoKSkgewoJCQkJV2l6YXJkRGlhbG9nIGRpYWxvZyA9IG5ldyBXaXphcmREaWFsb2coc2hlbGwsIHdpemFyZCk7CgkJCQlpZiAoZGlhbG9nLm9wZW4oKSA9PSBXaW5kb3cuQ0FOQ0VMKQoJCQkJCXJldHVybjsKCQkJfSBlbHNlCgkJCQl3aXphcmQucGVyZm9ybUZpbmlzaCgpOwoJCX0KCQkKCQlUaHJlYWQgdCA9IG5ldyBUaHJlYWQoIlNlcnZlciBsYXVuY2ggc2hvcnRjdXQiKSB7CgkJCXB1YmxpYyB2b2lkIHJ1bigpIHsKCQkJCVN0cmluZyBsYXVuY2hNb2RlID0gbGF1bmNoTW9kZTI7CgkJCQkvLyBnZXQgdGhlIGxhdW5jaGFibGUgYWRhcHRlciBhbmQgbW9kdWxlIG9iamVjdAoJCQkJSUxhdW5jaGFibGVBZGFwdGVyIGxhdW5jaGFibGVBZGFwdGVyID0gbnVsbDsKCQkJCU9iamVjdCBsYXVuY2hhYmxlID0gbnVsbDsKCQkJCUlMYXVuY2hhYmxlQWRhcHRlcltdIGFkYXB0ZXJzID0gU2VydmVyUGx1Z2luLmdldExhdW5jaGFibGVBZGFwdGVycygpOwoJCQkJaWYgKGFkYXB0ZXJzICE9IG51bGwpIHsKCQkJCQlpbnQgc2l6ZTIgPSBhZGFwdGVycy5sZW5ndGg7CgkJCQkJZm9yIChpbnQgaiA9IDA7IGogPCBzaXplMjsgaisrKSB7CgkJCQkJCUlMYXVuY2hhYmxlQWRhcHRlciBhZGFwdGVyID0gYWRhcHRlcnNbal07CgkJCQkJCXRyeSB7CgkJCQkJCQlPYmplY3QgbGF1bmNoYWJsZTIgPSBhZGFwdGVyLmdldExhdW5jaGFibGUoc2VydmVyLCBtb2R1bGVBcnRpZmFjdCk7CgkJCQkJCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICJhZGFwdGVyPSAiICsgYWRhcHRlciArICIsIGxhdW5jaGFibGU9ICIgKyBsYXVuY2hhYmxlMik7CgkJCQkJCQlpZiAobGF1bmNoYWJsZTIgIT0gbnVsbCkgewoJCQkJCQkJCWxhdW5jaGFibGVBZGFwdGVyID0gYWRhcHRlcjsKCQkJCQkJCQlsYXVuY2hhYmxlID0gbGF1bmNoYWJsZTI7CgkJCQkJCQl9CgkJCQkJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCQkJCQlUcmFjZS50cmFjZShUcmFjZS5TRVZFUkUsICJFcnJvciBpbiBsYXVuY2hhYmxlIGFkYXB0ZXIiLCBlKTsKCQkJCQkJfQoJCQkJCX0KCQkJCX0KCQkJCQoJCQkJSUNsaWVudFtdIGNsaWVudHMgPSBuZXcgSUNsaWVudFswXTsKCQkJCWlmIChsYXVuY2hhYmxlICE9IG51bGwpCgkJCQkJY2xpZW50cyA9IGdldENsaWVudHMoc2VydmVyLCBsYXVuY2hhYmxlLCBsYXVuY2hNb2RlKTsKCQkJCQoJCQkJVHJhY2UudHJhY2UoVHJhY2UuRklORVNULCAiTGF1bmNoYWJsZSBjbGllbnRzOiAiICsgY2xpZW50cyk7CgkJCQkKCQkJCUlDbGllbnQgY2xpZW50ID0gbnVsbDsKCQkJCWlmIChjbGllbnRzID09IG51bGwgfHwgY2xpZW50cy5sZW5ndGggPT0gMCkgewoJCQkJCUVjbGlwc2VVdGlsLm9wZW5FcnJvcihNZXNzYWdlcy5lcnJvck5vQ2xpZW50KTsKCQkJCQlUcmFjZS50cmFjZShUcmFjZS5TRVZFUkUsICJObyBsYXVuY2hhYmxlIGNsaWVudHMhIik7CgkJCQkJcmV0dXJuOwoJCQkJfSBlbHNlIGlmIChjbGllbnRzLmxlbmd0aCA9PSAxKSB7CgkJCQkJY2xpZW50ID0gY2xpZW50c1swXTsKCQkJCX0gZWxzZSB7CgkJCQkJU2VsZWN0Q2xpZW50V2l6YXJkIHdpemFyZCA9IG5ldyBTZWxlY3RDbGllbnRXaXphcmQoY2xpZW50cyk7CgkJCQkJQ2xvc2FibGVXaXphcmREaWFsb2cgZGlhbG9nID0gbmV3IENsb3NhYmxlV2l6YXJkRGlhbG9nKHNoZWxsLCB3aXphcmQpOwoJCQkJCWRpYWxvZy5vcGVuKCk7CgkJCQkJY2xpZW50ID0gd2l6YXJkLmdldFNlbGVjdGVkQ2xpZW50KCk7CgkJCQkJaWYgKGNsaWVudCA9PSBudWxsKQoJCQkJCQlyZXR1cm47CgkJCQl9CgkJCQkKCQkJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgIlJlYWR5IHRvIGxhdW5jaCIpOwoJCQkJCgkJCQkvLyBzdGFydCBzZXJ2ZXIgaWYgaXQncyBub3QgYWxyZWFkeSBzdGFydGVkCgkJCQkvLyBhbmQgY3VlIHRoZSBjbGllbnQgdG8gc3RhcnQKCQkJCUlNb2R1bGVbXSBtb2R1bGVzID0gbmV3IElNb2R1bGVbXSB7IG1vZHVsZSB9OyAvLyBUT0RPOiBnZXQgcGFyZW50IGhlaXJhcmNoeSBjb3JyZWN0CgkJCQlpbnQgc3RhdGUgPSBzZXJ2ZXIuZ2V0U2VydmVyU3RhdGUoKTsKCQkJCWlmIChzdGF0ZSA9PSBJU2VydmVyLlNUQVRFX1NUQVJUSU5HKSB7CgkJCQkJTGF1bmNoQ2xpZW50Sm9iIGNsaWVudEpvYiA9IG5ldyBMYXVuY2hDbGllbnRKb2Ioc2VydmVyLCBtb2R1bGVzLCBsYXVuY2hNb2RlLCBtb2R1bGVBcnRpZmFjdCwgbGF1bmNoYWJsZUFkYXB0ZXIsIGNsaWVudCk7CgkJCQkJY2xpZW50Sm9iLnNjaGVkdWxlKCk7CgkJCQl9IGVsc2UgaWYgKHN0YXRlID09IElTZXJ2ZXIuU1RBVEVfU1RBUlRFRCkgewoJCQkJCWJvb2xlYW4gcmVzdGFydCA9IGZhbHNlOwoJCQkJCVN0cmluZyBtb2RlID0gc2VydmVyLmdldE1vZGUoKTsKCQkJCQlpZiAoIUlMYXVuY2hNYW5hZ2VyLkRFQlVHX01PREUuZXF1YWxzKG1vZGUpICYmIElMYXVuY2hNYW5hZ2VyLkRFQlVHX01PREUuZXF1YWxzKGxhdW5jaE1vZGUpKSB7CgkJCQkJCWludCByZXN1bHQgPSBvcGVuV2FybmluZ0RpYWxvZyhzaGVsbCwgTWVzc2FnZXMuZGlhbG9nTW9kZVdhcm5pbmdEZWJ1Zyk7CgkJCQkJCWlmIChyZXN1bHQgPT0gMSkKCQkJCQkJCWxhdW5jaE1vZGUgPSBtb2RlOwoJCQkJCQllbHNlIGlmIChyZXN1bHQgPT0gMCkKCQkJCQkJCXJlc3RhcnQgPSB0cnVlOwoJCQkJCQllbHNlCgkJCQkJCQlyZXR1cm47CgkJCQkJfSBlbHNlIGlmICghSUxhdW5jaE1hbmFnZXIuUFJPRklMRV9NT0RFLmVxdWFscyhtb2RlKSAmJiBJTGF1bmNoTWFuYWdlci5QUk9GSUxFX01PREUuZXF1YWxzKGxhdW5jaE1vZGUpKSB7CgkJCQkJCWludCByZXN1bHQgPSBvcGVuV2FybmluZ0RpYWxvZyhzaGVsbCwgTWVzc2FnZXMuZGlhbG9nTW9kZVdhcm5pbmdQcm9maWxlKTsKCQkJCQkJaWYgKHJlc3VsdCA9PSAxKQoJCQkJCQkJbGF1bmNoTW9kZSA9IG1vZGU7CgkJCQkJCWVsc2UgaWYgKHJlc3VsdCA9PSAwKQoJCQkJCQkJcmVzdGFydCA9IHRydWU7CgkJCQkJCWVsc2UKCQkJCQkJCXJldHVybjsKCQkJCQl9CgkJCQkJCgkJCQkJUHVibGlzaFNlcnZlckpvYiBwdWJsaXNoSm9iID0gbmV3IFB1Ymxpc2hTZXJ2ZXJKb2Ioc2VydmVyLCBJU2VydmVyLlBVQkxJU0hfSU5DUkVNRU5UQUwsIGZhbHNlKTsKCQkJCQlMYXVuY2hDbGllbnRKb2IgY2xpZW50Sm9iID0gbmV3IExhdW5jaENsaWVudEpvYihzZXJ2ZXIsIG1vZHVsZXMsIGxhdW5jaE1vZGUsIG1vZHVsZUFydGlmYWN0LCBsYXVuY2hhYmxlQWRhcHRlciwgY2xpZW50KTsKCQkJCQlwdWJsaXNoSm9iLnNldE5leHRKb2IoY2xpZW50Sm9iKTsKCQkJCQkKCQkJCQlpZiAocmVzdGFydCkgewoJCQkJCQlSZXN0YXJ0U2VydmVySm9iIHJlc3RhcnRKb2IgPSBuZXcgUmVzdGFydFNlcnZlckpvYihzZXJ2ZXIsIGxhdW5jaE1vZGUpOwoJCQkJCQlyZXN0YXJ0Sm9iLnNldE5leHRKb2IocHVibGlzaEpvYik7CgkJCQkJCXJlc3RhcnRKb2Iuc2NoZWR1bGUoKTsKCQkJCQl9IGVsc2UKCQkJCQkJcHVibGlzaEpvYi5zY2hlZHVsZSgpOwoJCQkJfSBlbHNlIGlmIChzdGF0ZSAhPSBJU2VydmVyLlNUQVRFX1NUT1BQSU5HKSB7CgkJCQkJUHVibGlzaFNlcnZlckpvYiBwdWJsaXNoSm9iID0gbmV3IFB1Ymxpc2hTZXJ2ZXJKb2Ioc2VydmVyKTsKCQkJCQlTdGFydFNlcnZlckpvYiBzdGFydFNlcnZlckpvYiA9IG5ldyBTdGFydFNlcnZlckpvYihzZXJ2ZXIsIGxhdW5jaE1vZGUpOwoJCQkJCUxhdW5jaENsaWVudEpvYiBjbGllbnRKb2IgPSBuZXcgTGF1bmNoQ2xpZW50Sm9iKHNlcnZlciwgbW9kdWxlcywgbGF1bmNoTW9kZSwgbW9kdWxlQXJ0aWZhY3QsIGxhdW5jaGFibGVBZGFwdGVyLCBjbGllbnQpOwoJCQkJCQoJCQkJCWlmICgoKFNlcnZlclR5cGUpc2VydmVyLmdldFNlcnZlclR5cGUoKSkuc3RhcnRCZWZvcmVQdWJsaXNoKCkpIHsKCQkJCQkJc3RhcnRTZXJ2ZXJKb2Iuc2V0TmV4dEpvYihwdWJsaXNoSm9iKTsKCQkJCQkJcHVibGlzaEpvYi5zZXROZXh0Sm9iKGNsaWVudEpvYik7CgkJCQkJCXN0YXJ0U2VydmVySm9iLnNjaGVkdWxlKCk7CgkJCQkJfSBlbHNlIHsKCQkJCQkJcHVibGlzaEpvYi5zZXROZXh0Sm9iKHN0YXJ0U2VydmVySm9iKTsKCQkJCQkJc3RhcnRTZXJ2ZXJKb2Iuc2V0TmV4dEpvYihjbGllbnRKb2IpOwoJCQkJCQlwdWJsaXNoSm9iLnNjaGVkdWxlKCk7CgkJCQkJfQoJCQkJfQoJCQl9CgkJfTsKCQl0LnNldERhZW1vbih0cnVlKTsKCQl0LnN0YXJ0KCk7Cgl9CgoJLyoqCgkgKiBSZXR1cm5zIHRoZSBsYXVuY2hhYmxlIGNsaWVudHMgZm9yIHRoZSBnaXZlbiBzZXJ2ZXIgYW5kIGxhdW5jaGFibGUKCSAqIG9iamVjdC4KCSAqCgkgKiBAcGFyYW0gc2VydmVyIG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIuY29yZS5JU2VydmVyCgkgKiBAcGFyYW0gbGF1bmNoYWJsZQoJICogQHBhcmFtIGxhdW5jaE1vZGUgU3RyaW5nCgkgKiBAcmV0dXJuIGFuIGFycmF5IG9mIGNsaWVudHMKCSAqLwoJcHVibGljIHN0YXRpYyBJQ2xpZW50W10gZ2V0Q2xpZW50cyhJU2VydmVyIHNlcnZlciwgT2JqZWN0IGxhdW5jaGFibGUsIFN0cmluZyBsYXVuY2hNb2RlKSB7CgkJQXJyYXlMaXN0IGxpc3QgPSBuZXcgQXJyYXlMaXN0KCk7CgkJSUNsaWVudFtdIGNsaWVudHMgPSBTZXJ2ZXJQbHVnaW4uZ2V0Q2xpZW50cygpOwoJCWlmIChjbGllbnRzICE9IG51bGwpIHsKCQkJaW50IHNpemUgPSBjbGllbnRzLmxlbmd0aDsKCQkJZm9yIChpbnQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHsKCQkJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgImNsaWVudD0gIiArIGNsaWVudHNbaV0pOwoJCQkJaWYgKGNsaWVudHNbaV0uc3VwcG9ydHMoc2VydmVyLCBsYXVuY2hhYmxlLCBsYXVuY2hNb2RlKSkKCQkJCQlsaXN0LmFkZChjbGllbnRzW2ldKTsKCQkJfQoJCX0KCQkKCQlJQ2xpZW50W10gY2xpZW50czIgPSBuZXcgSUNsaWVudFtsaXN0LnNpemUoKV07CgkJbGlzdC50b0FycmF5KGNsaWVudHMyKTsKCQlyZXR1cm4gY2xpZW50czI7Cgl9CgoJLyoqCgkgKiBPcGVuIGEgbWVzc2FnZSBkaWFsb2cuCgkgKiAKCSAqIEBwYXJhbSBzaGVsbAoJICogQHBhcmFtIG1lc3NhZ2UKCSAqIEByZXR1cm4gYSBkaWFsb2cgcmV0dXJuIGNvbnN0YW50CgkgKi8KCXByb3RlY3RlZCBpbnQgb3Blbldhcm5pbmdEaWFsb2coU2hlbGwgc2hlbGwsIFN0cmluZyBtZXNzYWdlKSB7CgkJTWVzc2FnZURpYWxvZyBkaWFsb2cgPSBuZXcgTWVzc2FnZURpYWxvZyhzaGVsbCwgTWVzc2FnZXMuZXJyb3JEaWFsb2dUaXRsZSwgbnVsbCwKCQkJbWVzc2FnZSwJTWVzc2FnZURpYWxvZy5XQVJOSU5HLCBuZXcgU3RyaW5nW10ge01lc3NhZ2VzLmRpYWxvZ01vZGVXYXJuaW5nUmVzdGFydCwKCQkJTWVzc2FnZXMuZGlhbG9nTW9kZVdhcm5pbmdDb250aW51ZSwgSURpYWxvZ0NvbnN0YW50cy5DQU5DRUxfTEFCRUx9LCAwKTsKCQlyZXR1cm4gZGlhbG9nLm9wZW4oKTsKCX0KCgkvKioKCSAqIFRoZSBkZWxlZ2F0aW5nIGFjdGlvbiBoYXMgYmVlbiBwZXJmb3JtZWQuIEltcGxlbWVudAoJICogdGhpcyBtZXRob2QgdG8gZG8gdGhlIGFjdHVhbCB3b3JrLgoJICoKCSAqIEBwYXJhbSBhY3Rpb24gYWN0aW9uIHByb3h5IHRoYXQgaGFuZGxlcyB0aGUgcHJlc2VudGF0aW9uCgkgKiBwb3J0aW9uIG9mIHRoZSBwbHVnaW4gYWN0aW9uCgkgKi8KCXB1YmxpYyB2b2lkIHJ1bihJQWN0aW9uIGFjdGlvbikgewoJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgIlJ1bm5pbmcgb24gU2VydmVyLi4uIik7CgkJdHJ5IHsKCQkJcnVuKG5ldyBOdWxsUHJvZ3Jlc3NNb25pdG9yKCkpOwoJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCVRyYWNlLnRyYWNlKFRyYWNlLlNFVkVSRSwgIlJ1biBvbiBTZXJ2ZXIgRXJyb3IiLCBlKTsKCQl9Cgl9CgkKCXByb3RlY3RlZCBib29sZWFuIGlzRW5hYmxlZCgpIHsKCQl0cnkgewoJCQlCb29sZWFuIGIgPSAoQm9vbGVhbikgZ2xvYmFsTGF1bmNoTW9kZS5nZXQoZ2V0TGF1bmNoTW9kZSgpKTsKCQkJcmV0dXJuIGIuYm9vbGVhblZhbHVlKCk7CgkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJLy8gaWdub3JlCgkJfQoJCXJldHVybiBmYWxzZTsKCX0KCgkvKioKCSAqIFJldHVybnMgdGhlIHN0YXJ0IG1vZGUgdGhhdCB0aGUgc2VydmVyIHNob3VsZCB1c2UuCgkgKi8KCXByb3RlY3RlZCBTdHJpbmcgZ2V0TGF1bmNoTW9kZSgpIHsKCQlyZXR1cm4gSUxhdW5jaE1hbmFnZXIuUlVOX01PREU7Cgl9CgoJLyoqCgkgKiBEZXRlcm1pbmUgd2hpY2ggY2xpZW50cyBjYW4gYWN0IG9uIHRoZSBjdXJyZW50IHNlbGVjdGlvbi4KCSAqCgkgKiBAcGFyYW0gYWN0aW9uIGFjdGlvbiBwcm94eSB0aGF0IGhhbmRsZXMgcHJlc2VudGF0aW9uCgkgKiAgICBwb3J0aW9uIG9mIHRoZSBwbHVnaW4gYWN0aW9uCgkgKiBAcGFyYW0gc2VsIGN1cnJlbnQgc2VsZWN0aW9uIGluIHRoZSBkZXNrdG9wCgkgKi8KCXB1YmxpYyB2b2lkIHNlbGVjdGlvbkNoYW5nZWQoSUFjdGlvbiBhY3Rpb24sIElTZWxlY3Rpb24gc2VsKSB7CgkJVHJhY2UudHJhY2UoVHJhY2UuRklORVNULCAiPiBzZWxlY3Rpb25DaGFuZ2VkIik7CgkJc2VsZWN0aW9uID0gbnVsbDsKCQlsb25nIHRpbWUgPSBTeXN0ZW0uY3VycmVudFRpbWVNaWxsaXMoKTsKCQlpZiAoc2VsID09IG51bGwgfHwgc2VsLmlzRW1wdHkoKSB8fCAhKHNlbCBpbnN0YW5jZW9mIElTdHJ1Y3R1cmVkU2VsZWN0aW9uKSkgewoJCQlhY3Rpb24uc2V0RW5hYmxlZChmYWxzZSk7CgkJCWdsb2JhbFNlbGVjdGlvbiA9IG51bGw7CgkJCXJldHVybjsKCQl9CgoJCUlTdHJ1Y3R1cmVkU2VsZWN0aW9uIHNlbGVjdCA9IChJU3RydWN0dXJlZFNlbGVjdGlvbikgc2VsOwoJCUl0ZXJhdG9yIGl0ZXJhdG9yID0gc2VsZWN0Lml0ZXJhdG9yKCk7CgkJaWYgKGl0ZXJhdG9yLmhhc05leHQoKSkKCQkJc2VsZWN0aW9uID0gaXRlcmF0b3IubmV4dCgpOwoJCWlmIChpdGVyYXRvci5oYXNOZXh0KCkpIHsgLy8gbW9yZSB0aGFuIG9uZSBzZWxlY3Rpb24gKHNob3VsZCBuZXZlciBoYXBwZW4pCgkJCWFjdGlvbi5zZXRFbmFibGVkKGZhbHNlKTsKCQkJc2VsZWN0aW9uID0gbnVsbDsKCQkJZ2xvYmFsU2VsZWN0aW9uID0gbnVsbDsKCQkJcmV0dXJuOwoJCX0KCgkJaWYgKHNlbGVjdGlvbiAhPSBnbG9iYWxTZWxlY3Rpb24pIHsKCQkJVHJhY2UudHJhY2UoVHJhY2UuRklORVNULCAiU2VsZWN0aW9uOiAiICsgc2VsZWN0aW9uKTsKCQkJaWYgKHNlbGVjdGlvbiAhPSBudWxsKQkKCQkJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgIlNlbGVjdGlvbiB0eXBlOiAiICsgc2VsZWN0aW9uLmdldENsYXNzKCkuZ2V0TmFtZSgpKTsKCQkJZ2xvYmFsU2VsZWN0aW9uID0gc2VsZWN0aW9uOwoJCQlnbG9iYWxMYXVuY2hNb2RlID0gbmV3IEhhc2hNYXAoKTsKCQkJaWYgKCFTZXJ2ZXJQbHVnaW4uaGFzTW9kdWxlQXJ0aWZhY3QoZ2xvYmFsU2VsZWN0aW9uKSkgewoJCQkJYWN0aW9uLnNldEVuYWJsZWQoZmFsc2UpOwoJCQkJcmV0dXJuOwoJCQl9CgkJCQoJCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICJjaGVja2luZyBmb3IgbW9kdWxlIGFydGlmYWN0Iik7CgkJCUlNb2R1bGVBcnRpZmFjdCBtb2R1bGVBcnRpZmFjdCA9IFNlcnZlclBsdWdpbi5nZXRNb2R1bGVBcnRpZmFjdChnbG9iYWxTZWxlY3Rpb24pOwoJCQlJTW9kdWxlIG1vZHVsZSA9IG51bGw7CgkJCWlmIChtb2R1bGVBcnRpZmFjdCAhPSBudWxsKQoJCQkJbW9kdWxlID0gbW9kdWxlQXJ0aWZhY3QuZ2V0TW9kdWxlKCk7CgkJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVTVCwgIm1vZHVsZUFydGlmYWN0PSAiICsgbW9kdWxlQXJ0aWZhY3QgKyAiLCBtb2R1bGU9ICIgKyBtb2R1bGUpOwoJCQlpZiAobW9kdWxlICE9IG51bGwpCgkJCQlmaW5kR2xvYmFsTGF1bmNoTW9kZXMobW9kdWxlKTsKCQkJZWxzZSB7CgkJCQlnbG9iYWxMYXVuY2hNb2RlLnB1dChJTGF1bmNoTWFuYWdlci5SVU5fTU9ERSwgbmV3IEJvb2xlYW4odHJ1ZSkpOwoJCQkJZ2xvYmFsTGF1bmNoTW9kZS5wdXQoSUxhdW5jaE1hbmFnZXIuREVCVUdfTU9ERSwgbmV3IEJvb2xlYW4odHJ1ZSkpOwoJCQkJZ2xvYmFsTGF1bmNoTW9kZS5wdXQoSUxhdW5jaE1hbmFnZXIuUFJPRklMRV9NT0RFLCBuZXcgQm9vbGVhbih0cnVlKSk7CgkJCX0KCQl9CgoJCWFjdGlvbi5zZXRFbmFibGVkKGlzRW5hYmxlZCgpKTsKCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FU1QsICI8IHNlbGVjdGlvbkNoYW5nZWQgIiArIChTeXN0ZW0uY3VycmVudFRpbWVNaWxsaXMoKSAtIHRpbWUpKTsKCX0KCQoJLyoqCgkgKiBEZXRlcm1pbmVzIHdoZXRoZXIgdGhlcmUgaXMgYSBzZXJ2ZXIgZmFjdG9yeSBhdmFpbGFibGUgZm9yIHRoZSBnaXZlbiBtb2R1bGUKCSAqIGFuZCB0aGUgdmFyaW91cyBzdGFydCBtb2Rlcy4KCSAqLwoJcHJvdGVjdGVkIHZvaWQgZmluZEdsb2JhbExhdW5jaE1vZGVzKElNb2R1bGUgbW9kdWxlKSB7CgkJSVNlcnZlclR5cGVbXSBzZXJ2ZXJUeXBlcyA9IFNlcnZlckNvcmUuZ2V0U2VydmVyVHlwZXMoKTsKCQlpZiAoc2VydmVyVHlwZXMgIT0gbnVsbCkgewoJCQlpbnQgc2l6ZSA9IHNlcnZlclR5cGVzLmxlbmd0aDsKCQkJZm9yIChpbnQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHsKCQkJCUlTZXJ2ZXJUeXBlIHR5cGUgPSBzZXJ2ZXJUeXBlc1tpXTsKCQkJCWlmIChpc1ZhbGlkU2VydmVyVHlwZSh0eXBlLCBtb2R1bGUpKSB7CgkJCQkJZm9yIChieXRlIGIgPSAwOyBiIDwgbGF1bmNoTW9kZXMubGVuZ3RoOyBiKyspIHsKCQkJCQkJaWYgKHR5cGUuc3VwcG9ydHNMYXVuY2hNb2RlKGxhdW5jaE1vZGVzW2JdKSkgewoJCQkJCQkJZ2xvYmFsTGF1bmNoTW9kZS5wdXQobGF1bmNoTW9kZXNbYl0sIG5ldyBCb29sZWFuKHRydWUpKTsKCQkJCQkJfQoJCQkJCX0KCQkJCX0KCQkJfQoJCX0KCX0KCgkvKioKCSAqIFJldHVybnMgdHJ1ZSBpZiB0aGUgZ2l2ZW4gc2VydmVyIHR5cGUgY2FuIGxhdW5jaCB0aGUgbW9kdWxlLiAKCSAqLwoJcHJvdGVjdGVkIGJvb2xlYW4gaXNWYWxpZFNlcnZlclR5cGUoSVNlcnZlclR5cGUgdHlwZSwgSU1vZHVsZSBtb2R1bGUpIHsKCQl0cnkgewoJCQlJUnVudGltZVR5cGUgcnVudGltZVR5cGUgPSB0eXBlLmdldFJ1bnRpbWVUeXBlKCk7CgkJCVNlcnZlclV0aWwuaXNTdXBwb3J0ZWRNb2R1bGUocnVudGltZVR5cGUuZ2V0TW9kdWxlVHlwZXMoKSwgbW9kdWxlLmdldE1vZHVsZVR5cGUoKSk7CgkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJcmV0dXJuIGZhbHNlOwoJCX0KCQlyZXR1cm4gdHJ1ZTsKCX0KCglwcm90ZWN0ZWQgYm9vbGVhbiBzdXBwb3J0c0xhdW5jaE1vZGUoSVNlcnZlciBzZXJ2ZXIsIFN0cmluZyBsYXVuY2hNb2RlKSB7CgkJcmV0dXJuIHNlcnZlci5nZXRTZXJ2ZXJUeXBlKCkuc3VwcG9ydHNMYXVuY2hNb2RlKGxhdW5jaE1vZGUpOwoJfQp9