LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogQ29weXJpZ2h0IChjKSAyMDAzLCAyMDA1IElCTSBDb3Jwb3JhdGlvbiBhbmQgb3RoZXJzLgogKiBBbGwgcmlnaHRzIHJlc2VydmVkLiBUaGlzIHByb2dyYW0gYW5kIHRoZSBhY2NvbXBhbnlpbmcgbWF0ZXJpYWxzCiAqIGFyZSBtYWRlIGF2YWlsYWJsZSB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEVjbGlwc2UgUHVibGljIExpY2Vuc2UgdjEuMAogKiB3aGljaCBhY2NvbXBhbmllcyB0aGlzIGRpc3RyaWJ1dGlvbiwgYW5kIGlzIGF2YWlsYWJsZSBhdAogKiBodHRwOi8vd3d3LmVjbGlwc2Uub3JnL2xlZ2FsL2VwbC12MTAuaHRtbAqgKiAKICogQ29udHJpYnV0b3JzOgogKiAgICAgSUJNIENvcnBvcmF0aW9uIC0gSW5pdGlhbCBBUEkgYW5kIGltcGxlbWVudGF0aW9uCiAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLwpwYWNrYWdlIG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIuY29yZS5pbnRlcm5hbDsKCmltcG9ydCBqYXZhLmlvLkZpbGVJbnB1dFN0cmVhbTsKaW1wb3J0IGphdmEuaW8uSW5wdXRTdHJlYW07CmltcG9ydCBqYXZhLnV0aWwuQXJyYXlMaXN0OwppbXBvcnQgamF2YS51dGlsLkhhc2hNYXA7CmltcG9ydCBqYXZhLnV0aWwuSXRlcmF0b3I7CmltcG9ydCBqYXZhLnV0aWwuTGlzdDsKaW1wb3J0IGphdmEudXRpbC5NYXA7CgppbXBvcnQgb3JnLmVjbGlwc2UuY29yZS5yZXNvdXJjZXMuSUZpbGU7CmltcG9ydCBvcmcuZWNsaXBzZS5jb3JlLnJ1bnRpbWUuKjsKaW1wb3J0IG9yZy5lY2xpcHNlLm9zZ2kudXRpbC5OTFM7Ci8qKgogKiBIZWxwZXIgY2xhc3MgZm9yIHN0b3JpbmcgcnVudGltZSBhbmQgc2VydmVyIGF0dHJpYnV0ZXMuCiAqLwpwdWJsaWMgYWJzdHJhY3QgY2xhc3MgQmFzZSB7Cglwcm90ZWN0ZWQgc3RhdGljIGZpbmFsIFN0cmluZyBQUk9QX0xPQ0tFRCA9ICJsb2NrZWQiOwoJcHJvdGVjdGVkIHN0YXRpYyBmaW5hbCBTdHJpbmcgUFJPUF9QUklWQVRFID0gInByaXZhdGUiOwoJcHJvdGVjdGVkIHN0YXRpYyBmaW5hbCBTdHJpbmcgUFJPUF9OQU1FID0gIm5hbWUiOwoJcHJvdGVjdGVkIHN0YXRpYyBmaW5hbCBTdHJpbmcgUFJPUF9JRCA9ICJpZCI7CgoJcHJvdGVjdGVkIE1hcCBtYXAgPSBuZXcgSGFzaE1hcCgpOwoJCgkvLyBmaWxlIGxvYWRlZCBmcm9tLCBvciBudWxsIGlmIGl0IGlzIHNhdmVkIGluIG1ldGFkYXRhCglwcm90ZWN0ZWQgSUZpbGUgZmlsZTsKCQoJLyoqCgkgKiBDcmVhdGUgYSBuZXcgb2JqZWN0LgoJICogCgkgKiBAcGFyYW0gZmlsZQoJICovCglwdWJsaWMgQmFzZShJRmlsZSBmaWxlKSB7CgkJdGhpcy5maWxlID0gZmlsZTsKCX0KCgkvKioKCSAqIENyZWF0ZSBhIG5ldyBvYmplY3QuCgkgKiAKCSAqIEBwYXJhbSBmaWxlCgkgKiBAcGFyYW0gaWQKCSAqLwoJcHVibGljIEJhc2UoSUZpbGUgZmlsZSwgU3RyaW5nIGlkKSB7CgkJdGhpcy5maWxlID0gZmlsZTsKCQkvL3RoaXMubWFwID0gbWFwOwoJCW1hcC5wdXQoUFJPUF9JRCwgaWQpOwoJfQoKCS8qKgoJICogUmV0dXJucyB0aGUgdGltZXN0YW1wIG9mIHRoaXMgb2JqZWN0LgoJICogVGltZXN0YW1wcyBhcmUgbW9ub3RvbmljYWxseSBpbmNyZWFzZWQgZWFjaCB0aW1lIHRoZSBvYmplY3QgaXMgc2F2ZWQKCSAqIGFuZCBjYW4gYmUgdXNlZCB0byBkZXRlcm1pbmUgaWYgYW55IGNoYW5nZXMgaGF2ZSBiZWVuIG1hZGUgb24gZGlzawoJICogc2luY2UgdGhlIG9iamVjdCB3YXMgbG9hZGVkLgoJICogCgkgKiBAcmV0dXJuIHRoZSBvYmplY3QncyB0aW1lc3RhbXAKCSAqLwoJcHVibGljIGludCBnZXRUaW1lc3RhbXAoKSB7CgkJcmV0dXJuIGdldEF0dHJpYnV0ZSgidGltZXN0YW1wIiwgLTEpOwoJfQoKCS8qKgoJICogUmV0dXJucyB0aGUgZmlsZSB3aGVyZSB0aGlzIHNlcnZlciBpbnN0YW5jZSBpcyBzZXJpYWxpemVkLgoJICogCgkgKiBAcmV0dXJuIHRoZSBmaWxlIGluIHRoZSB3b3Jrc3BhY2Ugd2hlcmUgdGhlIHNlcnZlciBpbnN0YW5jZQoJICogaXMgc2VyaWFsaXplZCwgb3IgPGNvZGU+bnVsbDwvY29kZT4gaWYgdGhlIGluZm9ybWF0aW9uIGlzCgkgKiBpbnN0ZWFkIHRvIGJlIHBlcnNpc3RlZCB3aXRoIHRoZSB3b3Jrc3BhY2UgYnV0IG5vdCB3aXRoIGFueQoJICogcGFydGljdWxhciB3b3Jrc3BhY2UgcmVzb3VyY2UKCSAqLwoJcHVibGljIElGaWxlIGdldEZpbGUoKSB7CgkJcmV0dXJuIGZpbGU7Cgl9CgoJcHVibGljIFN0cmluZyBnZXRBdHRyaWJ1dGUoU3RyaW5nIGF0dHJpYnV0ZU5hbWUsIFN0cmluZyBkZWZhdWx0VmFsdWUpIHsKCQl0cnkgewoJCQlPYmplY3Qgb2JqID0gbWFwLmdldChhdHRyaWJ1dGVOYW1lKTsKCQkJaWYgKG9iaiA9PSBudWxsKQoJCQkJcmV0dXJuIGRlZmF1bHRWYWx1ZTsKCQkJcmV0dXJuIChTdHJpbmcpIG9iajsKCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkvLyBpZ25vcmUKCQl9CgkJcmV0dXJuIGRlZmF1bHRWYWx1ZTsKCX0KCglwdWJsaWMgaW50IGdldEF0dHJpYnV0ZShTdHJpbmcgYXR0cmlidXRlTmFtZSwgaW50IGRlZmF1bHRWYWx1ZSkgewoJCXRyeSB7CgkJCU9iamVjdCBvYmogPSBtYXAuZ2V0KGF0dHJpYnV0ZU5hbWUpOwoJCQlpZiAob2JqID09IG51bGwpCgkJCQlyZXR1cm4gZGVmYXVsdFZhbHVlOwoJCQlyZXR1cm4gSW50ZWdlci5wYXJzZUludCgoU3RyaW5nKSBvYmopOwoJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCS8vIGlnbm9yZQoJCX0KCQlyZXR1cm4gZGVmYXVsdFZhbHVlOwoJfQoKCXB1YmxpYyBib29sZWFuIGdldEF0dHJpYnV0ZShTdHJpbmcgYXR0cmlidXRlTmFtZSwgYm9vbGVhbiBkZWZhdWx0VmFsdWUpIHsKCQl0cnkgewoJCQlPYmplY3Qgb2JqID0gbWFwLmdldChhdHRyaWJ1dGVOYW1lKTsKCQkJaWYgKG9iaiA9PSBudWxsKQoJCQkJcmV0dXJuIGRlZmF1bHRWYWx1ZTsKCQkJcmV0dXJuIEJvb2xlYW4udmFsdWVPZigoU3RyaW5nKSBvYmopLmJvb2xlYW5WYWx1ZSgpOwoJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCS8vIGlnbm9yZQoJCX0KCQlyZXR1cm4gZGVmYXVsdFZhbHVlOwoJfQoJCglwdWJsaWMgTGlzdCBnZXRBdHRyaWJ1dGUoU3RyaW5nIGF0dHJpYnV0ZU5hbWUsIExpc3QgZGVmYXVsdFZhbHVlKSB7CgkJdHJ5IHsKCQkJT2JqZWN0IG9iaiA9IG1hcC5nZXQoYXR0cmlidXRlTmFtZSk7CgkJCWlmIChvYmogPT0gbnVsbCkKCQkJCXJldHVybiBkZWZhdWx0VmFsdWU7CgkJCUxpc3QgbGlzdCA9IChMaXN0KSBvYmo7CgkJCWlmIChsaXN0ICE9IG51bGwpCgkJCQlyZXR1cm4gbGlzdDsKCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkvLyBpZ25vcmUKCQl9CgkJcmV0dXJuIGRlZmF1bHRWYWx1ZTsKCX0KCQoJcHVibGljIE1hcCBnZXRBdHRyaWJ1dGUoU3RyaW5nIGF0dHJpYnV0ZU5hbWUsIE1hcCBkZWZhdWx0VmFsdWUpIHsKCQl0cnkgewoJCQlPYmplY3Qgb2JqID0gbWFwLmdldChhdHRyaWJ1dGVOYW1lKTsKCQkJaWYgKG9iaiA9PSBudWxsKQoJCQkJcmV0dXJuIGRlZmF1bHRWYWx1ZTsKCQkJTWFwIG1hcDIgPSAoTWFwKSBvYmo7CgkJCWlmIChtYXAyICE9IG51bGwpCgkJCQlyZXR1cm4gbWFwMjsKCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkvLyBpZ25vcmUKCQl9CgkJcmV0dXJuIGRlZmF1bHRWYWx1ZTsKCX0KCglwdWJsaWMgU3RyaW5nIGdldElkKCkgewoJCXJldHVybiBnZXRBdHRyaWJ1dGUoUFJPUF9JRCwgIiIpOwoJfQoKCXB1YmxpYyBTdHJpbmcgZ2V0TmFtZSgpIHsKCQlyZXR1cm4gZ2V0QXR0cmlidXRlKFBST1BfTkFNRSwgIiIpOwoJfQoKCXB1YmxpYyBib29sZWFuIGlzUmVhZE9ubHkoKSB7CgkJcmV0dXJuIGdldEF0dHJpYnV0ZShQUk9QX0xPQ0tFRCwgZmFsc2UpOwoJfQoKCS8qKgoJICogUmV0dXJucyA8Y29kZT50cnVlPC9jb2RlPiBpZiB0aGlzIHJ1bnRpbWUgaXMgcHJpdmF0ZSAobm90IHNob3duCgkgKiBpbiB0aGUgVUkgdG8gdGhlIHVzZXJzKSwgYW5kIDxjb2RlPmZhbHNlPC9jb2RlPiBvdGhlcndpc2UuCgkgKiAKCSAqIEByZXR1cm4gPGNvZGU+dHJ1ZTwvY29kZT4gaWYgdGhpcyBydW50aW1lIGlzIHByaXZhdGUsCgkgKiAgICBhbmQgPGNvZGU+ZmFsc2U8L2NvZGU+IG90aGVyd2lzZQoJICovCglwdWJsaWMgYm9vbGVhbiBpc1ByaXZhdGUoKSB7CgkJcmV0dXJuIGdldEF0dHJpYnV0ZShQUk9QX1BSSVZBVEUsIGZhbHNlKTsKCX0KCQoJcHVibGljIGJvb2xlYW4gaXNXb3JraW5nQ29weSgpIHsKCQlyZXR1cm4gZmFsc2U7Cgl9CgkKCXByb3RlY3RlZCBhYnN0cmFjdCBTdHJpbmcgZ2V0WE1MUm9vdCgpOwoJCglwcm90ZWN0ZWQgdm9pZCBzYXZlKElNZW1lbnRvIG1lbWVudG8pIHsKCQkvL0lNZW1lbnRvIGNoaWxkID0gbWVtZW50by5jcmVhdGVDaGlsZCgicHJvcGVydGllcyIpOwoJCUlNZW1lbnRvIGNoaWxkID0gbWVtZW50bzsKCQlJdGVyYXRvciBpdGVyYXRvciA9IG1hcC5rZXlTZXQoKS5pdGVyYXRvcigpOwoJCXdoaWxlIChpdGVyYXRvci5oYXNOZXh0KCkpIHsKCQkJU3RyaW5nIGtleSA9IChTdHJpbmcpIGl0ZXJhdG9yLm5leHQoKTsKCQkJT2JqZWN0IG9iaiA9IG1hcC5nZXQoa2V5KTsKCQkJaWYgKG9iaiBpbnN0YW5jZW9mIFN0cmluZykKCQkJCWNoaWxkLnB1dFN0cmluZyhrZXksIChTdHJpbmcpIG9iaik7CgkJCWVsc2UgaWYgKG9iaiBpbnN0YW5jZW9mIEludGVnZXIpIHsKCQkJCUludGVnZXIgaW4gPSAoSW50ZWdlcikgb2JqOwoJCQkJY2hpbGQucHV0SW50ZWdlcihrZXksIGluLmludFZhbHVlKCkpOwoJCQl9IGVsc2UgaWYgKG9iaiBpbnN0YW5jZW9mIEJvb2xlYW4pIHsKCQkJCUJvb2xlYW4gYm9vbCA9IChCb29sZWFuKSBvYmo7CgkJCQljaGlsZC5wdXRCb29sZWFuKGtleSwgYm9vbC5ib29sZWFuVmFsdWUoKSk7CgkJCX0gZWxzZSBpZiAob2JqIGluc3RhbmNlb2YgTGlzdCkgewoJCQkJTGlzdCBsaXN0ID0gKExpc3QpIG9iajsKCQkJCXNhdmVMaXN0KGNoaWxkLCBrZXksIGxpc3QpOwoJCQl9IGVsc2UgaWYgKG9iaiBpbnN0YW5jZW9mIE1hcCkgewoJCQkJTWFwIG1hcDIgPSAoTWFwKSBvYmo7CgkJCQlzYXZlTWFwKGNoaWxkLCBrZXksIG1hcDIpOwoJCQkJCgkJCX0KCQl9CgkJc2F2ZVN0YXRlKGNoaWxkKTsKCX0KCXByb3RlY3RlZCB2b2lkIHNhdmVNYXAoSU1lbWVudG8gbWVtZW50bywgU3RyaW5nIGtleSwgTWFwIG1hcDIpIHsKCQlJTWVtZW50byBjaGlsZCA9IG1lbWVudG8uY3JlYXRlQ2hpbGQoIm1hcCIpOwoJCWNoaWxkLnB1dFN0cmluZygia2V5Iiwga2V5KTsKCQlJdGVyYXRvciBpdGVyYXRvciA9IG1hcDIua2V5U2V0KCkuaXRlcmF0b3IoKTsKCQl3aGlsZSAoaXRlcmF0b3IuaGFzTmV4dCgpKSB7CgkJCVN0cmluZyBzID0gKFN0cmluZykgaXRlcmF0b3IubmV4dCgpOwoJCQljaGlsZC5wdXRTdHJpbmcocywgKFN0cmluZyltYXAyLmdldChzKSk7CgkJfQoJfQoJCglwcm90ZWN0ZWQgdm9pZCBzYXZlTGlzdChJTWVtZW50byBtZW1lbnRvLCBTdHJpbmcga2V5LCBMaXN0IGxpc3QpIHsKCQlJTWVtZW50byBjaGlsZCA9IG1lbWVudG8uY3JlYXRlQ2hpbGQoImxpc3QiKTsKCQljaGlsZC5wdXRTdHJpbmcoImtleSIsIGtleSk7CgkJaW50IGkgPSAwOwoJCUl0ZXJhdG9yIGl0ZXJhdG9yID0gbGlzdC5pdGVyYXRvcigpOwoJCXdoaWxlIChpdGVyYXRvci5oYXNOZXh0KCkpIHsKCQkJU3RyaW5nIHMgPSAoU3RyaW5nKSBpdGVyYXRvci5uZXh0KCk7CgkJCWNoaWxkLnB1dFN0cmluZygidmFsdWUiICsgKGkrKyksIHMpOwoJCX0KCX0KCglwcm90ZWN0ZWQgdm9pZCBzYXZlVG9GaWxlKElQcm9ncmVzc01vbml0b3IgbW9uaXRvcikgdGhyb3dzIENvcmVFeGNlcHRpb24gewoJCXRyeSB7CgkJCVhNTE1lbWVudG8gbWVtZW50byA9IFhNTE1lbWVudG8uY3JlYXRlV3JpdGVSb290KGdldFhNTFJvb3QoKSk7CgkJCXNhdmUobWVtZW50byk7CgoJCQlJbnB1dFN0cmVhbSBpbiA9IG1lbWVudG8uZ2V0SW5wdXRTdHJlYW0oKTsKCQkJaWYgKGZpbGUuZXhpc3RzKCkpCgkJCQlmaWxlLnNldENvbnRlbnRzKGluLCB0cnVlLCB0cnVlLCBQcm9ncmVzc1V0aWwuZ2V0U3ViTW9uaXRvckZvcihtb25pdG9yLCAxMDAwKSk7CgkJCWVsc2UKCQkJCWZpbGUuY3JlYXRlKGluLCB0cnVlLCBQcm9ncmVzc1V0aWwuZ2V0U3ViTW9uaXRvckZvcihtb25pdG9yLCAxMDAwKSk7CgkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiQ291bGQgbm90IHNhdmUgIiArIGdldFhNTFJvb3QoKSwgZSk7CgkJCXRocm93IG5ldyBDb3JlRXhjZXB0aW9uKG5ldyBTdGF0dXMoSVN0YXR1cy5FUlJPUiwgU2VydmVyUGx1Z2luLlBMVUdJTl9JRCwgMCwgTkxTLmJpbmQoTWVzc2FnZXMuZXJyb3JTYXZpbmcsIGdldEZpbGUoKS50b1N0cmluZygpKSwgZSkpOwoJCX0KCX0KCQoJcHJvdGVjdGVkIHZvaWQgZG9TYXZlKElQcm9ncmVzc01vbml0b3IgbW9uaXRvcikgdGhyb3dzIENvcmVFeGNlcHRpb24gewoJCWlmIChmaWxlICE9IG51bGwpCgkJCXNhdmVUb0ZpbGUobW9uaXRvcik7CgkJZWxzZQoJCQlzYXZlVG9NZXRhZGF0YShtb25pdG9yKTsKCQlSZXNvdXJjZU1hbmFnZXIuZ2V0SW5zdGFuY2UoKS5yZXNvbHZlU2VydmVycygpOwoJfQoJCglwcm90ZWN0ZWQgdm9pZCBzYXZlVG9NZXRhZGF0YShJUHJvZ3Jlc3NNb25pdG9yIG1vbml0b3IpIHsKCQkvLyBkbyBub3RoaW5nCgl9CgkKCXByb3RlY3RlZCBhYnN0cmFjdCB2b2lkIHNhdmVTdGF0ZShJTWVtZW50byBtZW1lbnRvKTsKCglwcm90ZWN0ZWQgdm9pZCBsb2FkKElNZW1lbnRvIG1lbWVudG8pIHsKCQltYXAgPSBuZXcgSGFzaE1hcCgpOwoJCQoJCUl0ZXJhdG9yIGl0ZXJhdG9yID0gbWVtZW50by5nZXROYW1lcygpLml0ZXJhdG9yKCk7CgkJd2hpbGUgKGl0ZXJhdG9yLmhhc05leHQoKSkgewoJCQlTdHJpbmcga2V5ID0gKFN0cmluZykgaXRlcmF0b3IubmV4dCgpOwoJCQltYXAucHV0KGtleSwgbWVtZW50by5nZXRTdHJpbmcoa2V5KSk7CgkJfQoJCUlNZW1lbnRvW10gY2hpbGRyZW4gPSBtZW1lbnRvLmdldENoaWxkcmVuKCJsaXN0Iik7CgkJaWYgKGNoaWxkcmVuICE9IG51bGwpIHsKCQkJaW50IHNpemUgPSBjaGlsZHJlbi5sZW5ndGg7CgkJCWZvciAoaW50IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKSB7CgkJCQlsb2FkTGlzdChjaGlsZHJlbltpXSk7CgkJCX0KCQl9CgkJSU1lbWVudG9bXSBtYXBzID0gbWVtZW50by5nZXRDaGlsZHJlbigibWFwIik7CgkJaWYgKG1hcHMgIT0gbnVsbCkgewoJCQlmb3IgKGludCBpID0gMDsgaSA8bWFwcy5sZW5ndGggOyBpKyspIHsKCQkJCWxvYWRNYXAobWFwc1tpXSk7CgkJCX0KCQl9CgkJCgkJbG9hZFN0YXRlKG1lbWVudG8pOwoJfQoKCQoJcHJvdGVjdGVkIHZvaWQgbG9hZE1hcChJTWVtZW50byBtZW1lbnRvKSB7CgkJU3RyaW5nIGtleSA9IG1lbWVudG8uZ2V0U3RyaW5nKCJrZXkiKTsKCQlNYXAgdk1hcCA9IG5ldyBIYXNoTWFwKCk7CgkJTGlzdCBrZXlzID0gbWVtZW50by5nZXROYW1lcygpOwoJCUl0ZXJhdG9yIGl0ZXJhdG9yID0ga2V5cy5pdGVyYXRvcigpOwoJCXdoaWxlKGl0ZXJhdG9yLmhhc05leHQoKSkgewoJCQlTdHJpbmcgcyA9IChTdHJpbmcpaXRlcmF0b3IubmV4dCgpOwoJCQlTdHJpbmcgdiA9IG1lbWVudG8uZ2V0U3RyaW5nKHMpOwoJCQl2TWFwLnB1dChzLHYpOwoJCX0KCQltYXAucHV0KGtleSwgdk1hcCk7Cgl9CgkKCQoJcHJvdGVjdGVkIHZvaWQgbG9hZExpc3QoSU1lbWVudG8gbWVtZW50bykgewoJCVN0cmluZyBrZXkgPSBtZW1lbnRvLmdldFN0cmluZygia2V5Iik7CgkJTGlzdCBsaXN0ID0gbmV3IEFycmF5TGlzdCgpOwoJCWludCBpID0gMDsKCQlTdHJpbmcga2V5MiA9IG1lbWVudG8uZ2V0U3RyaW5nKCJ2YWx1ZSIgKyAoaSsrKSk7CgkJd2hpbGUgKGtleTIgIT0gbnVsbCkgewoJCQlsaXN0LmFkZChrZXkyKTsKCQkJa2V5MiA9IG1lbWVudG8uZ2V0U3RyaW5nKCJ2YWx1ZSIgKyAoaSsrKSk7CgkJfQoJCW1hcC5wdXQoa2V5LCBsaXN0KTsKCX0KCQoJcHJvdGVjdGVkIGFic3RyYWN0IHZvaWQgbG9hZFN0YXRlKElNZW1lbnRvIG1lbWVudG8pOwoJCglwcm90ZWN0ZWQgdm9pZCByZXNvbHZlKCkgewoJCS8vIGRvIG5vdGhpbmcKCX0KCQoJcHVibGljIHZvaWQgZGVsZXRlKCkgdGhyb3dzIENvcmVFeGNlcHRpb24gewoJCWlmIChpc1dvcmtpbmdDb3B5KCkpCgkJCXRocm93IG5ldyBDb3JlRXhjZXB0aW9uKG5ldyBTdGF0dXMoSVN0YXR1cy5FUlJPUiwgU2VydmVyUGx1Z2luLlBMVUdJTl9JRCwgMCwgIkNhbm5vdCBkZWxldGUgYSB3b3JraW5nIGNvcHkiLCBudWxsKSk7CgkJCgkJaWYgKGZpbGUgIT0gbnVsbCkKCQkJZmlsZS5kZWxldGUodHJ1ZSwgdHJ1ZSwgbmV3IE51bGxQcm9ncmVzc01vbml0b3IoKSk7CgkJZWxzZQoJCQlkZWxldGVGcm9tTWV0YWRhdGEoKTsKCX0KCglwcm90ZWN0ZWQgdm9pZCBkZWxldGVGcm9tTWV0YWRhdGEoKSB7CgkJLy8gZG8gbm90aGluZwoJfQoKCXB1YmxpYyBib29sZWFuIGVxdWFscyhPYmplY3Qgb2JqKSB7CgkJaWYgKCEob2JqIGluc3RhbmNlb2YgQmFzZSkpCgkJCXJldHVybiBmYWxzZTsKCQkKCQlCYXNlIGJhc2UgPSAoQmFzZSkgb2JqOwoJCWlmIChnZXRJZCgpID09IG51bGwpCgkJCXJldHVybiBmYWxzZTsKCQlyZXR1cm4gZ2V0SWQoKS5lcXVhbHMoYmFzZS5nZXRJZCgpKTsKCX0KCgkvKioKCSAqIAoJICovCglwcm90ZWN0ZWQgdm9pZCBsb2FkRnJvbUZpbGUoSVByb2dyZXNzTW9uaXRvciBtb25pdG9yKSB0aHJvd3MgQ29yZUV4Y2VwdGlvbiB7CgkJSW5wdXRTdHJlYW0gaW4gPSBudWxsOwoJCXRyeSB7CgkJCWluID0gZmlsZS5nZXRDb250ZW50cygpOwoJCQlJTWVtZW50byBtZW1lbnRvID0gWE1MTWVtZW50by5sb2FkTWVtZW50byhpbik7CgkJCWxvYWQobWVtZW50byk7CgkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiQ291bGQgbm90IGxvYWQgZnJvbSBmaWxlIiArIGUuZ2V0TWVzc2FnZSgpLCBlKTsKCQkJdGhyb3cgbmV3IENvcmVFeGNlcHRpb24obmV3IFN0YXR1cyhJU3RhdHVzLkVSUk9SLCBTZXJ2ZXJQbHVnaW4uUExVR0lOX0lELCAwLCBOTFMuYmluZChNZXNzYWdlcy5lcnJvckxvYWRpbmcsIGdldEZpbGUoKS50b1N0cmluZygpKSwgZSkpOwoJCX0gZmluYWxseSB7CgkJCXRyeSB7CgkJCQlpbi5jbG9zZSgpOwoJCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkJLy8gaWdub3JlCgkJCX0KCQl9Cgl9CgkKCXByb3RlY3RlZCB2b2lkIGxvYWRGcm9tTWVtZW50byhJTWVtZW50byBtZW1lbnRvLCBJUHJvZ3Jlc3NNb25pdG9yIG1vbml0b3IpIHsKCQlsb2FkKG1lbWVudG8pOwoJfQoJCgkvKioKCSAqIAoJICovCglwcm90ZWN0ZWQgdm9pZCBsb2FkRnJvbVBhdGgoSVBhdGggcGF0aCwgSVByb2dyZXNzTW9uaXRvciBtb25pdG9yKSB0aHJvd3MgQ29yZUV4Y2VwdGlvbiB7CgkJRmlsZUlucHV0U3RyZWFtIGZpbiA9IG51bGw7CgkJdHJ5IHsKCQkJZmluID0gbmV3IEZpbGVJbnB1dFN0cmVhbShwYXRoLnRvRmlsZSgpKTsKCQkJSU1lbWVudG8gbWVtZW50byA9IFhNTE1lbWVudG8ubG9hZE1lbWVudG8oZmluKTsKCQkJbG9hZChtZW1lbnRvKTsKCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQlUcmFjZS50cmFjZShUcmFjZS5TRVZFUkUsICJDb3VsZCBub3QgbG9hZCBmcm9tIHBhdGg6ICIgKyBlLmdldE1lc3NhZ2UoKSwgZSk7CgkJCXRocm93IG5ldyBDb3JlRXhjZXB0aW9uKG5ldyBTdGF0dXMoSVN0YXR1cy5FUlJPUiwgU2VydmVyUGx1Z2luLlBMVUdJTl9JRCwgMCwgTkxTLmJpbmQoTWVzc2FnZXMuZXJyb3JMb2FkaW5nLCBwYXRoLnRvU3RyaW5nKCkpLCBlKSk7CgkJfSBmaW5hbGx5IHsKCQkJdHJ5IHsKCQkJCWZpbi5jbG9zZSgpOwoJCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkJLy8gaWdub3JlCgkJCX0KCQl9Cgl9CgkKCXB1YmxpYyBJU3RhdHVzIHZhbGlkYXRlRWRpdChPYmplY3QgY29udGV4dCkgewoJCWlmIChmaWxlID09IG51bGwpCgkJCXJldHVybiBudWxsOwoJCgkJcmV0dXJuIGZpbGUuZ2V0V29ya3NwYWNlKCkudmFsaWRhdGVFZGl0KG5ldyBJRmlsZVtdIHsgZmlsZSB9LCBjb250ZXh0KTsKCX0KfQ==