LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogQ29weXJpZ2h0IChjKSAyMDAzLCAyMDA1IElCTSBDb3Jwb3JhdGlvbiBhbmQgb3RoZXJzLgogKiBBbGwgcmlnaHRzIHJlc2VydmVkLiBUaGlzIHByb2dyYW0gYW5kIHRoZSBhY2NvbXBhbnlpbmcgbWF0ZXJpYWxzCiAqIGFyZSBtYWRlIGF2YWlsYWJsZSB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEVjbGlwc2UgUHVibGljIExpY2Vuc2UgdjEuMAogKiB3aGljaCBhY2NvbXBhbmllcyB0aGlzIGRpc3RyaWJ1dGlvbiwgYW5kIGlzIGF2YWlsYWJsZSBhdAogKiBodHRwOi8vd3d3LmVjbGlwc2Uub3JnL2xlZ2FsL2VwbC12MTAuaHRtbAqgKiAKICogQ29udHJpYnV0b3JzOgogKiAgICAgSUJNIENvcnBvcmF0aW9uIC0gSW5pdGlhbCBBUEkgYW5kIGltcGxlbWVudGF0aW9uCiAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLwpwYWNrYWdlIG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIuY29yZS5pbnRlcm5hbDsKCmltcG9ydCBqYXZhLmJlYW5zLlByb3BlcnR5Q2hhbmdlTGlzdGVuZXI7CmltcG9ydCBqYXZhLnV0aWwuQXJyYXlMaXN0OwppbXBvcnQgamF2YS51dGlsLkhhc2hNYXA7CmltcG9ydCBqYXZhLnV0aWwuSXRlcmF0b3I7CmltcG9ydCBqYXZhLnV0aWwuTGlzdDsKaW1wb3J0IGphdmEudXRpbC5NYXA7CgppbXBvcnQgb3JnLmVjbGlwc2UuY29yZS5yZXNvdXJjZXMuSUZpbGU7CmltcG9ydCBvcmcuZWNsaXBzZS5jb3JlLnJlc291cmNlcy5JRm9sZGVyOwppbXBvcnQgb3JnLmVjbGlwc2UuY29yZS5yZXNvdXJjZXMuSVByb2plY3Q7CmltcG9ydCBvcmcuZWNsaXBzZS5jb3JlLnJlc291cmNlcy5JUmVzb3VyY2U7CmltcG9ydCBvcmcuZWNsaXBzZS5jb3JlLnJ1bnRpbWUuKjsKaW1wb3J0IG9yZy5lY2xpcHNlLm9zZ2kudXRpbC5OTFM7CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc2VydmVyLmNvcmUuKjsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIuY29yZS5tb2RlbC5JbnRlcm5hbEluaXRpYWxpemVyOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNlcnZlci5jb3JlLm1vZGVsLlNlcnZlckJlaGF2aW91ckRlbGVnYXRlOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNlcnZlci5jb3JlLm1vZGVsLlNlcnZlckRlbGVnYXRlOwovKioKICogCiAqLwpwdWJsaWMgY2xhc3MgU2VydmVyV29ya2luZ0NvcHkgZXh0ZW5kcyBTZXJ2ZXIgaW1wbGVtZW50cyBJU2VydmVyV29ya2luZ0NvcHkgewoJcHJvdGVjdGVkIFNlcnZlciBzZXJ2ZXI7Cglwcm90ZWN0ZWQgV29ya2luZ0NvcHlIZWxwZXIgd2NoOwoJCglwcm90ZWN0ZWQgU2VydmVyRGVsZWdhdGUgd29ya2luZ0NvcHlEZWxlZ2F0ZTsKCQoJLy8gd29ya2luZyBjb3B5CglwdWJsaWMgU2VydmVyV29ya2luZ0NvcHkoU2VydmVyIHNlcnZlcikgewoJCXN1cGVyKHNlcnZlci5nZXRGaWxlKCkpOwoJCXRoaXMuc2VydmVyID0gc2VydmVyOwoJCQoJCW1hcCA9IG5ldyBIYXNoTWFwKHNlcnZlci5tYXApOwoJCXdjaCA9IG5ldyBXb3JraW5nQ29weUhlbHBlcih0aGlzKTsKCQkKCQlyZXNvbHZlKCk7Cgl9CgkKCS8vIGNyZWF0aW9uCglwdWJsaWMgU2VydmVyV29ya2luZ0NvcHkoU3RyaW5nIGlkLCBJRmlsZSBmaWxlLCBJUnVudGltZSBydW50aW1lLCBJU2VydmVyVHlwZSBzZXJ2ZXJUeXBlKSB7CgkJc3VwZXIoaWQsIGZpbGUsIHJ1bnRpbWUsIHNlcnZlclR5cGUpOwoJCS8vc2VydmVyID0gdGhpczsKCQl3Y2ggPSBuZXcgV29ya2luZ0NvcHlIZWxwZXIodGhpcyk7CgkJd2NoLnNldERpcnR5KHRydWUpOwoJCXNlcnZlclN0YXRlID0gKChTZXJ2ZXJUeXBlKXNlcnZlclR5cGUpLmdldEluaXRpYWxTdGF0ZSgpOwoJfQoKCXB1YmxpYyBib29sZWFuIGlzV29ya2luZ0NvcHkoKSB7CgkJcmV0dXJuIHRydWU7Cgl9CgkKCXB1YmxpYyBJU2VydmVyIGdldE9yaWdpbmFsKCkgewoJCXJldHVybiBzZXJ2ZXI7Cgl9CgkKCXB1YmxpYyBJU2VydmVyV29ya2luZ0NvcHkgY3JlYXRlV29ya2luZ0NvcHkoKSB7CgkJcmV0dXJuIHRoaXM7Cgl9CgoJcHVibGljIGludCBnZXRTZXJ2ZXJTdGF0ZSgpIHsKCQlpZiAoc2VydmVyICE9IG51bGwpCgkJCXJldHVybiBzZXJ2ZXIuZ2V0U2VydmVyU3RhdGUoKTsKCQlyZXR1cm4gc2VydmVyU3RhdGU7Cgl9CgoJcHVibGljIHZvaWQgc2V0U2VydmVyU3RhdGUoaW50IHN0YXRlKSB7CgkJaWYgKHNlcnZlciAhPSBudWxsKQoJCQlzZXJ2ZXIuc2V0U2VydmVyU3RhdGUoc3RhdGUpOwoJCWVsc2UKCQkJc3VwZXIuc2V0U2VydmVyU3RhdGUoc3RhdGUpOwoJfQoJCglwdWJsaWMgaW50IGdldFNlcnZlclB1Ymxpc2hTdGF0ZSgpIHsKCQlpZiAoc2VydmVyICE9IG51bGwpCgkJCXJldHVybiBzZXJ2ZXIuZ2V0U2VydmVyUHVibGlzaFN0YXRlKCk7CgkJcmV0dXJuIHNlcnZlclN0YXRlOwoJfQoKCXB1YmxpYyB2b2lkIHNldFNlcnZlclB1Ymxpc2hTdGF0ZShpbnQgc3RhdGUpIHsKCQlpZiAoc2VydmVyICE9IG51bGwpCgkJCXNlcnZlci5zZXRTZXJ2ZXJQdWJsaXNoU3RhdGUoc3RhdGUpOwoJCWVsc2UKCQkJc3VwZXIuc2V0U2VydmVyUHVibGlzaFN0YXRlKHN0YXRlKTsKCX0KCQoJcHVibGljIFN0cmluZyBnZXRNb2RlKCkgewoJCWlmIChzZXJ2ZXIgIT0gbnVsbCkKCQkJcmV0dXJuIHNlcnZlci5nZXRNb2RlKCk7CgkJcmV0dXJuIG1vZGU7Cgl9CgoJcHVibGljIHZvaWQgc2V0TW9kZShTdHJpbmcgbW9kZSkgewoJCWlmIChzZXJ2ZXIgIT0gbnVsbCkKCQkJc2VydmVyLnNldE1vZGUobW9kZSk7CgkJZWxzZQoJCQlzdXBlci5zZXRNb2RlKG1vZGUpOwoJfQoKCXB1YmxpYyB2b2lkIHNldEF0dHJpYnV0ZShTdHJpbmcgYXR0cmlidXRlTmFtZSwgaW50IHZhbHVlKSB7CgkJd2NoLnNldEF0dHJpYnV0ZShhdHRyaWJ1dGVOYW1lLCB2YWx1ZSk7Cgl9CgoJcHVibGljIHZvaWQgc2V0QXR0cmlidXRlKFN0cmluZyBhdHRyaWJ1dGVOYW1lLCBib29sZWFuIHZhbHVlKSB7CgkJd2NoLnNldEF0dHJpYnV0ZShhdHRyaWJ1dGVOYW1lLCB2YWx1ZSk7Cgl9CgoJcHVibGljIHZvaWQgc2V0QXR0cmlidXRlKFN0cmluZyBhdHRyaWJ1dGVOYW1lLCBTdHJpbmcgdmFsdWUpIHsKCQl3Y2guc2V0QXR0cmlidXRlKGF0dHJpYnV0ZU5hbWUsIHZhbHVlKTsKCX0KCglwdWJsaWMgdm9pZCBzZXRBdHRyaWJ1dGUoU3RyaW5nIGF0dHJpYnV0ZU5hbWUsIExpc3QgdmFsdWUpIHsKCQl3Y2guc2V0QXR0cmlidXRlKGF0dHJpYnV0ZU5hbWUsIHZhbHVlKTsKCX0KCglwdWJsaWMgdm9pZCBzZXRBdHRyaWJ1dGUoU3RyaW5nIGF0dHJpYnV0ZU5hbWUsIE1hcCB2YWx1ZSkgewoJCXdjaC5zZXRBdHRyaWJ1dGUoYXR0cmlidXRlTmFtZSwgdmFsdWUpOwoJfQoKCS8qIChub24tSmF2YWRvYykKCSAqIEBzZWUgb3JnLmVjbGlwc2Uud3N0LnNlcnZlci5jb3JlLklTZXJ2ZXJXb3JraW5nQ29weSNzZXROYW1lKGphdmEubGFuZy5TdHJpbmcpCgkgKi8KCXB1YmxpYyB2b2lkIHNldE5hbWUoU3RyaW5nIG5hbWUpIHsKCQlzZXRBdHRyaWJ1dGUoUFJPUF9OQU1FLCBuYW1lKTsKCX0KCglwdWJsaWMgdm9pZCBzZXRSZWFkT25seShib29sZWFuIGIpIHsKCQlzZXRBdHRyaWJ1dGUoUFJPUF9MT0NLRUQsIGIpOwoJfQoKCS8qKgoJICogU2V0cyB3aGV0aGVyIHRoaXMgZWxlbWVudCBpcyBwcml2YXRlLgoJICogR2VuZXJhbGx5IHNwZWFraW5nLCBlbGVtZW50cyBtYXJrZWQgcHJpdmF0ZSBhcmUgaW50ZXJuYWwgb25lcwoJICogdGhhdCBzaG91bGQgbm90IGJlIHNob3duIHRvIHVzZXJzIChiZWNhdXNlIHRoZXkgd29uJ3Qga25vdwoJICogYW55dGhpbmcgYWJvdXQgdGhlbSkuCgkgKiAKCSAqIEBwYXJhbSBiIDxjb2RlPnRydWU8L2NvZGU+IGlmIHRoaXMgZWxlbWVudCBpcyBwcml2YXRlLAoJICogYW5kIDxjb2RlPmZhbHNlPC9jb2RlPiBvdGhlcndpc2UKCSAqIEBzZWUgI2lzUHJpdmF0ZSgpCgkgKi8KCXB1YmxpYyB2b2lkIHNldFByaXZhdGUoYm9vbGVhbiBiKSB7CgkJc2V0QXR0cmlidXRlKFBST1BfUFJJVkFURSwgYik7Cgl9CgoJcHVibGljIHZvaWQgc2V0SG9zdChTdHJpbmcgaG9zdCkgewoJCXNldEF0dHJpYnV0ZShQUk9QX0hPU1ROQU1FLCBob3N0KTsKCX0KCglwdWJsaWMgdm9pZCBzZXRBdXRvUHVibGlzaFRpbWUoaW50IHApIHsKCQlzZXRBdHRyaWJ1dGUoUFJPUF9BVVRPX1BVQkxJU0hfVElNRSwgcCk7Cgl9CgoJcHVibGljIHZvaWQgc2V0QXV0b1B1Ymxpc2hTZXR0aW5nKGludCBzKSB7CgkJc2V0QXR0cmlidXRlKFBST1BfQVVUT19QVUJMSVNIX1NFVFRJTkcsIHMpOwoJfQoKCXB1YmxpYyB2b2lkIHNldFNlcnZlckNvbmZpZ3VyYXRpb24oSUZvbGRlciBjb25maWcpIHsKCQl0aGlzLmNvbmZpZ3VyYXRpb24gPSBjb25maWc7CgkJaWYgKGNvbmZpZ3VyYXRpb24gPT0gbnVsbCkKCQkJc2V0QXR0cmlidXRlKENPTkZJR1VSQVRJT05fSUQsIChTdHJpbmcpbnVsbCk7CgkJZWxzZQoJCQlzZXRBdHRyaWJ1dGUoQ09ORklHVVJBVElPTl9JRCwgY29uZmlndXJhdGlvbi5nZXRGdWxsUGF0aCgpLnRvU3RyaW5nKCkpOwoJfQoKCS8qKgoJICogU2V0cyB0aGUgZmlsZSB3aGVyZSB0aGlzIHNlcnZlciBpbnN0YW5jZSBpcyBzZXJpYWxpemVkLgoJICogCgkgKiBAcGFyYW0gZmlsZSB0aGUgZmlsZSBpbiB0aGUgd29ya3NwYWNlIHdoZXJlIHRoZSBzZXJ2ZXIgaW5zdGFuY2UKCSAqICAgIGlzIHNlcmlhbGl6ZWQsIG9yIDxjb2RlPm51bGw8L2NvZGU+IGlmIHRoZSBpbmZvcm1hdGlvbiBpcwoJICogICAgaW5zdGVhZCB0byBiZSBwZXJzaXN0ZWQgd2l0aCB0aGUgd29ya3NwYWNlIGJ1dCBub3Qgd2l0aCBhbnkKCSAqICAgIHBhcnRpY3VsYXIgd29ya3NwYWNlIHJlc291cmNlCgkgKi8KCXB1YmxpYyB2b2lkIHNldEZpbGUoSUZpbGUgZmlsZSkgewoJCXRoaXMuZmlsZSA9IGZpbGU7Cgl9CgoJLyogKG5vbi1KYXZhZG9jKQoJICogQHNlZSBvcmcuZWNsaXBzZS53c3Quc2VydmVyLmNvcmUuSVNlcnZlcldvcmtpbmdDb3B5I2lzRGlydHkoKQoJICovCglwdWJsaWMgYm9vbGVhbiBpc0RpcnR5KCkgewoJCXJldHVybiB3Y2guaXNEaXJ0eSgpOwoJfQoKCXB1YmxpYyBTZXJ2ZXJEZWxlZ2F0ZSBnZXRXb3JraW5nQ29weURlbGVnYXRlKElQcm9ncmVzc01vbml0b3IgbW9uaXRvcikgewoJCS8vIG1ha2Ugc3VyZSB0aGF0IHRoZSByZWd1bGFyIGRlbGVnYXRlIGlzIGxvYWRlZCAKCQkvL2dldERlbGVnYXRlKCk7CgkJCgkJaWYgKHdvcmtpbmdDb3B5RGVsZWdhdGUgIT0gbnVsbCB8fCBzZXJ2ZXJUeXBlID09IG51bGwpCgkJCXJldHVybiB3b3JraW5nQ29weURlbGVnYXRlOwoJCQoJCXN5bmNocm9uaXplZCAodGhpcykgewoJCQlpZiAod29ya2luZ0NvcHlEZWxlZ2F0ZSA9PSBudWxsKSB7CgkJCQl0cnkgewoJCQkJCWxvbmcgdGltZSA9IFN5c3RlbS5jdXJyZW50VGltZU1pbGxpcygpOwoJCQkJCXdvcmtpbmdDb3B5RGVsZWdhdGUgPSAoKFNlcnZlclR5cGUpIHNlcnZlclR5cGUpLmNyZWF0ZVNlcnZlckRlbGVnYXRlKCk7CgkJCQkJSW50ZXJuYWxJbml0aWFsaXplci5pbml0aWFsaXplU2VydmVyRGVsZWdhdGUod29ya2luZ0NvcHlEZWxlZ2F0ZSwgdGhpcywgbW9uaXRvcik7CgkJCQkJVHJhY2UudHJhY2UoVHJhY2UuUEVSRk9STUFOQ0UsICJTZXJ2ZXJXb3JraW5nQ29weS5nZXRXb3JraW5nQ29weURlbGVnYXRlKCk6IDwiICsgKFN5c3RlbS5jdXJyZW50VGltZU1pbGxpcygpIC0gdGltZSkgKyAiPiAiICsgZ2V0U2VydmVyVHlwZSgpLmdldElkKCkpOwoJCQkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJCQlUcmFjZS50cmFjZShUcmFjZS5TRVZFUkUsICJDb3VsZCBub3QgY3JlYXRlIGRlbGVnYXRlICIgKyB0b1N0cmluZygpLCBlKTsKCQkJCX0KCQkJfQoJCX0KCQlyZXR1cm4gd29ya2luZ0NvcHlEZWxlZ2F0ZTsKCX0KCglwcm90ZWN0ZWQgU2VydmVyQmVoYXZpb3VyRGVsZWdhdGUgZ2V0QmVoYXZpb3VyRGVsZWdhdGUoSVByb2dyZXNzTW9uaXRvciBtb25pdG9yKSB7CgkJaWYgKHNlcnZlciA9PSBudWxsKQoJCQlyZXR1cm4gbnVsbDsKCQkKCQlpZiAoYmVoYXZpb3VyRGVsZWdhdGUgIT0gbnVsbCkKCQkJcmV0dXJuIGJlaGF2aW91ckRlbGVnYXRlOwoJCQoJCXN5bmNocm9uaXplZCAodGhpcykgewoJCQlpZiAoYmVoYXZpb3VyRGVsZWdhdGUgPT0gbnVsbCkKCQkJCWJlaGF2aW91ckRlbGVnYXRlID0gc2VydmVyLmdldEJlaGF2aW91ckRlbGVnYXRlKG1vbml0b3IpOwoJCX0KCQlyZXR1cm4gYmVoYXZpb3VyRGVsZWdhdGU7Cgl9CgoJcHVibGljIHZvaWQgZGlzcG9zZSgpIHsKCQkvLyBiZWhhdmlvdXIgZGVsZWdhdGUgaXMgY2FjaGVkIGZyb20gdGhlIG9yaWdpbmFsIHNlcnZlcgoJCWJlaGF2aW91ckRlbGVnYXRlID0gbnVsbDsKCQkKCQlzdXBlci5kaXNwb3NlKCk7CgkJaWYgKHdvcmtpbmdDb3B5RGVsZWdhdGUgIT0gbnVsbCkKCQkJd29ya2luZ0NvcHlEZWxlZ2F0ZS5kaXNwb3NlKCk7Cgl9CgoJcHVibGljIElTZXJ2ZXIgc2F2ZShib29sZWFuIGZvcmNlLCBJUHJvZ3Jlc3NNb25pdG9yIG1vbml0b3IpIHRocm93cyBDb3JlRXhjZXB0aW9uIHsKCQltb25pdG9yID0gUHJvZ3Jlc3NVdGlsLmdldE1vbml0b3JGb3IobW9uaXRvcik7CgkJbW9uaXRvci5zdWJUYXNrKE5MUy5iaW5kKE1lc3NhZ2VzLnNhdmluZ1Rhc2ssIGdldE5hbWUoKSkpOwoJCQoJCWlmICghZm9yY2UgJiYgZ2V0T3JpZ2luYWwoKSAhPSBudWxsKQoJCQl3Y2gudmFsaWRhdGVUaW1lc3RhbXAoKChTZXJ2ZXIpZ2V0T3JpZ2luYWwoKSkuZ2V0VGltZXN0YW1wKCkpOwoJCQoJCWlmIChzZXJ2ZXIgPT0gbnVsbCkgewoJCQlzZXJ2ZXIgPSBuZXcgU2VydmVyKGZpbGUpOwoJCQlzZXJ2ZXIuc2V0U2VydmVyU3RhdGUoc2VydmVyU3RhdGUpOwoJCQlzZXJ2ZXIucHVibGlzaExpc3RlbmVycyA9IHB1Ymxpc2hMaXN0ZW5lcnM7CgkJCXNlcnZlci5ub3RpZmljYXRpb25NYW5hZ2VyID0gbm90aWZpY2F0aW9uTWFuYWdlcjsKCQl9CgkJCgkJaWYgKGdldFNlcnZlclR5cGUoKS5oYXNTZXJ2ZXJDb25maWd1cmF0aW9uKCkpIHsKCQkJSUZvbGRlciBmb2xkZXIgPSBnZXRTZXJ2ZXJDb25maWd1cmF0aW9uKCk7CgkJCWlmIChmb2xkZXIgPT0gbnVsbCkgewoJCQkJZm9sZGVyID0gU2VydmVyVHlwZS5nZXRTZXJ2ZXJQcm9qZWN0KCkuZ2V0Rm9sZGVyKGdldE5hbWUoKSArICItY29uZmlnIik7CgkJCQlpZiAoIWZvbGRlci5leGlzdHMoKSkKCQkJCQlmb2xkZXIuY3JlYXRlKHRydWUsIHRydWUsIG51bGwpOwoJCQkJc2V0U2VydmVyQ29uZmlndXJhdGlvbihmb2xkZXIpOwoJCQl9CgkJfQoJCQoJCXNlcnZlci5zZXRJbnRlcm5hbCh0aGlzKTsKCQlzZXJ2ZXIuZG9TYXZlKG1vbml0b3IpOwoJCWlmIChnZXRTZXJ2ZXJUeXBlKCkuaGFzU2VydmVyQ29uZmlndXJhdGlvbigpKSB7CgkJCUlGb2xkZXIgZm9sZGVyID0gZ2V0U2VydmVyQ29uZmlndXJhdGlvbigpOwoJCQlpZiAoZm9sZGVyICE9IG51bGwpIHsKCQkJCUlQcm9qZWN0IHByb2plY3QgPSBmb2xkZXIuZ2V0UHJvamVjdCgpOwoJCQkJaWYgKHByb2plY3QgIT0gbnVsbCAmJiAhcHJvamVjdC5leGlzdHMoKSkgewoJCQkJCXByb2plY3QuY3JlYXRlKG51bGwpOwoJCQkJCXByb2plY3Qub3BlbihudWxsKTsKCQkJCQkoKFByb2plY3RQcm9wZXJ0aWVzKVNlcnZlckNvcmUuZ2V0UHJvamVjdFByb3BlcnRpZXMocHJvamVjdCkpLnNldFNlcnZlclByb2plY3QodHJ1ZSwgbW9uaXRvcik7CgkJCQl9CgkJCQlpZiAoIWZvbGRlci5leGlzdHMoKSkKCQkJCQlmb2xkZXIuY3JlYXRlKElSZXNvdXJjZS5GT1JDRSwgdHJ1ZSwgbnVsbCk7CgkJCX0KCQl9CgkJZ2V0RGVsZWdhdGUobW9uaXRvcikuc2F2ZUNvbmZpZ3VyYXRpb24obW9uaXRvcik7CgkJd2NoLnNldERpcnR5KGZhbHNlKTsKCQkKCQlyZXR1cm4gc2VydmVyOwoJfQoKCXB1YmxpYyBJU2VydmVyIHNhdmVBbGwoYm9vbGVhbiBmb3JjZSwgSVByb2dyZXNzTW9uaXRvciBtb25pdG9yKSB0aHJvd3MgQ29yZUV4Y2VwdGlvbiB7CgkJaWYgKHJ1bnRpbWUgIT0gbnVsbCAmJiBydW50aW1lLmlzV29ya2luZ0NvcHkoKSkgewoJCQlJUnVudGltZVdvcmtpbmdDb3B5IHdjID0gKElSdW50aW1lV29ya2luZ0NvcHkpIHJ1bnRpbWU7CgkJCXdjLnNhdmUoZm9yY2UsIG1vbml0b3IpOwoJCX0KCQkKCQlyZXR1cm4gc2F2ZShmb3JjZSwgbW9uaXRvcik7Cgl9CgoJLyoqCgkgKiBBZGQgYSBwcm9wZXJ0eSBjaGFuZ2UgbGlzdGVuZXIgdG8gdGhpcyBzZXJ2ZXIuCgkgKgoJICogQHBhcmFtIGxpc3RlbmVyIGphdmEuYmVhbnMuUHJvcGVydHlDaGFuZ2VMaXN0ZW5lcgoJICovCglwdWJsaWMgdm9pZCBhZGRQcm9wZXJ0eUNoYW5nZUxpc3RlbmVyKFByb3BlcnR5Q2hhbmdlTGlzdGVuZXIgbGlzdGVuZXIpIHsKCQlpZiAobGlzdGVuZXIgPT0gbnVsbCkKCQkJdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigiTGlzdGVuZXIgY2Fubm90IGJlIG51bGwiKTsKCQl3Y2guYWRkUHJvcGVydHlDaGFuZ2VMaXN0ZW5lcihsaXN0ZW5lcik7Cgl9CgkKCS8qKgoJICogUmVtb3ZlIGEgcHJvcGVydHkgY2hhbmdlIGxpc3RlbmVyIGZyb20gdGhpcyBzZXJ2ZXIuCgkgKgoJICogQHBhcmFtIGxpc3RlbmVyIGphdmEuYmVhbnMuUHJvcGVydHlDaGFuZ2VMaXN0ZW5lcgoJICovCglwdWJsaWMgdm9pZCByZW1vdmVQcm9wZXJ0eUNoYW5nZUxpc3RlbmVyKFByb3BlcnR5Q2hhbmdlTGlzdGVuZXIgbGlzdGVuZXIpIHsKCQlpZiAobGlzdGVuZXIgPT0gbnVsbCkKCQkJdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbigiTGlzdGVuZXIgY2Fubm90IGJlIG51bGwiKTsKCQl3Y2gucmVtb3ZlUHJvcGVydHlDaGFuZ2VMaXN0ZW5lcihsaXN0ZW5lcik7Cgl9CgkKCS8qKgoJICogRmlyZSBhIHByb3BlcnR5IGNoYW5nZSBldmVudC4KCSAqIAoJICogQHBhcmFtIHByb3BlcnR5TmFtZSBhIHByb3BlcnR5IG5hbWUKCSAqIEBwYXJhbSBvbGRWYWx1ZSB0aGUgb2xkIHZhbHVlCgkgKiBAcGFyYW0gbmV3VmFsdWUgdGhlIG5ldyB2YWx1ZQoJICovCglwdWJsaWMgdm9pZCBmaXJlUHJvcGVydHlDaGFuZ2VFdmVudChTdHJpbmcgcHJvcGVydHlOYW1lLCBPYmplY3Qgb2xkVmFsdWUsIE9iamVjdCBuZXdWYWx1ZSkgewoJCXdjaC5maXJlUHJvcGVydHlDaGFuZ2VFdmVudChwcm9wZXJ0eU5hbWUsIG9sZFZhbHVlLCBuZXdWYWx1ZSk7Cgl9CgkKCXB1YmxpYyB2b2lkIGFkZFNlcnZlckxpc3RlbmVyKElTZXJ2ZXJMaXN0ZW5lciBsaXN0ZW5lcikgewoJCWlmIChzZXJ2ZXIgIT0gbnVsbCkKCQkJc2VydmVyLmFkZFNlcnZlckxpc3RlbmVyKGxpc3RlbmVyKTsKCQllbHNlCgkJCXN1cGVyLmFkZFNlcnZlckxpc3RlbmVyKGxpc3RlbmVyKTsKCX0KCQoJcHVibGljIHZvaWQgcmVtb3ZlU2VydmVyTGlzdGVuZXIoSVNlcnZlckxpc3RlbmVyIGxpc3RlbmVyKSB7CgkJaWYgKHNlcnZlciAhPSBudWxsKQoJCQlzZXJ2ZXIucmVtb3ZlU2VydmVyTGlzdGVuZXIobGlzdGVuZXIpOwoJCWVsc2UKCQkJc3VwZXIucmVtb3ZlU2VydmVyTGlzdGVuZXIobGlzdGVuZXIpOwoJfQoJCglwdWJsaWMgdm9pZCBhZGRQdWJsaXNoTGlzdGVuZXIoSVB1Ymxpc2hMaXN0ZW5lciBsaXN0ZW5lcikgewoJCWlmIChzZXJ2ZXIgIT0gbnVsbCkKCQkJc2VydmVyLmFkZFB1Ymxpc2hMaXN0ZW5lcihsaXN0ZW5lcik7CgkJZWxzZQoJCQlzdXBlci5hZGRQdWJsaXNoTGlzdGVuZXIobGlzdGVuZXIpOwoJfQoJCglwdWJsaWMgdm9pZCByZW1vdmVQdWJsaXNoTGlzdGVuZXIoSVB1Ymxpc2hMaXN0ZW5lciBsaXN0ZW5lcikgewoJCWlmIChzZXJ2ZXIgIT0gbnVsbCkKCQkJc2VydmVyLnJlbW92ZVB1Ymxpc2hMaXN0ZW5lcihsaXN0ZW5lcik7CgkJZWxzZQoJCQlzdXBlci5yZW1vdmVQdWJsaXNoTGlzdGVuZXIobGlzdGVuZXIpOwoJfQoKCXB1YmxpYyB2b2lkIHNldFJ1bnRpbWUoSVJ1bnRpbWUgcnVudGltZSkgewoJCXRoaXMucnVudGltZSA9IHJ1bnRpbWU7CgkJaWYgKHJ1bnRpbWUgIT0gbnVsbCkKCQkJc2V0QXR0cmlidXRlKFJVTlRJTUVfSUQsIHJ1bnRpbWUuZ2V0SWQoKSk7CgkJZWxzZQoJCQlzZXRBdHRyaWJ1dGUoUlVOVElNRV9JRCwgKFN0cmluZyludWxsKTsKCX0KCQoJcHVibGljIHZvaWQgc2V0UnVudGltZUlkKFN0cmluZyBydW50aW1lSWQpIHsKCQlzZXRBdHRyaWJ1dGUoUlVOVElNRV9JRCwgcnVudGltZUlkKTsKCQlyZXNvbHZlKCk7Cgl9CgoJLyogKG5vbi1KYXZhZG9jKQoJICogQHNlZSBvcmcuZWNsaXBzZS53c3Quc2VydmVyLmNvcmUuSVNlcnZlciNtb2RpZnlNb2R1bGUob3JnLmVjbGlwc2Uud3N0LnNlcnZlci5jb3JlLm1vZGVsLklNb2R1bGUpCgkgKi8KCXB1YmxpYyB2b2lkIG1vZGlmeU1vZHVsZXMoSU1vZHVsZVtdIGFkZCwgSU1vZHVsZVtdIHJlbW92ZSwgSVByb2dyZXNzTW9uaXRvciBtb25pdG9yKSB0aHJvd3MgQ29yZUV4Y2VwdGlvbiB7CgkJaWYgKChhZGQgPT0gbnVsbCB8fCBhZGQubGVuZ3RoID09IDApICYmIChyZW1vdmUgPT0gbnVsbCB8fCByZW1vdmUubGVuZ3RoID09IDApKQoJCQl0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCJBZGQgYW5kIHJlbW92ZSBjYW5ub3QgYm90aCBiZSBudWxsL2VtcHR5Iik7CgkJCgkJdHJ5IHsKCQkJbW9uaXRvciA9IFByb2dyZXNzVXRpbC5nZXRNb25pdG9yRm9yKG1vbml0b3IpOwoJCQltb25pdG9yLnN1YlRhc2soTWVzc2FnZXMudGFza01vZGlmeU1vZHVsZXMpOwoJCQlnZXRXb3JraW5nQ29weURlbGVnYXRlKG1vbml0b3IpLm1vZGlmeU1vZHVsZXMoYWRkLCByZW1vdmUsIG1vbml0b3IpOwoJCQl3Y2guc2V0RGlydHkodHJ1ZSk7CgkJCQoJCQkvLyB0cmlnZ2VyIGxvYWQgb2YgbW9kdWxlcyBsaXN0CgkJCWdldE1vZHVsZXMoKTsKCQkJCgkJCWlmIChhZGQgIT0gbnVsbCkgewoJCQkJaW50IHNpemUgPSBhZGQubGVuZ3RoOwoJCQkJZm9yIChpbnQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHsKCQkJCQlpZiAoIW1vZHVsZXMuY29udGFpbnMoYWRkW2ldKSkKCQkJCQkJbW9kdWxlcy5hZGQoYWRkW2ldKTsKCQkJCX0KCQkJfQoJCQkKCQkJaWYgKHJlbW92ZSAhPSBudWxsKSB7CgkJCQlpbnQgc2l6ZSA9IHJlbW92ZS5sZW5ndGg7CgkJCQlmb3IgKGludCBpID0gMDsgaSA8IHNpemU7IGkrKykgewoJCQkJCWlmIChtb2R1bGVzLmNvbnRhaW5zKHJlbW92ZVtpXSkpCgkJCQkJCW1vZHVsZXMucmVtb3ZlKHJlbW92ZVtpXSk7CgkJCQl9CgkJCX0KCQkJCgkJCS8vIGNvbnZlcnQgdG8gYXR0cmlidXRlCgkJCUxpc3QgbGlzdCA9IG5ldyBBcnJheUxpc3QoKTsKCQkJSXRlcmF0b3IgaXRlcmF0b3IgPSBtb2R1bGVzLml0ZXJhdG9yKCk7CgkJCXdoaWxlIChpdGVyYXRvci5oYXNOZXh0KCkpIHsKCQkJCUlNb2R1bGUgbW9kdWxlID0gKElNb2R1bGUpIGl0ZXJhdG9yLm5leHQoKTsKCQkJCWxpc3QuYWRkKG1vZHVsZS5nZXROYW1lKCkgKyAiOjoiICsgbW9kdWxlLmdldElkKCkpOwoJCQl9CgkJCXNldEF0dHJpYnV0ZShNT0RVTEVfTElTVCwgbGlzdCk7CgkJfSBjYXRjaCAoQ29yZUV4Y2VwdGlvbiBjZSkgewoJCQl0aHJvdyBjZTsKCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQlUcmFjZS50cmFjZShUcmFjZS5TRVZFUkUsICJFcnJvciBjYWxsaW5nIGRlbGVnYXRlIG1vZGlmeU1vZHVsZSgpICIgKyB0b1N0cmluZygpLCBlKTsKCQkJdGhyb3cgbmV3IENvcmVFeGNlcHRpb24obmV3IFN0YXR1cyhJU3RhdHVzLkVSUk9SLCBTZXJ2ZXJQbHVnaW4uUExVR0lOX0lELCAwLCAiIiArIGUuZ2V0TG9jYWxpemVkTWVzc2FnZSgpLCBlKSk7CgkJfQoJfQoKCXB1YmxpYyB2b2lkIHNldERlZmF1bHRzKElQcm9ncmVzc01vbml0b3IgbW9uaXRvcikgewoJCXRyeSB7CgkJCWdldFdvcmtpbmdDb3B5RGVsZWdhdGUobW9uaXRvcikuc2V0RGVmYXVsdHMobW9uaXRvcik7CgkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiRXJyb3IgY2FsbGluZyBkZWxlZ2F0ZSBzZXREZWZhdWx0cygpICIgKyB0b1N0cmluZygpLCBlKTsKCQl9Cgl9CgoJcHVibGljIHZvaWQgcmVuYW1lRmlsZXMoSVByb2dyZXNzTW9uaXRvciBtb25pdG9yKSB0aHJvd3MgQ29yZUV4Y2VwdGlvbiB7CgkJaWYgKGdldFNlcnZlckNvbmZpZ3VyYXRpb24oKSAhPSBudWxsKSB7CgkJCUlGb2xkZXIgZm9sZGVyID0gZ2V0U2VydmVyQ29uZmlndXJhdGlvbigpOwoJCQlJRm9sZGVyIGZvbGRlcjIgPSBTZXJ2ZXJUeXBlLmdldFNlcnZlclByb2plY3QoKS5nZXRGb2xkZXIoZ2V0TmFtZSgpICsgIi1jb25maWciKTsKCQkJZm9sZGVyLm1vdmUoZm9sZGVyMi5nZXRGdWxsUGF0aCgpLCB0cnVlLCB0cnVlLCBtb25pdG9yKTsKCQkJc2V0U2VydmVyQ29uZmlndXJhdGlvbihmb2xkZXIyKTsKCQkJc2F2ZSh0cnVlLCBtb25pdG9yKTsKCQl9CgkJCgkJaWYgKGZpbGUgIT0gbnVsbCkgewoJCQlJRmlsZSBmaWxlMiA9IFNlcnZlclV0aWwuZ2V0VW51c2VkU2VydmVyRmlsZShmaWxlLmdldFByb2plY3QoKSwgdGhpcyk7CgkJCWZpbGUubW92ZShmaWxlMi5nZXRGdWxsUGF0aCgpLCB0cnVlLCB0cnVlLCBtb25pdG9yKTsKCQl9Cgl9CgoJcHVibGljIFN0cmluZyB0b1N0cmluZygpIHsKCQlyZXR1cm4gIlNlcnZlcldvcmtpbmdDb3B5ICIgKyBnZXRJZCgpOwoJfQp9