LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogQ29weXJpZ2h0IChjKSAyMDA3IGNvbXBlb3BsZSBBRyBhbmQgb3RoZXJzLgogKiBBbGwgcmlnaHRzIHJlc2VydmVkLiBUaGlzIHByb2dyYW0gYW5kIHRoZSBhY2NvbXBhbnlpbmcgbWF0ZXJpYWxzCiAqIGFyZSBtYWRlIGF2YWlsYWJsZSB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEVjbGlwc2UgUHVibGljIExpY2Vuc2UgdjEuMAogKiB3aGljaCBhY2NvbXBhbmllcyB0aGlzIGRpc3RyaWJ1dGlvbiwgYW5kIGlzIGF2YWlsYWJsZSBhdAogKiBodHRwOi8vd3d3LmVjbGlwc2Uub3JnL2xlZ2FsL2VwbC12MTAuaHRtbAogKgogKiBDb250cmlidXRvcnM6CiAqICAJY29tcGVvcGxlIEFHIChTdGVmYW4gTGllYmlnKSAtIGluaXRpYWwgQVBJIGFuZCBpbXBsZW1lbnRhdGlvbgogKiAJSUJNIENvcnBvcmF0aW9uIC0gb25nb2luZyBkZXZlbG9wbWVudAogKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KcGFja2FnZSBvcmcuZWNsaXBzZS5lcXVpbm94LmludGVybmFsLnAyLmFydGlmYWN0Lm9wdGltaXplcnMuamJkaWZmOwoKaW1wb3J0IGphdmEuaW8uSU9FeGNlcHRpb247CmltcG9ydCBqYXZhLmlvLk91dHB1dFN0cmVhbTsKaW1wb3J0IGphdmEudXRpbC4qOwppbXBvcnQgb3JnLmVjbGlwc2UuY29yZS5ydW50aW1lLklTdGF0dXM7CmltcG9ydCBvcmcuZWNsaXBzZS5jb3JlLnJ1bnRpbWUuTnVsbFByb2dyZXNzTW9uaXRvcjsKaW1wb3J0IG9yZy5lY2xpcHNlLmVxdWlub3guaW50ZXJuYWwucDIuYXJ0aWZhY3Qub3B0aW1pemVycy5WZXJzaW9ubGVzc0FydGlmYWN0S2V5OwppbXBvcnQgb3JnLmVjbGlwc2UuZXF1aW5veC5pbnRlcm5hbC5wcm92aXNpb25hbC5wMi5hcnRpZmFjdC5yZXBvc2l0b3J5Lio7CmltcG9ydCBvcmcuZWNsaXBzZS5lcXVpbm94LmludGVybmFsLnByb3Zpc2lvbmFsLnAyLmFydGlmYWN0LnJlcG9zaXRvcnkucHJvY2Vzc2luZy4qOwppbXBvcnQgb3JnLmVjbGlwc2UuZXF1aW5veC5pbnRlcm5hbC5wcm92aXNpb25hbC5wMi5jb3JlLlByb3Zpc2lvbkV4Y2VwdGlvbjsKaW1wb3J0IG9yZy5lY2xpcHNlLmVxdWlub3guaW50ZXJuYWwucHJvdmlzaW9uYWwucDIubWV0YWRhdGEuSUFydGlmYWN0S2V5OwoKcHVibGljIGNsYXNzIE9wdGltaXplciB7CgoJcHJpdmF0ZSBJQXJ0aWZhY3RSZXBvc2l0b3J5IHJlcG9zaXRvcnk7Cglwcml2YXRlIGludCB3aWR0aDsKCXByaXZhdGUgaW50IGRlcHRoOwoJcHJpdmF0ZSBib29sZWFuIG5vc2FyOwoKCXByaXZhdGUgc3RhdGljIGZpbmFsIFN0cmluZyBKQlBBVENIX1NURVBfSUQgPSAib3JnLmVjbGlwc2UuZXF1aW5veC5wMi5yZXBvc2l0b3J5LkpCUGF0Y2hTdGVwIjsgLy8kTk9OLU5MUy0xJAoJcHJpdmF0ZSBzdGF0aWMgZmluYWwgU3RyaW5nIEpCUEFUQ0hfU1RFUF9aSVBfSUQgPSAib3JnLmVjbGlwc2UuZXF1aW5veC5wMi5yZXBvc2l0b3J5LkpCUGF0Y2haaXBTdGVwIjsgLy8kTk9OLU5MUy0xJAoKCXByaXZhdGUgc3RhdGljIGZpbmFsIENvbXBhcmF0b3IgQVJUSUZBQ1RfREVTQ1JJUFRPUl9WRVJTSU9OX0NPTVBBUkFUT1IgPSBuZXcgQXJ0aWZhY3REZXNjcmlwdG9yVmVyc2lvbkNvbXBhcmF0b3IoKTsKCXByaXZhdGUgc3RhdGljIGZpbmFsIENvbXBhcmF0b3IgQVJUSUZBQ1RfS0VZX1ZFUlNJT05fQ09NUEFSQVRPUiA9IG5ldyBBcnRpZmFjdEtleVZlcnNpb25Db21wYXJhdG9yKCk7CgoJLyoqCgkgKiBUaGlzIG9wdGltaXplciBwZXJmb3JtcyBkZWx0YSBnZW5lcmF0aW9uIGJhc2VkIG9uIChjdXJyZW50bHkpIGpiZGlmZi4gCgkgKiBUaGUgb3B0aW1pemF0aW9uIGNhbiBiZSBjb250cm9sbGVkIHdpdGggdGhlILR3aWR0aLQgYW5kIHRoZSC0ZGVwdGi0IHBhcmFtZXRlci4KCSAqILR3aWR0aLQgZGVmaW5lcyBmb3IgaG93IG1hbnkgtHJlbGF0ZWS0IGFydGlmYWN0IGtleXMgYSBkZWx0YSBzaG91bGQgYmUgZ2VuZXJhdGVkLAoJICogc3RhcnRpbmcgZnJvbSB0aGUgbW9zdCB1cC10by1kYXRlLgoJICogtGRlcHRotCBkZWZpbmVzIHRvIGhvdyBtYW55IHByZWRlY2Vzc29yIGEgZGVsdGEgc2hvdWxkIGJlIGdlbmVyYXRlZC4KCSAqIAoJICogV2l0aCBBSyhjLXYpIDogQUsgLSBhcnRpZmFjdCBrZXksIGMgLSBhcnRpZmFjdCBpZCwgdiAtIGFydGlmYWN0IHZlcnNpb24KCSAqIHRoZSC0cmVwb3NpdG9yeSBjb250ZW50tCBjYW4gYmUgdmlld2VkIGEgdHdvIGRpbWVuc2lvbmFsIGFycmF5LCB3aGVyZSB0aGUKCSAqIGFydGlmYWN0IGtleXMgZm9yIHRoZSBzYW1lIGNvbXBvbmVudCBhcmUgaW4gb3JkZXIgb2YgdGhlaXIgdmVyc2lvbjogCgkgKiA8cHJlPjxjb2RlPgoJICogICAgIHc9MSAgICAgICB3PTIKCSAqICAgICAgfCAgICAgICAgfAoJICogICAgICB8ICstLS0tLS0uLS0tLS0tLS0tLS0tKyBkPTIKCSAqICAgICAgfCB8ICstLS0tLi0tLSsgZD0xICAgIHwKCSAqICAgICAgfCB8IHwgICAgfCAgIHwgICAgICAgIHYKCSAqIFsgICAgdiB8IHwgICAgdiAgIHYgICAgICAgIHYKCSAqIFsgQUsoeCwyLjApIEFLKHgsMS41KSBBSyh4LDEuMSkgXQoJICogWyBBSyh5LDIuMCkgQUsoeSwxLjkpIF0KCSAqIFsgQUsoeiwyLjApIEFLKHosMS41KSBBSyh6LDEuMykgQUsoeiwxLjApIF0KCSAqIF0KCSAqIDwvY29kZT48L3ByZT4gIAoJICogRS5nOiB3aXRoIGEgtHdpZHRotCBvZiBvbmUgYW5kIGEgtGRlcHRotCBvZiB0d28gdGhlIG9wdGltaXplciB3b3VsZAoJICogY3JlYXRlIHR3byBkZWx0YXMgZm9yIGNvbXBvbmVudCC0eLQgZnJvbSAxLjUgdG8gMi4wIGFuZCBmcm9tIDEuMSB0byAyLjAuICAgIAoJICogCgkgKiBAcGFyYW0gcmVwb3NpdG9yeQoJICogQHBhcmFtIHdpZHRoCgkgKiBAcGFyYW0gZGVwdGgKCSAqIEBwYXJhbSBub3NhciAKCSAqLwoJcHVibGljIE9wdGltaXplcihJQXJ0aWZhY3RSZXBvc2l0b3J5IHJlcG9zaXRvcnksIGludCB3aWR0aCwgaW50IGRlcHRoLCBib29sZWFuIG5vc2FyKSB7CgkJdGhpcy5yZXBvc2l0b3J5ID0gcmVwb3NpdG9yeTsKCQl0aGlzLndpZHRoID0gd2lkdGg7CgkJdGhpcy5kZXB0aCA9IGRlcHRoOwoJCXRoaXMubm9zYXIgPSBub3NhcjsKCX0KCglwdWJsaWMgdm9pZCBydW4oKSB7CgkJU3lzdGVtLm91dC5wcmludGxuKCJTdGFydGluZyBkZWx0YSAoamJkaWZmKSBvcHRpbWl6YXRpb25zICh3aWR0aD0iICsgd2lkdGggKyAiLCBkZXB0aD0iICsgZGVwdGggKyAiLCBub3Nhcj0iICsgbm9zYXIgKyAiKSIpOwoJCUlBcnRpZmFjdEtleVtdW10ga2V5cyA9IGdldFNvcnRlZFJlbGF0ZWRBcnRpZmFjdEtleXMocmVwb3NpdG9yeS5nZXRBcnRpZmFjdEtleXMoKSk7CgkJZm9yIChpbnQgaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgaSsrKSB7CgkJCWlmIChrZXlzW2ldLmxlbmd0aCA8IDIpCgkJCQkvLyBOb3RoaW5nIHRvIGRpZmYgaGVyZSEKCQkJCWNvbnRpbnVlOwoJCQlpbnQgbWluV2lkdGggPSBNYXRoLm1pbih3aWR0aCwga2V5c1tpXS5sZW5ndGgpOwoJCQlmb3IgKGludCBqID0gMDsgaiA8IG1pbldpZHRoOyBqKyspIHsKCQkJCUlBcnRpZmFjdEtleSBrZXkgPSBrZXlzW2ldW2pdOwoJCQkJYm9vbGVhbiBpc0FyY2hpdmUgPSBrZXkuZ2V0Q2xhc3NpZmllcigpLmVxdWFscygicGx1Z2luIik7IC8vJE5PTi1OTFMtMSQKCQkJCVN0cmluZyBwcm9wb3NlZFN0cmF0ZWd5ID0gaXNBcmNoaXZlICYmICFub3NhciA/IEpCUEFUQ0hfU1RFUF9aSVBfSUQgOiBKQlBBVENIX1NURVBfSUQ7CgkJCQlvcHRpbWl6ZShrZXlzW2ldLCBrZXksIHByb3Bvc2VkU3RyYXRlZ3kpOwoJCQl9CgkJfQoJCVN5c3RlbS5vdXQucHJpbnRsbigiRG9uZS4iKTsKCgl9CgoJcHJpdmF0ZSB2b2lkIG9wdGltaXplKElBcnRpZmFjdEtleVtdIGtleXMsIElBcnRpZmFjdEtleSBrZXksIFN0cmluZyBwcm9wb3NlZFN0cmF0ZWd5KSB0aHJvd3MgT3V0T2ZNZW1vcnlFcnJvciB7CgkJYm9vbGVhbiByZXRyeTsKCQlkbyB7CgkJCXJldHJ5ID0gZmFsc2U7CgkJCXRyeSB7CgkJCQlJQXJ0aWZhY3REZXNjcmlwdG9yW10gZGVzY3JpcHRvcnMgPSByZXBvc2l0b3J5LmdldEFydGlmYWN0RGVzY3JpcHRvcnMoa2V5KTsKCQkJCUlBcnRpZmFjdERlc2NyaXB0b3IgY29tcGxldGUgPSBudWxsOwoJCQkJZm9yIChpbnQgayA9IDA7IGsgPCBkZXNjcmlwdG9ycy5sZW5ndGg7IGsrKykgewoJCQkJCUlBcnRpZmFjdERlc2NyaXB0b3IgZGVzY3JpcHRvciA9IGRlc2NyaXB0b3JzW2tdOwoJCQkJCWlmIChpc0Nhbm9uaWNhbChkZXNjcmlwdG9yKSkKCQkJCQkJY29tcGxldGUgPSBkZXNjcmlwdG9yOwoJCQkJCWVsc2UgaWYgKGlzT3B0aW1pemVkKGRlc2NyaXB0b3IsIHByb3Bvc2VkU3RyYXRlZ3kpKSB7CgkJCQkJCXByb3Bvc2VkU3RyYXRlZ3kgPSBudWxsOwoJCQkJCQlicmVhazsKCQkJCQl9CgkJCQl9CgkJCQlpZiAocHJvcG9zZWRTdHJhdGVneSAhPSBudWxsICYmIGNvbXBsZXRlICE9IG51bGwpCgkJCQkJb3B0aW1pemUoY29tcGxldGUsIHByb3Bvc2VkU3RyYXRlZ3ksIGtleXMpOwoJCQl9IGNhdGNoIChPdXRPZk1lbW9yeUVycm9yIGUpIHsKCQkJCWlmIChKQlBBVENIX1NURVBfSUQuZXF1YWxzKHByb3Bvc2VkU3RyYXRlZ3kpKQoJCQkJCXRocm93IGU7CgkJCQlwcm9wb3NlZFN0cmF0ZWd5ID0gSkJQQVRDSF9TVEVQX0lEOwoJCQkJU3lzdGVtLm91dC5wcmludGxuKCJSZXRyeSB3aXRoICIgKyBwcm9wb3NlZFN0cmF0ZWd5KTsKCQkJCXJldHJ5ID0gdHJ1ZTsKCQkJfQoJCX0gd2hpbGUgKHJldHJ5KTsKCX0KCgkvKioKCSAqIFRoaXMgbWV0aG9kIHJldHJpZXZlcyBhIGxpc3Qgb2YgbGlzdCBvZiBJQXJ0aWZhY3RLZXlzLiBUaGUgYXJ0aWZhY3Qga2V5cyBpbiB0aGUKCSAqIGxpc3Qgb2YgYXJ0aWZhY3Qga2V5cyBhcmUgYWxsILRzdHJvbmdseSByZWxhdGVktCB0byBlYWNoIG90aGVyIHN1Y2ggdGhhdCBhcmUgIAoJICogZXF1YWwgYnV0IG5vdCBjb25zaWRlcmluZyB0aGUgdmVyc2lvbnMuIFRoaXMgbGlzdCBpcyBzb3J0ZWQgc3VjaCB0aGF0IHRoZSAKCSAqIG5ld2VyIHZlcnNpb25zIGFyZSBmaXJzdCBpbiB0aGUgbGlzdC48cD4KCSAqIFdpdGggQUsoYy12KSA6IEFLIC0gYXJ0aWZhY3Qga2V5LCBjIC0gYXJ0aWZhY3QgaWQsIHYgLSBhcnRpZmFjdCB2ZXJzaW9uCgkgKiB0aGUgcmVzdWx0IGlzIHRoYW4sIGUuZy4KCSAqIDxwcmU+PGNvZGU+CgkgKiBbCgkgKiBbIEFLKHgsMi4wKSBBSyh4LDEuNSkgQUsoeCwxLjEpIF0KCSAqIFsgQUsoeSwyLjApIEFLKHksMS45KSBdCgkgKiBbIEFLKHosMi4wKSBBSyh6LDEuNSkgQUsoeiwxLjMpIEFLKHosMS4wKSBdCgkgKiBdCgkgKiA8L2NvZGU+PC9wcmU+ICAKCSAqIEBwYXJhbSBhcnRpZmFjdEtleXMKCSAqIEByZXR1cm4gdGhlIHNvcnRlZCBhcnRpZmFjdCBrZXlzCgkgKi8KCXByaXZhdGUgSUFydGlmYWN0S2V5W11bXSBnZXRTb3J0ZWRSZWxhdGVkQXJ0aWZhY3RLZXlzKElBcnRpZmFjdEtleVtdIGFydGlmYWN0S2V5cykgewoJCU1hcCBtYXAgPSBuZXcgSGFzaE1hcCgpOwoJCWZvciAoaW50IGkgPSAwOyBpIDwgYXJ0aWZhY3RLZXlzLmxlbmd0aDsgaSsrKSB7CgkJCUlBcnRpZmFjdEtleSBmcmVlS2V5ID0gbmV3IFZlcnNpb25sZXNzQXJ0aWZhY3RLZXkoYXJ0aWZhY3RLZXlzW2ldKTsKCQkJTGlzdCB2YWx1ZXMgPSAoTGlzdCkgbWFwLmdldChmcmVlS2V5KTsKCQkJaWYgKHZhbHVlcyA9PSBudWxsKSB7CgkJCQl2YWx1ZXMgPSBuZXcgQXJyYXlMaXN0KCk7CgkJCQltYXAucHV0KGZyZWVLZXksIHZhbHVlcyk7CgkJCX0KCQkJdmFsdWVzLmFkZChhcnRpZmFjdEtleXNbaV0pOwoJCX0KCQlJQXJ0aWZhY3RLZXlbXVtdIGxpc3RzID0gbmV3IElBcnRpZmFjdEtleVttYXAuc2l6ZSgpXVtdOwoJCWludCBpID0gMDsKCQlmb3IgKEl0ZXJhdG9yIGl0ZXJhdG9yID0gbWFwLnZhbHVlcygpLml0ZXJhdG9yKCk7IGl0ZXJhdG9yLmhhc05leHQoKTspIHsKCQkJTGlzdCBhcnRpZmFjdEtleUxpc3QgPSAoTGlzdCkgaXRlcmF0b3IubmV4dCgpOwoJCQlJQXJ0aWZhY3RLZXlbXSByZWxhdGVkQXJ0aWZhY3RLZXlzID0gKElBcnRpZmFjdEtleVtdKSBhcnRpZmFjdEtleUxpc3QudG9BcnJheShuZXcgSUFydGlmYWN0S2V5W2FydGlmYWN0S2V5TGlzdC5zaXplKCldKTsKCQkJQXJyYXlzLnNvcnQocmVsYXRlZEFydGlmYWN0S2V5cywgQVJUSUZBQ1RfS0VZX1ZFUlNJT05fQ09NUEFSQVRPUik7CgkJCWxpc3RzW2krK10gPSByZWxhdGVkQXJ0aWZhY3RLZXlzOwoJCX0KCQlpbnQgY2FuZGlkYXRlcyA9IDA7CgkJZm9yIChpbnQgaWkgPSAwOyBpaSA8IGxpc3RzLmxlbmd0aDsgaWkrKykgewoJCQlmb3IgKGludCBqaiA9IDA7IGpqIDwgbGlzdHNbaWldLmxlbmd0aDsgamorKykgewoJCQkJU3lzdGVtLm91dC5wcmludGxuKGxpc3RzW2lpXVtqal0gKyAiLCAiKTsKCQkJfQoJCQlTeXN0ZW0ub3V0LnByaW50bG4oIiIpOwoJCQlpZiAobGlzdHNbaWldLmxlbmd0aCA+IDEpCgkJCQljYW5kaWRhdGVzKys7CgkJfQoJCVN5c3RlbS5vdXQucHJpbnRsbigiQ2FuZGlkYXRlcyBmb3VuZDogIiArIGNhbmRpZGF0ZXMpOwoJCXJldHVybiBsaXN0czsKCX0KCglwcml2YXRlIHZvaWQgb3B0aW1pemUoSUFydGlmYWN0RGVzY3JpcHRvciBjb21wbGV0ZSwgU3RyaW5nIHN0cmF0ZWd5LCBJQXJ0aWZhY3RLZXlbXSByZWxhdGVkQXJ0aWZhY3RLZXlzKSB7CgkJU3lzdGVtLm91dC5wcmludGxuKCJPcHRpbWl6aW5nICIgKyBjb21wbGV0ZSk7CgoJCUlBcnRpZmFjdERlc2NyaXB0b3JbXSBkZXNjcmlwdG9ycyA9IGdldFNvcnRlZENvbXBsZXRlUHJlZGVjZXNzb3JzKGNvbXBsZXRlLmdldEFydGlmYWN0S2V5KCksIHJlbGF0ZWRBcnRpZmFjdEtleXMpOwoKCQlpbnQgbWluRGVwdGggPSBNYXRoLm1pbihkZXB0aCwgZGVzY3JpcHRvcnMubGVuZ3RoKTsKCQlmb3IgKGludCBpID0gMDsgaSA8IG1pbkRlcHRoOyBpKyspIHsKCgkJCVN5c3RlbS5vdXQucHJpbnRsbigiXHQgd2l0aCAiICsgc3RyYXRlZ3kgKyAiIGFnYWluc3QgIiArIGRlc2NyaXB0b3JzW2ldLmdldEFydGlmYWN0S2V5KCkpOwoJCQlTdHJpbmcgcHJlZGVjZXNzb3JEYXRhID0gZGVzY3JpcHRvcnNbaV0uZ2V0QXJ0aWZhY3RLZXkoKS50b0V4dGVybmFsRm9ybSgpOwoJCQlBcnRpZmFjdERlc2NyaXB0b3IgbmV3RGVzY3JpcHRvciA9IG5ldyBBcnRpZmFjdERlc2NyaXB0b3IoY29tcGxldGUpOwoJCQlQcm9jZXNzaW5nU3RlcERlc2NyaXB0b3IgcGF0Y2hTdGVwID0gbmV3IFByb2Nlc3NpbmdTdGVwRGVzY3JpcHRvcihzdHJhdGVneSwgcHJlZGVjZXNzb3JEYXRhLCB0cnVlKTsKCQkJUHJvY2Vzc2luZ1N0ZXBEZXNjcmlwdG9yW10gc3RlcHMgPSBuZXcgUHJvY2Vzc2luZ1N0ZXBEZXNjcmlwdG9yW10ge3BhdGNoU3RlcH07CgkJCW5ld0Rlc2NyaXB0b3Iuc2V0UHJvY2Vzc2luZ1N0ZXBzKHN0ZXBzKTsKCQkJbmV3RGVzY3JpcHRvci5zZXRQcm9wZXJ0eShJQXJ0aWZhY3REZXNjcmlwdG9yLkZPUk1BVCwgc3RyYXRlZ3kpOwoJCQlPdXRwdXRTdHJlYW0gcmVwb3NpdG9yeVN0cmVhbSA9IG51bGw7CgkJCXRyeSB7CgkJCQlyZXBvc2l0b3J5U3RyZWFtID0gcmVwb3NpdG9yeS5nZXRPdXRwdXRTdHJlYW0obmV3RGVzY3JpcHRvcik7CgoJCQkJLy8gQWRkIGluIGFsbCB0aGUgcHJvY2Vzc2luZyBzdGVwcyBuZWVkZWQgdG8gb3B0aW1pemUgKGUuZy4sIHBhY2syMDAsIC4uLikKCQkJCVByb2Nlc3NpbmdTdGVwIGRpZmZTdGVwID0gZ2V0UHJvY2Vzc2luZ1N0ZXAoc3RyYXRlZ3kpOwoJCQkJZGlmZlN0ZXAuaW5pdGlhbGl6ZShwYXRjaFN0ZXAsIG5ld0Rlc2NyaXB0b3IpOwoJCQkJUHJvY2Vzc2luZ1N0ZXBIYW5kbGVyIGhhbmRsZXIgPSBuZXcgUHJvY2Vzc2luZ1N0ZXBIYW5kbGVyKCk7CgkJCQlPdXRwdXRTdHJlYW0gZGVzdGluYXRpb24gPSBoYW5kbGVyLmxpbmsobmV3IFByb2Nlc3NpbmdTdGVwW10ge2RpZmZTdGVwfSwgcmVwb3NpdG9yeVN0cmVhbSwgbnVsbCk7CgoJCQkJLy8gRG8gdGhlIGFjdHVhbCB3b3JrIGJ5IGFza2luZyB0aGUgcmVwbyB0byBnZXQgdGhlIGFydGlmYWN0IGFuZCBwdXQgaXQgaW4gdGhlIGRlc3RpbmF0aW9uLgoJCQkJSVN0YXR1cyBzdGF0dXMgPSByZXBvc2l0b3J5LmdldEFydGlmYWN0KGNvbXBsZXRlLCBkZXN0aW5hdGlvbiwgbmV3IE51bGxQcm9ncmVzc01vbml0b3IoKSk7CgkJCQlpZiAoIXN0YXR1cy5pc09LKCkpIHsKCQkJCQlTeXN0ZW0ub3V0LnByaW50bG4oIkdldHRpbmcgdGhlIGFydGlmYWN0IGlzIG5vdCBvay4iKTsgLy8kTk9OLU5MUy0xJAoJCQkJCVN5c3RlbS5vdXQucHJpbnRsbihzdGF0dXMpOwoJCQkJfQoJCQl9IGNhdGNoIChQcm92aXNpb25FeGNlcHRpb24gZSkgewoJCQkJU3lzdGVtLm91dC5wcmludGxuKCJTa2lwcGluZyBvcHRpbWl6YXRpb24gb2Y6ICIgKyBkZXNjcmlwdG9yc1tpXS5nZXRBcnRpZmFjdEtleSgpKTsgLy8kTk9OLU5MUy0xJAoJCQkJU3lzdGVtLm91dC5wcmludGxuKGUuZ2V0TWVzc2FnZSgpKTsKCQkJCWUucHJpbnRTdGFja1RyYWNlKCk7CgkJCX0gZmluYWxseSB7CgkJCQlpZiAocmVwb3NpdG9yeVN0cmVhbSAhPSBudWxsKQoJCQkJCXRyeSB7CgkJCQkJCXJlcG9zaXRvcnlTdHJlYW0uY2xvc2UoKTsKCQkJCQkJSVN0YXR1cyBzdGF0dXMgPSBQcm9jZXNzaW5nU3RlcEhhbmRsZXIuY2hlY2tTdGF0dXMocmVwb3NpdG9yeVN0cmVhbSk7CgkJCQkJCWlmICghc3RhdHVzLmlzT0soKSkgewoJCQkJCQkJU3lzdGVtLm91dC5wcmludGxuKCJTa2lwcGluZyBvcHRpbWl6YXRpb24gb2Y6ICIgKyBkZXNjcmlwdG9yc1tpXS5nZXRBcnRpZmFjdEtleSgpKTsgLy8kTk9OLU5MUy0xJAoJCQkJCQkJU3lzdGVtLm91dC5wcmludGxuKHN0YXR1cy50b1N0cmluZygpKTsKCQkJCQkJfQoJCQkJCX0gY2F0Y2ggKElPRXhjZXB0aW9uIGUpIHsKCQkJCQkJU3lzdGVtLm91dC5wcmludGxuKCJTa2lwcGluZyBvcHRpbWl6YXRpb24gb2Y6ICIgKyBkZXNjcmlwdG9yc1tpXS5nZXRBcnRpZmFjdEtleSgpKTsgLy8kTk9OLU5MUy0xJAoJCQkJCQlTeXN0ZW0ub3V0LnByaW50bG4oZS5nZXRNZXNzYWdlKCkpOwoJCQkJCQllLnByaW50U3RhY2tUcmFjZSgpOwoJCQkJCX0KCQkJfQoJCX0KCX0KCglwcml2YXRlIFByb2Nlc3NpbmdTdGVwIGdldFByb2Nlc3NpbmdTdGVwKFN0cmluZyBzdHJhdGVneSkgewoJCWlmIChzdHJhdGVneS5lcXVhbHMoSkJQQVRDSF9TVEVQX0lEKSkKCQkJcmV0dXJuIG5ldyBKQkRpZmZTdGVwKHJlcG9zaXRvcnkpOwoJCXJldHVybiBuZXcgSkJEaWZmWmlwU3RlcChyZXBvc2l0b3J5KTsKCX0KCglwcml2YXRlIElBcnRpZmFjdERlc2NyaXB0b3JbXSBnZXRTb3J0ZWRDb21wbGV0ZVByZWRlY2Vzc29ycyhJQXJ0aWZhY3RLZXkgYXJ0aWZhY3RLZXksIElBcnRpZmFjdEtleVtdIHJlbGF0ZWRBcnRpZmFjdEtleXMpIHsKCQkvLyBnZXQgYWxsIGFydGlmYWN0IGtleXMKCQlMaXN0IGNvbXBsZXRlRGVzY3JpcHRvcnMgPSBuZXcgQXJyYXlMaXN0KHJlbGF0ZWRBcnRpZmFjdEtleXMubGVuZ3RoKTsKCQlmb3IgKGludCBpID0gMDsgaSA8IHJlbGF0ZWRBcnRpZmFjdEtleXMubGVuZ3RoOyBpKyspIHsKCQkJLy8gaWYgd2UgZmluZCC0b3VyIHNlbGa0IHNraXAKCQkJaWYgKHJlbGF0ZWRBcnRpZmFjdEtleXNbaV0uZXF1YWxzKGFydGlmYWN0S2V5KSkKCQkJCWNvbnRpbnVlOwoJCQkvLyBsb29rIGZvciBhIGNvbXBsZXRlIGFydGlmYWN0IGRlc2NyaXB0b3Igb2YgdGhlIGN1cnJlbnQga2V5ICAKCQkJSUFydGlmYWN0RGVzY3JpcHRvcltdIGRlc2NyaXB0b3JzID0gcmVwb3NpdG9yeS5nZXRBcnRpZmFjdERlc2NyaXB0b3JzKHJlbGF0ZWRBcnRpZmFjdEtleXNbaV0pOwoJCQlmb3IgKGludCBqID0gMDsgaiA8IGRlc2NyaXB0b3JzLmxlbmd0aDsgaisrKSB7CgkJCQlpZiAoaXNDYW5vbmljYWwoZGVzY3JpcHRvcnNbal0pKSB7CgkJCQkJY29tcGxldGVEZXNjcmlwdG9ycy5hZGQoZGVzY3JpcHRvcnNbal0pOwoJCQkJCWJyZWFrOwoJCQkJfQoJCQl9CgkJfQoKCQlJQXJ0aWZhY3REZXNjcmlwdG9yW10gY29tcGxldGVTb3J0ZWREZXNjcmlwdG9ycyA9IChJQXJ0aWZhY3REZXNjcmlwdG9yW10pIGNvbXBsZXRlRGVzY3JpcHRvcnMudG9BcnJheShuZXcgSUFydGlmYWN0RGVzY3JpcHRvcltjb21wbGV0ZURlc2NyaXB0b3JzLnNpemUoKV0pOwoJCS8vIFNvcnQsIHNvIHRvIGFsbG93IGEgZGVwdGggbG9va3VwIQoJCUFycmF5cy5zb3J0KGNvbXBsZXRlU29ydGVkRGVzY3JpcHRvcnMsIEFSVElGQUNUX0RFU0NSSVBUT1JfVkVSU0lPTl9DT01QQVJBVE9SKTsKCQlyZXR1cm4gY29tcGxldGVTb3J0ZWREZXNjcmlwdG9yczsKCX0KCglwcml2YXRlIGJvb2xlYW4gaXNPcHRpbWl6ZWQoSUFydGlmYWN0RGVzY3JpcHRvciBkZXNjcmlwdG9yLCBTdHJpbmcgc3RlcElkKSB7CgkJaWYgKGRlc2NyaXB0b3IuZ2V0UHJvY2Vzc2luZ1N0ZXBzKCkubGVuZ3RoICE9IDEpCgkJCXJldHVybiBmYWxzZTsKCQlyZXR1cm4gc3RlcElkLmVxdWFscyhkZXNjcmlwdG9yLmdldFByb2Nlc3NpbmdTdGVwcygpWzBdLmdldFByb2Nlc3NvcklkKCkpOwoJfQoKCXByaXZhdGUgYm9vbGVhbiBpc0Nhbm9uaWNhbChJQXJ0aWZhY3REZXNjcmlwdG9yIGRlc2NyaXB0b3IpIHsKCQkvLyBUT0RPIGxlbmd0aCAhPSAwIGlzIG5vdCBuZWNlc3NhcmlseSBhbiBpbmRpY2F0b3IgZm9yIG5vdCBiZWluZyBjb21wbGV0ZSEgICAKCQlyZXR1cm4gZGVzY3JpcHRvci5nZXRQcm9jZXNzaW5nU3RlcHMoKS5sZW5ndGggPT0gMDsKCX0KCglzdGF0aWMgZmluYWwgY2xhc3MgQXJ0aWZhY3REZXNjcmlwdG9yVmVyc2lvbkNvbXBhcmF0b3IgaW1wbGVtZW50cyBDb21wYXJhdG9yIHsKCQlwdWJsaWMgaW50IGNvbXBhcmUoT2JqZWN0IGFydGlmYWN0RGVzY3JpcHRvcjAsIE9iamVjdCBhcnRpZmFjdERlc2NyaXB0b3IxKSB7CgkJCXJldHVybiAtMSAqICgoSUFydGlmYWN0RGVzY3JpcHRvcikgYXJ0aWZhY3REZXNjcmlwdG9yMCkuZ2V0QXJ0aWZhY3RLZXkoKS5nZXRWZXJzaW9uKCkuY29tcGFyZVRvKCgoSUFydGlmYWN0RGVzY3JpcHRvcikgYXJ0aWZhY3REZXNjcmlwdG9yMSkuZ2V0QXJ0aWZhY3RLZXkoKS5nZXRWZXJzaW9uKCkpOwoJCX0KCX0KCglzdGF0aWMgZmluYWwgY2xhc3MgQXJ0aWZhY3RLZXlWZXJzaW9uQ29tcGFyYXRvciBpbXBsZW1lbnRzIENvbXBhcmF0b3IgewoJCXB1YmxpYyBpbnQgY29tcGFyZShPYmplY3QgYXJ0aWZhY3RLZXkwLCBPYmplY3QgYXJ0aWZhY3RLZXkxKSB7CgkJCXJldHVybiAtMSAqICgoSUFydGlmYWN0S2V5KSBhcnRpZmFjdEtleTApLmdldFZlcnNpb24oKS5jb21wYXJlVG8oKChJQXJ0aWZhY3RLZXkpIGFydGlmYWN0S2V5MSkuZ2V0VmVyc2lvbigpKTsKCQl9Cgl9Cn0K