LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogQ29weXJpZ2h0IChjKSAyMDA3LCAyMDEwIGNvbXBlb3BsZSBBRyBhbmQgb3RoZXJzLgogKiBBbGwgcmlnaHRzIHJlc2VydmVkLiBUaGlzIHByb2dyYW0gYW5kIHRoZSBhY2NvbXBhbnlpbmcgbWF0ZXJpYWxzCiAqIGFyZSBtYWRlIGF2YWlsYWJsZSB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEVjbGlwc2UgUHVibGljIExpY2Vuc2UgdjEuMAogKiB3aGljaCBhY2NvbXBhbmllcyB0aGlzIGRpc3RyaWJ1dGlvbiwgYW5kIGlzIGF2YWlsYWJsZSBhdAogKiBodHRwOi8vd3d3LmVjbGlwc2Uub3JnL2xlZ2FsL2VwbC12MTAuaHRtbAogKgogKiBDb250cmlidXRvcnM6CiAqICAJY29tcGVvcGxlIEFHIChTdGVmYW4gTGllYmlnKSAtIGluaXRpYWwgQVBJIGFuZCBpbXBsZW1lbnRhdGlvbgogKiAJSUJNIENvcnBvcmF0aW9uIC0gb25nb2luZyBkZXZlbG9wbWVudAogKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KcGFja2FnZSBvcmcuZWNsaXBzZS5lcXVpbm94LmludGVybmFsLnAyLmFydGlmYWN0Lm9wdGltaXplcnMuamJkaWZmOwoKaW1wb3J0IGphdmEuaW8uSU9FeGNlcHRpb247CmltcG9ydCBqYXZhLmlvLk91dHB1dFN0cmVhbTsKaW1wb3J0IGphdmEudXRpbC4qOwppbXBvcnQgb3JnLmVjbGlwc2UuY29yZS5ydW50aW1lLklTdGF0dXM7CmltcG9ydCBvcmcuZWNsaXBzZS5jb3JlLnJ1bnRpbWUuTnVsbFByb2dyZXNzTW9uaXRvcjsKaW1wb3J0IG9yZy5lY2xpcHNlLmVxdWlub3guaW50ZXJuYWwucDIuYXJ0aWZhY3Qub3B0aW1pemVycy5WZXJzaW9ubGVzc0FydGlmYWN0S2V5OwppbXBvcnQgb3JnLmVjbGlwc2UuZXF1aW5veC5pbnRlcm5hbC5wcm92aXNpb25hbC5wMi5hcnRpZmFjdC5yZXBvc2l0b3J5LnByb2Nlc3NpbmcuUHJvY2Vzc2luZ1N0ZXA7CmltcG9ydCBvcmcuZWNsaXBzZS5lcXVpbm94LmludGVybmFsLnByb3Zpc2lvbmFsLnAyLmFydGlmYWN0LnJlcG9zaXRvcnkucHJvY2Vzc2luZy5Qcm9jZXNzaW5nU3RlcEhhbmRsZXI7CmltcG9ydCBvcmcuZWNsaXBzZS5lcXVpbm94LnAyLmNvcmUuUHJvdmlzaW9uRXhjZXB0aW9uOwppbXBvcnQgb3JnLmVjbGlwc2UuZXF1aW5veC5wMi5tZXRhZGF0YS5JQXJ0aWZhY3RLZXk7CmltcG9ydCBvcmcuZWNsaXBzZS5lcXVpbm94LnAyLnF1ZXJ5LklRdWVyeVJlc3VsdDsKaW1wb3J0IG9yZy5lY2xpcHNlLmVxdWlub3gucDIucmVwb3NpdG9yeS5hcnRpZmFjdC4qOwppbXBvcnQgb3JnLmVjbGlwc2UuZXF1aW5veC5wMi5yZXBvc2l0b3J5LmFydGlmYWN0LnNwaS5BcnRpZmFjdERlc2NyaXB0b3I7CmltcG9ydCBvcmcuZWNsaXBzZS5lcXVpbm94LnAyLnJlcG9zaXRvcnkuYXJ0aWZhY3Quc3BpLlByb2Nlc3NpbmdTdGVwRGVzY3JpcHRvcjsKCnB1YmxpYyBjbGFzcyBPcHRpbWl6ZXIgewoKCXByaXZhdGUgSUFydGlmYWN0UmVwb3NpdG9yeSByZXBvc2l0b3J5OwoJcHJpdmF0ZSBpbnQgd2lkdGg7Cglwcml2YXRlIGludCBkZXB0aDsKCXByaXZhdGUgYm9vbGVhbiBub3NhcjsKCglwcml2YXRlIHN0YXRpYyBmaW5hbCBTdHJpbmcgSkJQQVRDSF9TVEVQX0lEID0gIm9yZy5lY2xpcHNlLmVxdWlub3gucDIucmVwb3NpdG9yeS5KQlBhdGNoU3RlcCI7IC8vJE5PTi1OTFMtMSQKCXByaXZhdGUgc3RhdGljIGZpbmFsIFN0cmluZyBKQlBBVENIX1NURVBfWklQX0lEID0gIm9yZy5lY2xpcHNlLmVxdWlub3gucDIucmVwb3NpdG9yeS5KQlBhdGNoWmlwU3RlcCI7IC8vJE5PTi1OTFMtMSQKCglwcml2YXRlIHN0YXRpYyBmaW5hbCBDb21wYXJhdG9yPElBcnRpZmFjdERlc2NyaXB0b3I+IEFSVElGQUNUX0RFU0NSSVBUT1JfVkVSU0lPTl9DT01QQVJBVE9SID0gbmV3IEFydGlmYWN0RGVzY3JpcHRvclZlcnNpb25Db21wYXJhdG9yKCk7Cglwcml2YXRlIHN0YXRpYyBmaW5hbCBDb21wYXJhdG9yPElBcnRpZmFjdEtleT4gQVJUSUZBQ1RfS0VZX1ZFUlNJT05fQ09NUEFSQVRPUiA9IG5ldyBBcnRpZmFjdEtleVZlcnNpb25Db21wYXJhdG9yKCk7CgoJLyoqCgkgKiBUaGlzIG9wdGltaXplciBwZXJmb3JtcyBkZWx0YSBnZW5lcmF0aW9uIGJhc2VkIG9uIChjdXJyZW50bHkpIGpiZGlmZi4gCgkgKiBUaGUgb3B0aW1pemF0aW9uIGNhbiBiZSBjb250cm9sbGVkIHdpdGggdGhlILR3aWR0aLQgYW5kIHRoZSC0ZGVwdGi0IHBhcmFtZXRlci4KCSAqILR3aWR0aLQgZGVmaW5lcyBmb3IgaG93IG1hbnkgtHJlbGF0ZWS0IGFydGlmYWN0IGtleXMgYSBkZWx0YSBzaG91bGQgYmUgZ2VuZXJhdGVkLAoJICogc3RhcnRpbmcgZnJvbSB0aGUgbW9zdCB1cC10by1kYXRlLgoJICogtGRlcHRotCBkZWZpbmVzIHRvIGhvdyBtYW55IHByZWRlY2Vzc29yIGEgZGVsdGEgc2hvdWxkIGJlIGdlbmVyYXRlZC4KCSAqIAoJICogV2l0aCBBSyhjLXYpIDogQUsgLSBhcnRpZmFjdCBrZXksIGMgLSBhcnRpZmFjdCBpZCwgdiAtIGFydGlmYWN0IHZlcnNpb24KCSAqIHRoZSC0cmVwb3NpdG9yeSBjb250ZW50tCBjYW4gYmUgdmlld2VkIGEgdHdvIGRpbWVuc2lvbmFsIGFycmF5LCB3aGVyZSB0aGUKCSAqIGFydGlmYWN0IGtleXMgZm9yIHRoZSBzYW1lIGNvbXBvbmVudCBhcmUgaW4gb3JkZXIgb2YgdGhlaXIgdmVyc2lvbjogCgkgKiA8cHJlPjxjb2RlPgoJICogICAgIHc9MSAgICAgICB3PTIKCSAqICAgICAgfCAgICAgICAgfAoJICogICAgICB8ICstLS0tLS0uLS0tLS0tLS0tLS0tKyBkPTIKCSAqICAgICAgfCB8ICstLS0tLi0tLSsgZD0xICAgIHwKCSAqICAgICAgfCB8IHwgICAgfCAgIHwgICAgICAgIHYKCSAqIFsgICAgdiB8IHwgICAgdiAgIHYgICAgICAgIHYKCSAqIFsgQUsoeCwyLjApIEFLKHgsMS41KSBBSyh4LDEuMSkgXQoJICogWyBBSyh5LDIuMCkgQUsoeSwxLjkpIF0KCSAqIFsgQUsoeiwyLjApIEFLKHosMS41KSBBSyh6LDEuMykgQUsoeiwxLjApIF0KCSAqIF0KCSAqIDwvY29kZT48L3ByZT4gIAoJICogRS5nOiB3aXRoIGEgtHdpZHRotCBvZiBvbmUgYW5kIGEgtGRlcHRotCBvZiB0d28gdGhlIG9wdGltaXplciB3b3VsZAoJICogY3JlYXRlIHR3byBkZWx0YXMgZm9yIGNvbXBvbmVudCC0eLQgZnJvbSAxLjUgdG8gMi4wIGFuZCBmcm9tIDEuMSB0byAyLjAuICAgIAoJICogCgkgKiBAcGFyYW0gcmVwb3NpdG9yeQoJICogQHBhcmFtIHdpZHRoCgkgKiBAcGFyYW0gZGVwdGgKCSAqIEBwYXJhbSBub3NhciAKCSAqLwoJcHVibGljIE9wdGltaXplcihJQXJ0aWZhY3RSZXBvc2l0b3J5IHJlcG9zaXRvcnksIGludCB3aWR0aCwgaW50IGRlcHRoLCBib29sZWFuIG5vc2FyKSB7CgkJdGhpcy5yZXBvc2l0b3J5ID0gcmVwb3NpdG9yeTsKCQl0aGlzLndpZHRoID0gd2lkdGg7CgkJdGhpcy5kZXB0aCA9IGRlcHRoOwoJCXRoaXMubm9zYXIgPSBub3NhcjsKCX0KCglwdWJsaWMgdm9pZCBydW4oKSB7CgkJU3lzdGVtLm91dC5wcmludGxuKCJTdGFydGluZyBkZWx0YSAoamJkaWZmKSBvcHRpbWl6YXRpb25zICh3aWR0aD0iICsgd2lkdGggKyAiLCBkZXB0aD0iICsgZGVwdGggKyAiLCBub3Nhcj0iICsgbm9zYXIgKyAiKSIpOwoJCUlRdWVyeVJlc3VsdDxJQXJ0aWZhY3RLZXk+IHF1ZXJ5UmVzdWx0ID0gcmVwb3NpdG9yeS5xdWVyeShBcnRpZmFjdEtleVF1ZXJ5LkFMTF9LRVlTLCBudWxsKTsKCQlJQXJ0aWZhY3RLZXlbXVtdIGtleXMgPSBnZXRTb3J0ZWRSZWxhdGVkQXJ0aWZhY3RLZXlzKHF1ZXJ5UmVzdWx0KTsKCQlmb3IgKGludCBpID0gMDsgaSA8IGtleXMubGVuZ3RoOyBpKyspIHsKCQkJaWYgKGtleXNbaV0ubGVuZ3RoIDwgMikKCQkJCS8vIE5vdGhpbmcgdG8gZGlmZiBoZXJlIQoJCQkJY29udGludWU7CgkJCWludCBtaW5XaWR0aCA9IE1hdGgubWluKHdpZHRoLCBrZXlzW2ldLmxlbmd0aCk7CgkJCWZvciAoaW50IGogPSAwOyBqIDwgbWluV2lkdGg7IGorKykgewoJCQkJSUFydGlmYWN0S2V5IGtleSA9IGtleXNbaV1bal07CgkJCQlib29sZWFuIGlzQXJjaGl2ZSA9IGtleS5nZXRDbGFzc2lmaWVyKCkuZXF1YWxzKCJwbHVnaW4iKTsgLy8kTk9OLU5MUy0xJAoJCQkJU3RyaW5nIHByb3Bvc2VkU3RyYXRlZ3kgPSBpc0FyY2hpdmUgJiYgIW5vc2FyID8gSkJQQVRDSF9TVEVQX1pJUF9JRCA6IEpCUEFUQ0hfU1RFUF9JRDsKCQkJCW9wdGltaXplKGtleXNbaV0sIGtleSwgcHJvcG9zZWRTdHJhdGVneSk7CgkJCX0KCQl9CgkJU3lzdGVtLm91dC5wcmludGxuKCJEb25lLiIpOwoKCX0KCglwcml2YXRlIHZvaWQgb3B0aW1pemUoSUFydGlmYWN0S2V5W10ga2V5cywgSUFydGlmYWN0S2V5IGtleSwgU3RyaW5nIHByb3Bvc2VkU3RyYXRlZ3kpIHRocm93cyBPdXRPZk1lbW9yeUVycm9yIHsKCQlib29sZWFuIHJldHJ5OwoJCWRvIHsKCQkJcmV0cnkgPSBmYWxzZTsKCQkJdHJ5IHsKCQkJCUlBcnRpZmFjdERlc2NyaXB0b3JbXSBkZXNjcmlwdG9ycyA9IHJlcG9zaXRvcnkuZ2V0QXJ0aWZhY3REZXNjcmlwdG9ycyhrZXkpOwoJCQkJSUFydGlmYWN0RGVzY3JpcHRvciBjb21wbGV0ZSA9IG51bGw7CgkJCQlmb3IgKGludCBrID0gMDsgayA8IGRlc2NyaXB0b3JzLmxlbmd0aDsgaysrKSB7CgkJCQkJSUFydGlmYWN0RGVzY3JpcHRvciBkZXNjcmlwdG9yID0gZGVzY3JpcHRvcnNba107CgkJCQkJaWYgKGlzQ2Fub25pY2FsKGRlc2NyaXB0b3IpKQoJCQkJCQljb21wbGV0ZSA9IGRlc2NyaXB0b3I7CgkJCQkJZWxzZSBpZiAoaXNPcHRpbWl6ZWQoZGVzY3JpcHRvciwgcHJvcG9zZWRTdHJhdGVneSkpIHsKCQkJCQkJcHJvcG9zZWRTdHJhdGVneSA9IG51bGw7CgkJCQkJCWJyZWFrOwoJCQkJCX0KCQkJCX0KCQkJCWlmIChwcm9wb3NlZFN0cmF0ZWd5ICE9IG51bGwgJiYgY29tcGxldGUgIT0gbnVsbCkKCQkJCQlvcHRpbWl6ZShjb21wbGV0ZSwgcHJvcG9zZWRTdHJhdGVneSwga2V5cyk7CgkJCX0gY2F0Y2ggKE91dE9mTWVtb3J5RXJyb3IgZSkgewoJCQkJaWYgKEpCUEFUQ0hfU1RFUF9JRC5lcXVhbHMocHJvcG9zZWRTdHJhdGVneSkpCgkJCQkJdGhyb3cgZTsKCQkJCXByb3Bvc2VkU3RyYXRlZ3kgPSBKQlBBVENIX1NURVBfSUQ7CgkJCQlTeXN0ZW0ub3V0LnByaW50bG4oIlJldHJ5IHdpdGggIiArIHByb3Bvc2VkU3RyYXRlZ3kpOwoJCQkJcmV0cnkgPSB0cnVlOwoJCQl9CgkJfSB3aGlsZSAocmV0cnkpOwoJfQoKCS8qKgoJICogVGhpcyBtZXRob2QgcmV0cmlldmVzIGEgbGlzdCBvZiBsaXN0IG9mIElBcnRpZmFjdEtleXMuIFRoZSBhcnRpZmFjdCBrZXlzIGluIHRoZQoJICogbGlzdCBvZiBhcnRpZmFjdCBrZXlzIGFyZSBhbGwgtHN0cm9uZ2x5IHJlbGF0ZWS0IHRvIGVhY2ggb3RoZXIgc3VjaCB0aGF0IGFyZSAgCgkgKiBlcXVhbCBidXQgbm90IGNvbnNpZGVyaW5nIHRoZSB2ZXJzaW9ucy4gVGhpcyBsaXN0IGlzIHNvcnRlZCBzdWNoIHRoYXQgdGhlIAoJICogbmV3ZXIgdmVyc2lvbnMgYXJlIGZpcnN0IGluIHRoZSBsaXN0LjxwPgoJICogV2l0aCBBSyhjLXYpIDogQUsgLSBhcnRpZmFjdCBrZXksIGMgLSBhcnRpZmFjdCBpZCwgdiAtIGFydGlmYWN0IHZlcnNpb24KCSAqIHRoZSByZXN1bHQgaXMgdGhhbiwgZS5nLgoJICogPHByZT48Y29kZT4KCSAqIFsKCSAqIFsgQUsoeCwyLjApIEFLKHgsMS41KSBBSyh4LDEuMSkgXQoJICogWyBBSyh5LDIuMCkgQUsoeSwxLjkpIF0KCSAqIFsgQUsoeiwyLjApIEFLKHosMS41KSBBSyh6LDEuMykgQUsoeiwxLjApIF0KCSAqIF0KCSAqIDwvY29kZT48L3ByZT4gIAoJICogQHBhcmFtIGFydGlmYWN0S2V5cwoJICogQHJldHVybiB0aGUgc29ydGVkIGFydGlmYWN0IGtleXMKCSAqLwoJcHJpdmF0ZSBJQXJ0aWZhY3RLZXlbXVtdIGdldFNvcnRlZFJlbGF0ZWRBcnRpZmFjdEtleXMoSVF1ZXJ5UmVzdWx0PElBcnRpZmFjdEtleT4gYXJ0aWZhY3RLZXlzKSB7CgkJTWFwPElBcnRpZmFjdEtleSwgTGlzdDxJQXJ0aWZhY3RLZXk+PiBtYXAgPSBuZXcgSGFzaE1hcDxJQXJ0aWZhY3RLZXksIExpc3Q8SUFydGlmYWN0S2V5Pj4oKTsKCQlmb3IgKEl0ZXJhdG9yPElBcnRpZmFjdEtleT4gaXRlciA9IGFydGlmYWN0S2V5cy5pdGVyYXRvcigpOyBpdGVyLmhhc05leHQoKTspIHsKCQkJSUFydGlmYWN0S2V5IG54dCA9IGl0ZXIubmV4dCgpOwoJCQlJQXJ0aWZhY3RLZXkgZnJlZUtleSA9IG5ldyBWZXJzaW9ubGVzc0FydGlmYWN0S2V5KG54dCk7CgkJCUxpc3Q8SUFydGlmYWN0S2V5PiB2YWx1ZXMgPSBtYXAuZ2V0KGZyZWVLZXkpOwoJCQlpZiAodmFsdWVzID09IG51bGwpIHsKCQkJCXZhbHVlcyA9IG5ldyBBcnJheUxpc3Q8SUFydGlmYWN0S2V5PigpOwoJCQkJbWFwLnB1dChmcmVlS2V5LCB2YWx1ZXMpOwoJCQl9CgkJCXZhbHVlcy5hZGQobnh0KTsKCQl9CgkJSUFydGlmYWN0S2V5W11bXSBsaXN0cyA9IG5ldyBJQXJ0aWZhY3RLZXlbbWFwLnNpemUoKV1bXTsKCQlpbnQgaSA9IDA7CgkJZm9yIChMaXN0PElBcnRpZmFjdEtleT4gYXJ0aWZhY3RLZXlMaXN0IDogbWFwLnZhbHVlcygpKSB7CgkJCUlBcnRpZmFjdEtleVtdIHJlbGF0ZWRBcnRpZmFjdEtleXMgPSBhcnRpZmFjdEtleUxpc3QudG9BcnJheShuZXcgSUFydGlmYWN0S2V5W2FydGlmYWN0S2V5TGlzdC5zaXplKCldKTsKCQkJQXJyYXlzLnNvcnQocmVsYXRlZEFydGlmYWN0S2V5cywgQVJUSUZBQ1RfS0VZX1ZFUlNJT05fQ09NUEFSQVRPUik7CgkJCWxpc3RzW2krK10gPSByZWxhdGVkQXJ0aWZhY3RLZXlzOwoJCX0KCQlpbnQgY2FuZGlkYXRlcyA9IDA7CgkJZm9yIChpbnQgaWkgPSAwOyBpaSA8IGxpc3RzLmxlbmd0aDsgaWkrKykgewoJCQlmb3IgKGludCBqaiA9IDA7IGpqIDwgbGlzdHNbaWldLmxlbmd0aDsgamorKykgewoJCQkJU3lzdGVtLm91dC5wcmludGxuKGxpc3RzW2lpXVtqal0gKyAiLCAiKTsKCQkJfQoJCQlTeXN0ZW0ub3V0LnByaW50bG4oIiIpOwoJCQlpZiAobGlzdHNbaWldLmxlbmd0aCA+IDEpCgkJCQljYW5kaWRhdGVzKys7CgkJfQoJCVN5c3RlbS5vdXQucHJpbnRsbigiQ2FuZGlkYXRlcyBmb3VuZDogIiArIGNhbmRpZGF0ZXMpOwoJCXJldHVybiBsaXN0czsKCX0KCglwcml2YXRlIHZvaWQgb3B0aW1pemUoSUFydGlmYWN0RGVzY3JpcHRvciBjb21wbGV0ZSwgU3RyaW5nIHN0cmF0ZWd5LCBJQXJ0aWZhY3RLZXlbXSByZWxhdGVkQXJ0aWZhY3RLZXlzKSB7CgkJU3lzdGVtLm91dC5wcmludGxuKCJPcHRpbWl6aW5nICIgKyBjb21wbGV0ZSk7CgoJCUlBcnRpZmFjdERlc2NyaXB0b3JbXSBkZXNjcmlwdG9ycyA9IGdldFNvcnRlZENvbXBsZXRlUHJlZGVjZXNzb3JzKGNvbXBsZXRlLmdldEFydGlmYWN0S2V5KCksIHJlbGF0ZWRBcnRpZmFjdEtleXMpOwoKCQlpbnQgbWluRGVwdGggPSBNYXRoLm1pbihkZXB0aCwgZGVzY3JpcHRvcnMubGVuZ3RoKTsKCQlmb3IgKGludCBpID0gMDsgaSA8IG1pbkRlcHRoOyBpKyspIHsKCgkJCVN5c3RlbS5vdXQucHJpbnRsbigiXHQgd2l0aCAiICsgc3RyYXRlZ3kgKyAiIGFnYWluc3QgIiArIGRlc2NyaXB0b3JzW2ldLmdldEFydGlmYWN0S2V5KCkpOwoJCQlTdHJpbmcgcHJlZGVjZXNzb3JEYXRhID0gZGVzY3JpcHRvcnNbaV0uZ2V0QXJ0aWZhY3RLZXkoKS50b0V4dGVybmFsRm9ybSgpOwoJCQlBcnRpZmFjdERlc2NyaXB0b3IgbmV3RGVzY3JpcHRvciA9IG5ldyBBcnRpZmFjdERlc2NyaXB0b3IoY29tcGxldGUpOwoJCQlJUHJvY2Vzc2luZ1N0ZXBEZXNjcmlwdG9yIHBhdGNoU3RlcCA9IG5ldyBQcm9jZXNzaW5nU3RlcERlc2NyaXB0b3Ioc3RyYXRlZ3ksIHByZWRlY2Vzc29yRGF0YSwgdHJ1ZSk7CgkJCUlQcm9jZXNzaW5nU3RlcERlc2NyaXB0b3JbXSBzdGVwcyA9IG5ldyBJUHJvY2Vzc2luZ1N0ZXBEZXNjcmlwdG9yW10ge3BhdGNoU3RlcH07CgkJCW5ld0Rlc2NyaXB0b3Iuc2V0UHJvY2Vzc2luZ1N0ZXBzKHN0ZXBzKTsKCQkJbmV3RGVzY3JpcHRvci5zZXRQcm9wZXJ0eShJQXJ0aWZhY3REZXNjcmlwdG9yLkZPUk1BVCwgc3RyYXRlZ3kpOwoJCQlPdXRwdXRTdHJlYW0gcmVwb3NpdG9yeVN0cmVhbSA9IG51bGw7CgkJCXRyeSB7CgkJCQlyZXBvc2l0b3J5U3RyZWFtID0gcmVwb3NpdG9yeS5nZXRPdXRwdXRTdHJlYW0obmV3RGVzY3JpcHRvcik7CgoJCQkJLy8gQWRkIGluIGFsbCB0aGUgcHJvY2Vzc2luZyBzdGVwcyBuZWVkZWQgdG8gb3B0aW1pemUgKGUuZy4sIHBhY2syMDAsIC4uLikKCQkJCVByb2Nlc3NpbmdTdGVwIGRpZmZTdGVwID0gZ2V0UHJvY2Vzc2luZ1N0ZXAoc3RyYXRlZ3kpOwoJCQkJZGlmZlN0ZXAuaW5pdGlhbGl6ZShyZXBvc2l0b3J5LmdldFByb3Zpc2lvbmluZ0FnZW50KCksIHBhdGNoU3RlcCwgbmV3RGVzY3JpcHRvcik7CgkJCQlQcm9jZXNzaW5nU3RlcEhhbmRsZXIgaGFuZGxlciA9IG5ldyBQcm9jZXNzaW5nU3RlcEhhbmRsZXIoKTsKCQkJCU91dHB1dFN0cmVhbSBkZXN0aW5hdGlvbiA9IGhhbmRsZXIubGluayhuZXcgUHJvY2Vzc2luZ1N0ZXBbXSB7ZGlmZlN0ZXB9LCByZXBvc2l0b3J5U3RyZWFtLCBudWxsKTsKCgkJCQkvLyBEbyB0aGUgYWN0dWFsIHdvcmsgYnkgYXNraW5nIHRoZSByZXBvIHRvIGdldCB0aGUgYXJ0aWZhY3QgYW5kIHB1dCBpdCBpbiB0aGUgZGVzdGluYXRpb24uCgkJCQlJU3RhdHVzIHN0YXR1cyA9IHJlcG9zaXRvcnkuZ2V0QXJ0aWZhY3QoY29tcGxldGUsIGRlc3RpbmF0aW9uLCBuZXcgTnVsbFByb2dyZXNzTW9uaXRvcigpKTsKCQkJCWlmICghc3RhdHVzLmlzT0soKSkgewoJCQkJCVN5c3RlbS5vdXQucHJpbnRsbigiR2V0dGluZyB0aGUgYXJ0aWZhY3QgaXMgbm90IG9rLiIpOyAvLyROT04tTkxTLTEkCgkJCQkJU3lzdGVtLm91dC5wcmludGxuKHN0YXR1cyk7CgkJCQl9CgkJCX0gY2F0Y2ggKFByb3Zpc2lvbkV4Y2VwdGlvbiBlKSB7CgkJCQlTeXN0ZW0ub3V0LnByaW50bG4oIlNraXBwaW5nIG9wdGltaXphdGlvbiBvZjogIiArIGRlc2NyaXB0b3JzW2ldLmdldEFydGlmYWN0S2V5KCkpOyAvLyROT04tTkxTLTEkCgkJCQlTeXN0ZW0ub3V0LnByaW50bG4oZS5nZXRNZXNzYWdlKCkpOwoJCQkJZS5wcmludFN0YWNrVHJhY2UoKTsKCQkJfSBmaW5hbGx5IHsKCQkJCWlmIChyZXBvc2l0b3J5U3RyZWFtICE9IG51bGwpCgkJCQkJdHJ5IHsKCQkJCQkJcmVwb3NpdG9yeVN0cmVhbS5jbG9zZSgpOwoJCQkJCQlJU3RhdHVzIHN0YXR1cyA9IFByb2Nlc3NpbmdTdGVwSGFuZGxlci5jaGVja1N0YXR1cyhyZXBvc2l0b3J5U3RyZWFtKTsKCQkJCQkJaWYgKCFzdGF0dXMuaXNPSygpKSB7CgkJCQkJCQlTeXN0ZW0ub3V0LnByaW50bG4oIlNraXBwaW5nIG9wdGltaXphdGlvbiBvZjogIiArIGRlc2NyaXB0b3JzW2ldLmdldEFydGlmYWN0S2V5KCkpOyAvLyROT04tTkxTLTEkCgkJCQkJCQlTeXN0ZW0ub3V0LnByaW50bG4oc3RhdHVzLnRvU3RyaW5nKCkpOwoJCQkJCQl9CgkJCQkJfSBjYXRjaCAoSU9FeGNlcHRpb24gZSkgewoJCQkJCQlTeXN0ZW0ub3V0LnByaW50bG4oIlNraXBwaW5nIG9wdGltaXphdGlvbiBvZjogIiArIGRlc2NyaXB0b3JzW2ldLmdldEFydGlmYWN0S2V5KCkpOyAvLyROT04tTkxTLTEkCgkJCQkJCVN5c3RlbS5vdXQucHJpbnRsbihlLmdldE1lc3NhZ2UoKSk7CgkJCQkJCWUucHJpbnRTdGFja1RyYWNlKCk7CgkJCQkJfQoJCQl9CgkJfQoJfQoKCXByaXZhdGUgUHJvY2Vzc2luZ1N0ZXAgZ2V0UHJvY2Vzc2luZ1N0ZXAoU3RyaW5nIHN0cmF0ZWd5KSB7CgkJaWYgKHN0cmF0ZWd5LmVxdWFscyhKQlBBVENIX1NURVBfSUQpKQoJCQlyZXR1cm4gbmV3IEpCRGlmZlN0ZXAocmVwb3NpdG9yeSk7CgkJcmV0dXJuIG5ldyBKQkRpZmZaaXBTdGVwKHJlcG9zaXRvcnkpOwoJfQoKCXByaXZhdGUgSUFydGlmYWN0RGVzY3JpcHRvcltdIGdldFNvcnRlZENvbXBsZXRlUHJlZGVjZXNzb3JzKElBcnRpZmFjdEtleSBhcnRpZmFjdEtleSwgSUFydGlmYWN0S2V5W10gcmVsYXRlZEFydGlmYWN0S2V5cykgewoJCS8vIGdldCBhbGwgYXJ0aWZhY3Qga2V5cwoJCUxpc3Q8SUFydGlmYWN0RGVzY3JpcHRvcj4gY29tcGxldGVEZXNjcmlwdG9ycyA9IG5ldyBBcnJheUxpc3Q8SUFydGlmYWN0RGVzY3JpcHRvcj4ocmVsYXRlZEFydGlmYWN0S2V5cy5sZW5ndGgpOwoJCWZvciAoaW50IGkgPSAwOyBpIDwgcmVsYXRlZEFydGlmYWN0S2V5cy5sZW5ndGg7IGkrKykgewoJCQkvLyBpZiB3ZSBmaW5kILRvdXIgc2VsZrQgc2tpcAoJCQlpZiAocmVsYXRlZEFydGlmYWN0S2V5c1tpXS5lcXVhbHMoYXJ0aWZhY3RLZXkpKQoJCQkJY29udGludWU7CgkJCS8vIGxvb2sgZm9yIGEgY29tcGxldGUgYXJ0aWZhY3QgZGVzY3JpcHRvciBvZiB0aGUgY3VycmVudCBrZXkgIAoJCQlJQXJ0aWZhY3REZXNjcmlwdG9yW10gZGVzY3JpcHRvcnMgPSByZXBvc2l0b3J5LmdldEFydGlmYWN0RGVzY3JpcHRvcnMocmVsYXRlZEFydGlmYWN0S2V5c1tpXSk7CgkJCWZvciAoaW50IGogPSAwOyBqIDwgZGVzY3JpcHRvcnMubGVuZ3RoOyBqKyspIHsKCQkJCWlmIChpc0Nhbm9uaWNhbChkZXNjcmlwdG9yc1tqXSkpIHsKCQkJCQljb21wbGV0ZURlc2NyaXB0b3JzLmFkZChkZXNjcmlwdG9yc1tqXSk7CgkJCQkJYnJlYWs7CgkJCQl9CgkJCX0KCQl9CgoJCUlBcnRpZmFjdERlc2NyaXB0b3JbXSBjb21wbGV0ZVNvcnRlZERlc2NyaXB0b3JzID0gY29tcGxldGVEZXNjcmlwdG9ycy50b0FycmF5KG5ldyBJQXJ0aWZhY3REZXNjcmlwdG9yW2NvbXBsZXRlRGVzY3JpcHRvcnMuc2l6ZSgpXSk7CgkJLy8gU29ydCwgc28gdG8gYWxsb3cgYSBkZXB0aCBsb29rdXAhCgkJQXJyYXlzLnNvcnQoY29tcGxldGVTb3J0ZWREZXNjcmlwdG9ycywgQVJUSUZBQ1RfREVTQ1JJUFRPUl9WRVJTSU9OX0NPTVBBUkFUT1IpOwoJCXJldHVybiBjb21wbGV0ZVNvcnRlZERlc2NyaXB0b3JzOwoJfQoKCXByaXZhdGUgYm9vbGVhbiBpc09wdGltaXplZChJQXJ0aWZhY3REZXNjcmlwdG9yIGRlc2NyaXB0b3IsIFN0cmluZyBzdGVwSWQpIHsKCQlpZiAoZGVzY3JpcHRvci5nZXRQcm9jZXNzaW5nU3RlcHMoKS5sZW5ndGggIT0gMSkKCQkJcmV0dXJuIGZhbHNlOwoJCXJldHVybiBzdGVwSWQuZXF1YWxzKGRlc2NyaXB0b3IuZ2V0UHJvY2Vzc2luZ1N0ZXBzKClbMF0uZ2V0UHJvY2Vzc29ySWQoKSk7Cgl9CgoJcHJpdmF0ZSBib29sZWFuIGlzQ2Fub25pY2FsKElBcnRpZmFjdERlc2NyaXB0b3IgZGVzY3JpcHRvcikgewoJCS8vIFRPRE8gbGVuZ3RoICE9IDAgaXMgbm90IG5lY2Vzc2FyaWx5IGFuIGluZGljYXRvciBmb3Igbm90IGJlaW5nIGNvbXBsZXRlISAgIAoJCXJldHVybiBkZXNjcmlwdG9yLmdldFByb2Nlc3NpbmdTdGVwcygpLmxlbmd0aCA9PSAwOwoJfQoKCXN0YXRpYyBmaW5hbCBjbGFzcyBBcnRpZmFjdERlc2NyaXB0b3JWZXJzaW9uQ29tcGFyYXRvciBpbXBsZW1lbnRzIENvbXBhcmF0b3I8SUFydGlmYWN0RGVzY3JpcHRvcj4gewoJCXB1YmxpYyBpbnQgY29tcGFyZShJQXJ0aWZhY3REZXNjcmlwdG9yIGFydGlmYWN0RGVzY3JpcHRvcjAsIElBcnRpZmFjdERlc2NyaXB0b3IgYXJ0aWZhY3REZXNjcmlwdG9yMSkgewoJCQlyZXR1cm4gLTEgKiBhcnRpZmFjdERlc2NyaXB0b3IwLmdldEFydGlmYWN0S2V5KCkuZ2V0VmVyc2lvbigpLmNvbXBhcmVUbyhhcnRpZmFjdERlc2NyaXB0b3IxLmdldEFydGlmYWN0S2V5KCkuZ2V0VmVyc2lvbigpKTsKCQl9Cgl9CgoJc3RhdGljIGZpbmFsIGNsYXNzIEFydGlmYWN0S2V5VmVyc2lvbkNvbXBhcmF0b3IgaW1wbGVtZW50cyBDb21wYXJhdG9yPElBcnRpZmFjdEtleT4gewoJCXB1YmxpYyBpbnQgY29tcGFyZShJQXJ0aWZhY3RLZXkgYXJ0aWZhY3RLZXkwLCBJQXJ0aWZhY3RLZXkgYXJ0aWZhY3RLZXkxKSB7CgkJCXJldHVybiAtMSAqIGFydGlmYWN0S2V5MC5nZXRWZXJzaW9uKCkuY29tcGFyZVRvKGFydGlmYWN0S2V5MS5nZXRWZXJzaW9uKCkpOwoJCX0KCX0KfQo=