LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogQ29weXJpZ2h0IChjKSAyMDA3LCAyMDE1IFdpbmQgUml2ZXIgU3lzdGVtcywgSW5jLiBhbmQgb3RoZXJzLgogKiBBbGwgcmlnaHRzIHJlc2VydmVkLiBUaGlzIHByb2dyYW0gYW5kIHRoZSBhY2NvbXBhbnlpbmcgbWF0ZXJpYWxzCiAqIGFyZSBtYWRlIGF2YWlsYWJsZSB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEVjbGlwc2UgUHVibGljIExpY2Vuc2UgdjEuMAogKiB3aGljaCBhY2NvbXBhbmllcyB0aGlzIGRpc3RyaWJ1dGlvbiwgYW5kIGlzIGF2YWlsYWJsZSBhdAogKiBodHRwOi8vd3d3LmVjbGlwc2Uub3JnL2xlZ2FsL2VwbC12MTAuaHRtbAogKgogKiBDb250cmlidXRvcnM6CiAqIE1hcnRpbiBPYmVyaHViZXIgKFdpbmQgUml2ZXIpIC0gaW5pdGlhbCBBUEkgYW5kIGltcGxlbWVudGF0aW9uCiAqIEpvaG4gQXJ0aG9ybmUgKElCTSkgLSBbMTcyMzQ2XSBkaXNhYmxlIHRlc3RzIHdpdGggcHJvYmxlbWF0aWMgUGxhdGZvcm0gZW5jb2RpbmcKICogTWFydGluIE9iZXJodWJlciAoV2luZCBSaXZlcikgLSBbMTgzMTM3XSBsaWJsb2NhbGZpbGUgZm9yIHNvbGFyaXMtc3BhcmMKICogTWFydGluIE9iZXJodWJlciAoV2luZCBSaXZlcikgLSBbMTg0NDMzXSBsaWJsb2NhbGZpbGUgZm9yIExpbnV4IHg4Nl82NAogKiBNYXJ0aW4gT2Jlcmh1YmVyIChXaW5kIFJpdmVyKSAtIFsyMzI0MjZdIHB1c2ggdXAgY3JlYXRlU3ltTGluaygpIHRvIENvcmVUZXN0CiAqIE1hcnRpbiBPYmVyaHViZXIgKFdpbmQgUml2ZXIpIC0gWzMzMTcxNl0gU3ltbGluayB0ZXN0IGZhaWx1cmVzIG9uIFdpbmRvd3MgNwogKiBTZXJnZXkgUHJpZ29naW4gKEdvb2dsZSkgLSBbNDQwMjgzXSBNb2RpZnkgc3ltbGluayB0ZXN0cyB0byBydW4gb24gV2luZG93cyB3aXRoIG9yIHdpdGhvdXQgYWRtaW5pc3RyYXRvciBwcml2aWxlZ2VzCiAqIAkJCQkJCQkgIFs0NDU4MDVdIE1ha2Ugc3VyZSBzeW1saW5rIHRlc3RzIGFyZSBncmVlbiB3aGVuIHJ1biBvbiBXaW5kb3dzIHdpdGggYWRtaW5pc3RyYXRvciBwcml2aWxlZ2VzCiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgIFs0NTg5ODldIEFkZCBhIHRlc3QgY2FzZSBmb3Igc2V0dGluZyBBVFRSSUJVVEVfSElEREVOIG9uIGEgc3ltbGluayBvbiBXaW5kb3dzCiAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLwpwYWNrYWdlIG9yZy5lY2xpcHNlLmNvcmUudGVzdHMuZmlsZXN5c3RlbTsKCmltcG9ydCBqYXZhLmlvLk91dHB1dFN0cmVhbTsKaW1wb3J0IG9yZy5lY2xpcHNlLmNvcmUuZmlsZXN5c3RlbS4qOwppbXBvcnQgb3JnLmVjbGlwc2UuY29yZS5yZXNvdXJjZXMuSVdvcmtzcGFjZTsKaW1wb3J0IG9yZy5lY2xpcHNlLmNvcmUucmVzb3VyY2VzLlJlc291cmNlc1BsdWdpbjsKaW1wb3J0IG9yZy5lY2xpcHNlLmNvcmUucnVudGltZS5Db3JlRXhjZXB0aW9uOwppbXBvcnQgb3JnLmVjbGlwc2UuY29yZS5ydW50aW1lLlBsYXRmb3JtOwoKLyoqCiAqCiAqLwpwdWJsaWMgY2xhc3MgU3ltbGlua1Rlc3QgZXh0ZW5kcyBGaWxlU3lzdGVtVGVzdCB7CgkvKioKCSAqIFN5bWJvbGljIGxpbmtzIG9uIFdpbmRvd3MgYmVoYXZlIGRpZmZlcmVudGx5IGNvbXBhcmVkIHRvIFVuaXgtYmFzZWQgc3lzdGVtcy4gU3ltYm9saWMgbGlua3MKCSAqIG9uIFdpbmRvd3MgaGF2ZSB0aGVpciBvd24gc2V0IG9mIGF0dHJpYnV0ZXMgaW5kZXBlbmRlbnQgZnJvbSB0aGUgYXR0cmlidXRlcyBvZiB0aGUgbGluaydzCgkgKiB0YXJnZXQuIFRoZSB7QGxpbmsgamF2YS5pby5GaWxlI2V4aXN0cygpIEZpbGUuZXhpc3RzKCl9IG1ldGhvZCBvbiBXaW5kb3dzIGNoZWNrcyBmb3IKCSAqIGV4aXN0ZW5jZSBvZiB0aGUgc3ltYm9saWMgbGluayBpdHNlbGYsIG5vdCBpdHMgdGFyZ2V0LgoJICovCglwcml2YXRlIHN0YXRpYyBmaW5hbCBib29sZWFuIFNZTUxJTktTX0FSRV9GSVJTVF9DTEFTU19GSUxFU19PUl9ESVJFQ1RPUklFUyA9IGlzV2luZG93c1Zpc3RhT3JIaWdoZXIoKTsKCXByaXZhdGUgc3RhdGljIFN0cmluZyBzcGVjaWFsQ2hhck5hbWUgPSAi5Pb83yDE1twg4MDiwiC1srP64SI7IC8vJE5PTi1OTFMtMSQKCglwcm90ZWN0ZWQgSUZpbGVTdG9yZSBhRGlyLCBhRmlsZTsgLy9hY3R1YWwgRGlyLCBGaWxlCglwcm90ZWN0ZWQgSUZpbGVJbmZvIGlEaXIsIGlGaWxlLCBpbERpciwgaWxGaWxlLCBpbGxEaXIsIGlsbEZpbGU7Cglwcm90ZWN0ZWQgSUZpbGVTdG9yZSBsRGlyLCBsRmlsZTsgLy9zeW1saW5rIHRvIERpciwgRmlsZQoJcHJvdGVjdGVkIElGaWxlU3RvcmUgbGxEaXIsIGxsRmlsZTsgLy9saW5rIHRvIGxpbmsgdG8gRGlyLCBGaWxlCgoJcHVibGljIHN0YXRpYyBJRmlsZVN5c3RlbSBnZXRGaWxlU3lzdGVtKCkgewoJCXRyeSB7CgkJCXJldHVybiBFRlMuZ2V0RmlsZVN5c3RlbShFRlMuU0NIRU1FX0ZJTEUpOwoJCX0gY2F0Y2ggKENvcmVFeGNlcHRpb24gZSkgewoJCQlmYWlsKCJnZXRGaWxlU3lzdGVtIiwgZSk7CgkJfQoJCXJldHVybiBudWxsOwoJfQoKCXB1YmxpYyBzdGF0aWMgSVdvcmtzcGFjZSBnZXRXb3Jrc3BhY2UoKSB7CgkJcmV0dXJuIFJlc291cmNlc1BsdWdpbi5nZXRXb3Jrc3BhY2UoKTsKCX0KCglwcm90ZWN0ZWQgdm9pZCBmZXRjaEZpbGVJbmZvcygpIHsKCQlpRGlyID0gYURpci5mZXRjaEluZm8oKTsKCQlpRmlsZSA9IGFGaWxlLmZldGNoSW5mbygpOwoJCWlsRGlyID0gbERpci5mZXRjaEluZm8oKTsKCQlpbEZpbGUgPSBsRmlsZS5mZXRjaEluZm8oKTsKCQlpbGxEaXIgPSBsbERpci5mZXRjaEluZm8oKTsKCQlpbGxGaWxlID0gbGxGaWxlLmZldGNoSW5mbygpOwoJfQoKCXB1YmxpYyBib29sZWFuIGhhdmVTeW1saW5rcygpIHsKCQlyZXR1cm4gaXNBdHRyaWJ1dGVTdXBwb3J0ZWQoRUZTLkFUVFJJQlVURV9TWU1MSU5LKTsKCX0KCglwcm90ZWN0ZWQgdm9pZCBtYWtlTGlua1N0cnVjdHVyZSgpIHsKCQlhRGlyID0gYmFzZVN0b3JlLmdldENoaWxkKCJhRGlyIik7CgkJYUZpbGUgPSBiYXNlU3RvcmUuZ2V0Q2hpbGQoImFGaWxlIik7CgkJbERpciA9IGJhc2VTdG9yZS5nZXRDaGlsZCgibERpciIpOwoJCWxGaWxlID0gYmFzZVN0b3JlLmdldENoaWxkKCJsRmlsZSIpOwoJCWxsRGlyID0gYmFzZVN0b3JlLmdldENoaWxkKCJsbERpciIpOwoJCWxsRmlsZSA9IGJhc2VTdG9yZS5nZXRDaGlsZCgibGxGaWxlIik7CgkJZW5zdXJlRXhpc3RzKGFEaXIsIHRydWUpOwoJCWVuc3VyZUV4aXN0cyhhRmlsZSwgZmFsc2UpOwoJCW1rTGluayhiYXNlU3RvcmUsICJsRGlyIiwgImFEaXIiLCB0cnVlKTsKCQlta0xpbmsoYmFzZVN0b3JlLCAibGxEaXIiLCAibERpciIsIHRydWUpOwoJCW1rTGluayhiYXNlU3RvcmUsICJsRmlsZSIsICJhRmlsZSIsIGZhbHNlKTsKCQlta0xpbmsoYmFzZVN0b3JlLCAibGxGaWxlIiwgImxGaWxlIiwgZmFsc2UpOwoJCWZldGNoRmlsZUluZm9zKCk7Cgl9CgoJcHJvdGVjdGVkIHZvaWQgbWtMaW5rKElGaWxlU3RvcmUgZGlyLCBTdHJpbmcgc3JjLCBTdHJpbmcgdGd0LCBib29sZWFuIGlzRGlyKSB7CgkJdHJ5IHsKCQkJY3JlYXRlU3ltTGluayhkaXIudG9Mb2NhbEZpbGUoRUZTLk5PTkUsIGdldE1vbml0b3IoKSksIHNyYywgdGd0LCBpc0Rpcik7CgkJfSBjYXRjaCAoQ29yZUV4Y2VwdGlvbiBlKSB7CgkJCWZhaWwoIm1rTGluayIsIGUpOwoJCX0KCX0KCglAT3ZlcnJpZGUKCXByb3RlY3RlZCB2b2lkIHNldFVwKCkgdGhyb3dzIEV4Y2VwdGlvbiB7CgkJYmFzZVN0b3JlID0gZ2V0RmlsZVN5c3RlbSgpLmdldFN0b3JlKGdldFdvcmtzcGFjZSgpLmdldFJvb3QoKS5nZXRMb2NhdGlvbigpLmFwcGVuZCgidGVtcCIpKTsKCQliYXNlU3RvcmUubWtkaXIoRUZTLk5PTkUsIG51bGwpOwoJfQoKCUBPdmVycmlkZQoJcHJvdGVjdGVkIHZvaWQgdGVhckRvd24oKSB0aHJvd3MgRXhjZXB0aW9uIHsKCQliYXNlU3RvcmUuZGVsZXRlKEVGUy5OT05FLCBudWxsKTsKCX0KCglwdWJsaWMgdm9pZCB0ZXN0QnJva2VuU3ltbGlua0F0dHJpYnV0ZXMoKSB7CgkJLy8gT25seSBhY3RpdmF0ZSB0aGlzIHRlc3QgaWYgdGVzdGluZyBvZiBzeW1ib2xpYyBsaW5rcyBpcyBwb3NzaWJsZS4KCQlpZiAoIWNhbkNyZWF0ZVN5bUxpbmtzKCkpIHsKCQkJcmV0dXJuOwoJCX0KCQlsb25nIHRlc3RTdGFydFRpbWUgPSBTeXN0ZW0uY3VycmVudFRpbWVNaWxsaXMoKTsKCQltYWtlTGlua1N0cnVjdHVyZSgpOwoJCS8vYnJlYWsgbGlua3MgYnkgcmVtb3ZpbmcgYWN0dWFsIGRpciBhbmQgZmlsZQoJCWVuc3VyZURvZXNOb3RFeGlzdChhRGlyKTsKCQllbnN1cmVEb2VzTm90RXhpc3QoYUZpbGUpOwoJCWZldGNoRmlsZUluZm9zKCk7CgoJCWFzc2VydEVxdWFscyhTWU1MSU5LU19BUkVfRklSU1RfQ0xBU1NfRklMRVNfT1JfRElSRUNUT1JJRVMsIGlsRmlsZS5leGlzdHMoKSk7CgkJYXNzZXJ0RmFsc2UoaWxGaWxlLmlzRGlyZWN0b3J5KCkpOwoJCWFzc2VydEVxdWFscyhTWU1MSU5LU19BUkVfRklSU1RfQ0xBU1NfRklMRVNfT1JfRElSRUNUT1JJRVMsIGlsbEZpbGUuZXhpc3RzKCkpOwoJCWFzc2VydEZhbHNlKGlsbEZpbGUuaXNEaXJlY3RvcnkoKSk7CgkJYXNzZXJ0RXF1YWxzKFNZTUxJTktTX0FSRV9GSVJTVF9DTEFTU19GSUxFU19PUl9ESVJFQ1RPUklFUywgaWxEaXIuZXhpc3RzKCkpOwoJCWFzc2VydEVxdWFscyhTWU1MSU5LU19BUkVfRklSU1RfQ0xBU1NfRklMRVNfT1JfRElSRUNUT1JJRVMsIGlsRGlyLmlzRGlyZWN0b3J5KCkpOwoJCWFzc2VydEVxdWFscyhTWU1MSU5LU19BUkVfRklSU1RfQ0xBU1NfRklMRVNfT1JfRElSRUNUT1JJRVMsIGlsbERpci5leGlzdHMoKSk7CgkJYXNzZXJ0RXF1YWxzKFNZTUxJTktTX0FSRV9GSVJTVF9DTEFTU19GSUxFU19PUl9ESVJFQ1RPUklFUywgaWxsRGlyLmlzRGlyZWN0b3J5KCkpOwoJCWlmIChTWU1MSU5LU19BUkVfRklSU1RfQ0xBU1NfRklMRVNfT1JfRElSRUNUT1JJRVMpIHsKCQkJLy8gU3ltbGlua3Mgb24gV2luZG93cyBoYXZlIHRoZWlyIG93biBtb2RpZmljYXRpb24gdGltZS4KCQkJYXNzZXJ0VHJ1ZShpbEZpbGUuZ2V0TGFzdE1vZGlmaWVkKCkgPj0gdGVzdFN0YXJ0VGltZSk7CgkJCWFzc2VydFRydWUoaWxEaXIuZ2V0TGFzdE1vZGlmaWVkKCkgPj0gdGVzdFN0YXJ0VGltZSk7CgkJCWFzc2VydFRydWUoaWxsRmlsZS5nZXRMYXN0TW9kaWZpZWQoKSA+PSB0ZXN0U3RhcnRUaW1lKTsKCQkJYXNzZXJ0VHJ1ZShpbGxEaXIuZ2V0TGFzdE1vZGlmaWVkKCkgPj0gdGVzdFN0YXJ0VGltZSk7CgkJfSBlbHNlIHsKCQkJYXNzZXJ0RXF1YWxzKDAsIGlsRmlsZS5nZXRMYXN0TW9kaWZpZWQoKSk7CgkJCWFzc2VydEVxdWFscygwLCBpbERpci5nZXRMYXN0TW9kaWZpZWQoKSk7CgkJCWFzc2VydEVxdWFscygwLCBpbGxGaWxlLmdldExhc3RNb2RpZmllZCgpKTsKCQkJYXNzZXJ0RXF1YWxzKDAsIGlsbERpci5nZXRMYXN0TW9kaWZpZWQoKSk7CgkJfQoJCWFzc2VydEVxdWFscygwLCBpbEZpbGUuZ2V0TGVuZ3RoKCkpOwoJCWFzc2VydEVxdWFscygwLCBpbERpci5nZXRMZW5ndGgoKSk7CgkJYXNzZXJ0RXF1YWxzKDAsIGlsbEZpbGUuZ2V0TGVuZ3RoKCkpOwoJCWFzc2VydEVxdWFscygwLCBpbGxEaXIuZ2V0TGVuZ3RoKCkpOwoKCQlhc3NlcnRUcnVlKGlsRmlsZS5nZXRBdHRyaWJ1dGUoRUZTLkFUVFJJQlVURV9TWU1MSU5LKSk7CgkJYXNzZXJ0RXF1YWxzKGlsRmlsZS5nZXRTdHJpbmdBdHRyaWJ1dGUoRUZTLkFUVFJJQlVURV9MSU5LX1RBUkdFVCksICJhRmlsZSIpOwoJCWFzc2VydFRydWUoaWxEaXIuZ2V0QXR0cmlidXRlKEVGUy5BVFRSSUJVVEVfU1lNTElOSykpOwoJCWFzc2VydEVxdWFscyhpbERpci5nZXRTdHJpbmdBdHRyaWJ1dGUoRUZTLkFUVFJJQlVURV9MSU5LX1RBUkdFVCksICJhRGlyIik7CgkJYXNzZXJ0VHJ1ZShpbGxGaWxlLmdldEF0dHJpYnV0ZShFRlMuQVRUUklCVVRFX1NZTUxJTkspKTsKCQlhc3NlcnRFcXVhbHMoaWxsRmlsZS5nZXRTdHJpbmdBdHRyaWJ1dGUoRUZTLkFUVFJJQlVURV9MSU5LX1RBUkdFVCksICJsRmlsZSIpOwoJCWFzc2VydFRydWUoaWxsRGlyLmdldEF0dHJpYnV0ZShFRlMuQVRUUklCVVRFX1NZTUxJTkspKTsKCQlhc3NlcnRFcXVhbHMoaWxsRGlyLmdldFN0cmluZ0F0dHJpYnV0ZShFRlMuQVRUUklCVVRFX0xJTktfVEFSR0VUKSwgImxEaXIiKTsKCX0KCgkvLyBNb3ZpbmcgYSBicm9rZW4gc3ltbGluayBpcyBwb3NzaWJsZS4KCXB1YmxpYyB2b2lkIHRlc3RCcm9rZW5TeW1saW5rTW92ZSgpIHRocm93cyBFeGNlcHRpb24gewoJCS8vIE9ubHkgYWN0aXZhdGUgdGhpcyB0ZXN0IGlmIHRlc3Rpbmcgb2Ygc3ltYm9saWMgbGlua3MgaXMgcG9zc2libGUuCgkJaWYgKCFjYW5DcmVhdGVTeW1MaW5rcygpKSB7CgkJCXJldHVybjsKCQl9CgkJbWFrZUxpbmtTdHJ1Y3R1cmUoKTsKCQllbnN1cmVEb2VzTm90RXhpc3QoYUZpbGUpOwoJCWVuc3VyZURvZXNOb3RFeGlzdChhRGlyKTsKCQlJRmlsZUluZm9bXSBpbmZvcyA9IGJhc2VTdG9yZS5jaGlsZEluZm9zKEVGUy5OT05FLCBnZXRNb25pdG9yKCkpOwoJCWFzc2VydEVxdWFscyhpbmZvcy5sZW5ndGgsIDQpOwoKCQlJRmlsZVN0b3JlIF9sbEZpbGUgPSBiYXNlU3RvcmUuZ2V0Q2hpbGQoIl9sbEZpbGUiKTsKCQlJRmlsZVN0b3JlIF9sbERpciA9IGJhc2VTdG9yZS5nZXRDaGlsZCgiX2xsRGlyIik7CgkJbGxGaWxlLm1vdmUoX2xsRmlsZSwgRUZTLk5PTkUsIGdldE1vbml0b3IoKSk7CgkJbGxEaXIubW92ZShfbGxEaXIsIEVGUy5OT05FLCBnZXRNb25pdG9yKCkpOwoJCWluZm9zID0gYmFzZVN0b3JlLmNoaWxkSW5mb3MoRUZTLk5PTkUsIGdldE1vbml0b3IoKSk7CgkJYXNzZXJ0RXF1YWxzKGluZm9zLmxlbmd0aCwgNCk7CgkJYXNzZXJ0RmFsc2UoIjEuMCIsIGNvbnRhaW5zU3ltbGluayhpbmZvcywgbGxGaWxlLmdldE5hbWUoKSkpOwoJCWFzc2VydEZhbHNlKCIxLjEiLCBjb250YWluc1N5bWxpbmsoaW5mb3MsIGxsRGlyLmdldE5hbWUoKSkpOwoJCWFzc2VydFRydWUoIjEuMiIsIGNvbnRhaW5zU3ltbGluayhpbmZvcywgX2xsRmlsZS5nZXROYW1lKCkpKTsKCQlhc3NlcnRUcnVlKCIxLjMiLCBjb250YWluc1N5bWxpbmsoaW5mb3MsIF9sbEZpbGUuZ2V0TmFtZSgpKSk7CgoJCUlGaWxlU3RvcmUgX2xGaWxlID0gYmFzZVN0b3JlLmdldENoaWxkKCJfbEZpbGUiKTsKCQlJRmlsZVN0b3JlIF9sRGlyID0gYmFzZVN0b3JlLmdldENoaWxkKCJfbERpciIpOwoJCWxGaWxlLm1vdmUoX2xGaWxlLCBFRlMuTk9ORSwgZ2V0TW9uaXRvcigpKTsKCQlsRGlyLm1vdmUoX2xEaXIsIEVGUy5OT05FLCBnZXRNb25pdG9yKCkpOwoJCWluZm9zID0gYmFzZVN0b3JlLmNoaWxkSW5mb3MoRUZTLk5PTkUsIGdldE1vbml0b3IoKSk7CgkJYXNzZXJ0RXF1YWxzKGluZm9zLmxlbmd0aCwgNCk7CgkJYXNzZXJ0RmFsc2UoIjEuNCIsIGNvbnRhaW5zU3ltbGluayhpbmZvcywgbEZpbGUuZ2V0TmFtZSgpKSk7CgkJYXNzZXJ0RmFsc2UoIjEuNSIsIGNvbnRhaW5zU3ltbGluayhpbmZvcywgbERpci5nZXROYW1lKCkpKTsKCQlhc3NlcnRUcnVlKCIxLjYiLCBjb250YWluc1N5bWxpbmsoaW5mb3MsIF9sRmlsZS5nZXROYW1lKCkpKTsKCQlhc3NlcnRUcnVlKCIxLjciLCBjb250YWluc1N5bWxpbmsoaW5mb3MsIF9sRmlsZS5nZXROYW1lKCkpKTsKCX0KCglwcml2YXRlIGJvb2xlYW4gY29udGFpbnNTeW1saW5rKElGaWxlSW5mb1tdIGluZm9zLCBTdHJpbmcgbGluaykgewoJCWZvciAoSUZpbGVJbmZvIGluZm8gOiBpbmZvcykgewoJCQlpZiAobGluay5lcXVhbHMoaW5mby5nZXROYW1lKCkpKSB7CgkJCQlpZiAoaW5mby5nZXRBdHRyaWJ1dGUoRUZTLkFUVFJJQlVURV9TWU1MSU5LKSkgewoJCQkJCXJldHVybiB0cnVlOwoJCQkJfQoJCQl9CgkJfQoJCXJldHVybiBmYWxzZTsKCX0KCgkvLyBSZW1vdmluZyBhIGJyb2tlbiBzeW1saW5rIGlzIHBvc3NpYmxlLgoJcHVibGljIHZvaWQgdGVzdEJyb2tlblN5bWxpbmtSZW1vdmUoKSB0aHJvd3MgRXhjZXB0aW9uIHsKCQkvLyBPbmx5IGFjdGl2YXRlIHRoaXMgdGVzdCBpZiB0ZXN0aW5nIG9mIHN5bWJvbGljIGxpbmtzIGlzIHBvc3NpYmxlLgoJCWlmICghY2FuQ3JlYXRlU3ltTGlua3MoKSkgewoJCQlyZXR1cm47CgkJfQoJCW1ha2VMaW5rU3RydWN0dXJlKCk7CgkJZW5zdXJlRG9lc05vdEV4aXN0KGFGaWxlKTsKCQllbnN1cmVEb2VzTm90RXhpc3QoYURpcik7CgkJSUZpbGVJbmZvW10gaW5mb3MgPSBiYXNlU3RvcmUuY2hpbGRJbmZvcyhFRlMuTk9ORSwgZ2V0TW9uaXRvcigpKTsKCQlhc3NlcnRFcXVhbHMoaW5mb3MubGVuZ3RoLCA0KTsKCQlsbEZpbGUuZGVsZXRlKEVGUy5OT05FLCBnZXRNb25pdG9yKCkpOwoJCWxsRGlyLmRlbGV0ZShFRlMuTk9ORSwgZ2V0TW9uaXRvcigpKTsKCQlpbmZvcyA9IGJhc2VTdG9yZS5jaGlsZEluZm9zKEVGUy5OT05FLCBnZXRNb25pdG9yKCkpOwoJCWFzc2VydEVxdWFscyhpbmZvcy5sZW5ndGgsIDIpOwoJCWxGaWxlLmRlbGV0ZShFRlMuTk9ORSwgZ2V0TW9uaXRvcigpKTsKCQlsRGlyLmRlbGV0ZShFRlMuTk9ORSwgZ2V0TW9uaXRvcigpKTsKCQlpbmZvcyA9IGJhc2VTdG9yZS5jaGlsZEluZm9zKEVGUy5OT05FLCBnZXRNb25pdG9yKCkpOwoJCWFzc2VydEVxdWFscyhpbmZvcy5sZW5ndGgsIDApOwoJfQoKCXB1YmxpYyB2b2lkIHRlc3RSZWN1cnNpdmVTeW1saW5rKCkgdGhyb3dzIEV4Y2VwdGlvbiB7CgkJLy8gT25seSBhY3RpdmF0ZSB0aGlzIHRlc3QgaWYgdGVzdGluZyBvZiBzeW1ib2xpYyBsaW5rcyBpcyBwb3NzaWJsZS4KCQlpZiAoIWNhbkNyZWF0ZVN5bUxpbmtzKCkpIHsKCQkJcmV0dXJuOwoJCX0KCQlta0xpbmsoYmFzZVN0b3JlLCAibDEiLCAibDIiLCBmYWxzZSk7CgkJbWtMaW5rKGJhc2VTdG9yZSwgImwyIiwgImwxIiwgZmFsc2UpOwoJCUlGaWxlU3RvcmUgbDEgPSBiYXNlU3RvcmUuZ2V0Q2hpbGQoImwxIik7CgkJSUZpbGVJbmZvIGkxID0gbDEuZmV0Y2hJbmZvKCk7CgkJYXNzZXJ0RXF1YWxzKFNZTUxJTktTX0FSRV9GSVJTVF9DTEFTU19GSUxFU19PUl9ESVJFQ1RPUklFUywgaTEuZXhpc3RzKCkpOwoJCWFzc2VydEZhbHNlKGkxLmlzRGlyZWN0b3J5KCkpOwoKCQlhc3NlcnRUcnVlKGkxLmdldEF0dHJpYnV0ZShFRlMuQVRUUklCVVRFX1NZTUxJTkspKTsKCQlhc3NlcnRFcXVhbHMoImwyIiwgaTEuZ2V0U3RyaW5nQXR0cmlidXRlKEVGUy5BVFRSSUJVVEVfTElOS19UQVJHRVQpKTsKCgkJSUZpbGVJbmZvW10gaW5mb3MgPSBiYXNlU3RvcmUuY2hpbGRJbmZvcyhFRlMuTk9ORSwgZ2V0TW9uaXRvcigpKTsKCQlhc3NlcnRFcXVhbHMoaW5mb3MubGVuZ3RoLCAyKTsKCQlpMS5zZXRBdHRyaWJ1dGUoRUZTLkFUVFJJQlVURV9SRUFEX09OTFksIHRydWUpOwoJCWJvb2xlYW4gZXhjZXB0aW9uVGhyb3duID0gZmFsc2U7CgkJdHJ5IHsKCQkJbDEucHV0SW5mbyhpMSwgRUZTLlNFVF9BVFRSSUJVVEVTLCBnZXRNb25pdG9yKCkpOwoJCX0gY2F0Y2ggKENvcmVFeGNlcHRpb24gY2UpIHsKCQkJZXhjZXB0aW9uVGhyb3duID0gdHJ1ZTsKCQl9CgkJaTEgPSBsMS5mZXRjaEluZm8oKTsKCQlib29sZWFuIGZpeE1lRml4ZWQgPSBmYWxzZTsKCQlpZiAoZml4TWVGaXhlZCkgewoJCQkvL0ZJWE1FIGJ1ZzogcHV0SW5mbyBuZWl0aGVyIHNldHMgYXR0cmlidXRlcyBub3IgdGhyb3dzIGFuIGV4Y2VwdGlvbiBmb3IgYnJva2VuIHN5bWJvbGljIGxpbmtzCgkJCWFzc2VydFRydWUoZXhjZXB0aW9uVGhyb3duKTsKCQkJYXNzZXJ0VHJ1ZShpMS5nZXRBdHRyaWJ1dGUoRUZTLkFUVFJJQlVURV9SRUFEX09OTFkpKTsKCQl9CgkJYXNzZXJ0RXF1YWxzKFNZTUxJTktTX0FSRV9GSVJTVF9DTEFTU19GSUxFU19PUl9ESVJFQ1RPUklFUywgaTEuZXhpc3RzKCkpOwoKCQlpMS5zZXRMYXN0TW9kaWZpZWQoMTIzNDUpOwoJCWV4Y2VwdGlvblRocm93biA9IGZhbHNlOwoJCXRyeSB7CgkJCWwxLnB1dEluZm8oaTEsIEVGUy5TRVRfTEFTVF9NT0RJRklFRCwgZ2V0TW9uaXRvcigpKTsKCQl9IGNhdGNoIChDb3JlRXhjZXB0aW9uIGNlKSB7CgkJCWV4Y2VwdGlvblRocm93biA9IHRydWU7CgkJfQoJCWkxID0gbDEuZmV0Y2hJbmZvKCk7CgkJLy9GSVhNRSBidWc6IHB1dEluZm8gbmVpdGhlciBzZXRzIGF0dHJpYnV0ZXMgbm9yIHRocm93cyBhbiBleGNlcHRpb24gZm9yIGJyb2tlbiBzeW1ib2xpYyBsaW5rcwoJCS8vYXNzZXJ0VHJ1ZShleGNlcHRpb25UaHJvd24pOwoJCS8vYXNzZXJ0RXF1YWxzKGkxLmdldExhc3RNb2RpZmllZCgpLCAxMjM0NSk7CgkJYXNzZXJ0RXF1YWxzKFNZTUxJTktTX0FSRV9GSVJTVF9DTEFTU19GSUxFU19PUl9ESVJFQ1RPUklFUywgaTEuZXhpc3RzKCkpOwoKCQlsMS5kZWxldGUoRUZTLk5PTkUsIGdldE1vbml0b3IoKSk7CgkJaW5mb3MgPSBiYXNlU3RvcmUuY2hpbGRJbmZvcyhFRlMuTk9ORSwgZ2V0TW9uaXRvcigpKTsKCQlhc3NlcnRFcXVhbHMoaW5mb3MubGVuZ3RoLCAxKTsKCX0KCglwdWJsaWMgdm9pZCB0ZXN0U3ltbGlua0F0dHJpYnV0ZXMoKSB7CgkJLy8gT25seSBhY3RpdmF0ZSB0aGlzIHRlc3QgaWYgdGVzdGluZyBvZiBzeW1ib2xpYyBsaW5rcyBpcyBwb3NzaWJsZS4KCQlpZiAoIWNhbkNyZWF0ZVN5bUxpbmtzKCkpIHsKCQkJcmV0dXJuOwoJCX0KCQltYWtlTGlua1N0cnVjdHVyZSgpOwoJCWFzc2VydEZhbHNlKGlGaWxlLmdldEF0dHJpYnV0ZShFRlMuQVRUUklCVVRFX1NZTUxJTkspKTsKCQlhc3NlcnRGYWxzZShpRGlyLmdldEF0dHJpYnV0ZShFRlMuQVRUUklCVVRFX1NZTUxJTkspKTsKCQkvL3ZhbGlkIGxpbmtzCgkJYXNzZXJ0VHJ1ZShpbEZpbGUuZXhpc3RzKCkpOwoJCWFzc2VydEZhbHNlKGlsRmlsZS5pc0RpcmVjdG9yeSgpKTsKCQlhc3NlcnRUcnVlKGlsbEZpbGUuZXhpc3RzKCkpOwoJCWFzc2VydEZhbHNlKGlsbEZpbGUuaXNEaXJlY3RvcnkoKSk7CgkJYXNzZXJ0VHJ1ZShpbERpci5leGlzdHMoKSk7CgkJYXNzZXJ0VHJ1ZShpbERpci5pc0RpcmVjdG9yeSgpKTsKCQlhc3NlcnRUcnVlKGlsbERpci5leGlzdHMoKSk7CgkJYXNzZXJ0VHJ1ZShpbGxEaXIuaXNEaXJlY3RvcnkoKSk7CgkJaWYgKFNZTUxJTktTX0FSRV9GSVJTVF9DTEFTU19GSUxFU19PUl9ESVJFQ1RPUklFUykgewoJCQkvLyBTeW1saW5rcyBvbiBXaW5kb3dzIGhhdmUgdGhlaXIgb3duIG1vZGlmaWNhdGlvbiB0aW1lIGFuZCB6ZXJvIHNpemUuCgkJCWFzc2VydFRydWUoaWxsRmlsZS5nZXRMYXN0TW9kaWZpZWQoKSA+PSBpRmlsZS5nZXRMYXN0TW9kaWZpZWQoKSk7CgkJCWFzc2VydEVxdWFscygwLCBpbGxGaWxlLmdldExlbmd0aCgpKTsKCQkJYXNzZXJ0VHJ1ZShpbGxEaXIuZ2V0TGFzdE1vZGlmaWVkKCkgPj0gaURpci5nZXRMYXN0TW9kaWZpZWQoKSk7CgkJCWFzc2VydEVxdWFscygwLCBpbGxEaXIuZ2V0TGVuZ3RoKCkpOwoJCX0gZWxzZSB7CgkJCWFzc2VydEVxdWFscyhpRmlsZS5nZXRMYXN0TW9kaWZpZWQoKSwgaWxsRmlsZS5nZXRMYXN0TW9kaWZpZWQoKSk7CgkJCWFzc2VydEVxdWFscyhpRmlsZS5nZXRMZW5ndGgoKSwgaWxsRmlsZS5nZXRMZW5ndGgoKSk7CgkJCWFzc2VydEVxdWFscyhpRGlyLmdldExhc3RNb2RpZmllZCgpLCBpbGxEaXIuZ2V0TGFzdE1vZGlmaWVkKCkpOwoJCQlhc3NlcnRFcXVhbHMoaURpci5nZXRMZW5ndGgoKSwgaWxsRGlyLmdldExlbmd0aCgpKTsKCQl9CgoJCWFzc2VydFRydWUoaWxGaWxlLmdldEF0dHJpYnV0ZShFRlMuQVRUUklCVVRFX1NZTUxJTkspKTsKCQlhc3NlcnRFcXVhbHMoaWxGaWxlLmdldFN0cmluZ0F0dHJpYnV0ZShFRlMuQVRUUklCVVRFX0xJTktfVEFSR0VUKSwgImFGaWxlIik7CgkJYXNzZXJ0VHJ1ZShpbERpci5nZXRBdHRyaWJ1dGUoRUZTLkFUVFJJQlVURV9TWU1MSU5LKSk7CgkJYXNzZXJ0RXF1YWxzKGlsRGlyLmdldFN0cmluZ0F0dHJpYnV0ZShFRlMuQVRUUklCVVRFX0xJTktfVEFSR0VUKSwgImFEaXIiKTsKCQlhc3NlcnRUcnVlKGlsbEZpbGUuZ2V0QXR0cmlidXRlKEVGUy5BVFRSSUJVVEVfU1lNTElOSykpOwoJCWFzc2VydEVxdWFscyhpbGxGaWxlLmdldFN0cmluZ0F0dHJpYnV0ZShFRlMuQVRUUklCVVRFX0xJTktfVEFSR0VUKSwgImxGaWxlIik7CgkJYXNzZXJ0VHJ1ZShpbGxEaXIuZ2V0QXR0cmlidXRlKEVGUy5BVFRSSUJVVEVfU1lNTElOSykpOwoJCWFzc2VydEVxdWFscyhpbGxEaXIuZ2V0U3RyaW5nQXR0cmlidXRlKEVGUy5BVFRSSUJVVEVfTElOS19UQVJHRVQpLCAibERpciIpOwoJfQoKCS8vIFJlYWRpbmcgZnJvbSBhIGRpcmVjdG9yeSBwb2ludGVkIHRvIGJ5IGEgbGluayBpcyBwb3NzaWJsZS4KCXB1YmxpYyB2b2lkIHRlc3RTeW1saW5rRGlyUmVhZCgpIHRocm93cyBFeGNlcHRpb24gewoJCS8vIE9ubHkgYWN0aXZhdGUgdGhpcyB0ZXN0IGlmIHRlc3Rpbmcgb2Ygc3ltYm9saWMgbGlua3MgaXMgcG9zc2libGUuCgkJaWYgKCFjYW5DcmVhdGVTeW1MaW5rcygpKSB7CgkJCXJldHVybjsKCQl9CgkJbWFrZUxpbmtTdHJ1Y3R1cmUoKTsKCQlJRmlsZVN0b3JlIGNoaWxkRGlyID0gYURpci5nZXRDaGlsZCgic3ViRGlyIik7CgkJZW5zdXJlRXhpc3RzKGNoaWxkRGlyLCB0cnVlKTsKCQlJRmlsZUluZm9bXSBpbmZvcyA9IGxsRGlyLmNoaWxkSW5mb3MoRUZTLk5PTkUsIGdldE1vbml0b3IoKSk7CgkJYXNzZXJ0RXF1YWxzKGluZm9zLmxlbmd0aCwgMSk7CgkJYXNzZXJ0VHJ1ZShpbmZvc1swXS5pc0RpcmVjdG9yeSgpKTsKCQlhc3NlcnRGYWxzZShpbmZvc1swXS5nZXRBdHRyaWJ1dGUoRUZTLkFUVFJJQlVURV9TWU1MSU5LKSk7CgkJYXNzZXJ0TnVsbChpbmZvc1swXS5nZXRTdHJpbmdBdHRyaWJ1dGUoRUZTLkFUVFJJQlVURV9MSU5LX1RBUkdFVCkpOwoJCWFzc2VydEVxdWFscyhpbmZvc1swXS5nZXROYW1lKCksICJzdWJEaXIiKTsKCQllbnN1cmVEb2VzTm90RXhpc3QoY2hpbGREaXIpOwoJfQoKCS8vIFdyaXRpbmcgdG8gc3ltbGlua2VkIGRpci4KCXB1YmxpYyB2b2lkIHRlc3RTeW1saW5rRGlyV3JpdGUoKSB0aHJvd3MgRXhjZXB0aW9uIHsKCQkvLyBPbmx5IGFjdGl2YXRlIHRoaXMgdGVzdCBpZiB0ZXN0aW5nIG9mIHN5bWJvbGljIGxpbmtzIGlzIHBvc3NpYmxlLgoJCWlmICghY2FuQ3JlYXRlU3ltTGlua3MoKSkgewoJCQlyZXR1cm47CgkJfQoJCW1ha2VMaW5rU3RydWN0dXJlKCk7CgkJSUZpbGVTdG9yZSBjaGlsZEZpbGUgPSBsbERpci5nZXRDaGlsZCgic3ViRmlsZSIpOwoJCWVuc3VyZUV4aXN0cyhjaGlsZEZpbGUsIGZhbHNlKTsKCQlJRmlsZUluZm9bXSBpbmZvcyA9IGFEaXIuY2hpbGRJbmZvcyhFRlMuTk9ORSwgZ2V0TW9uaXRvcigpKTsKCQlhc3NlcnRFcXVhbHMoaW5mb3MubGVuZ3RoLCAxKTsKCQlhc3NlcnRGYWxzZShpbmZvc1swXS5pc0RpcmVjdG9yeSgpKTsKCQlhc3NlcnRGYWxzZShpbmZvc1swXS5nZXRBdHRyaWJ1dGUoRUZTLkFUVFJJQlVURV9TWU1MSU5LKSk7CgkJYXNzZXJ0TnVsbChpbmZvc1swXS5nZXRTdHJpbmdBdHRyaWJ1dGUoRUZTLkFUVFJJQlVURV9MSU5LX1RBUkdFVCkpOwoJCWFzc2VydEVxdWFscyhpbmZvc1swXS5nZXROYW1lKCksICJzdWJGaWxlIik7CgoJCS8vd3JpdGluZyB0byBicm9rZW4gc3ltbGluawoJCWVuc3VyZURvZXNOb3RFeGlzdChhRGlyKTsKCQljaGlsZEZpbGUgPSBsbERpci5nZXRDaGlsZCgic3ViRmlsZSIpOwoJCU91dHB1dFN0cmVhbSBvdXQgPSBudWxsOwoJCWJvb2xlYW4gZXhjZXB0aW9uVGhyb3duID0gZmFsc2U7CgkJdHJ5IHsKCQkJb3V0ID0gY2hpbGRGaWxlLm9wZW5PdXRwdXRTdHJlYW0oRUZTLk5PTkUsIGdldE1vbml0b3IoKSk7CgkJfSBjYXRjaCAoQ29yZUV4Y2VwdGlvbiBjZSkgewoJCQlleGNlcHRpb25UaHJvd24gPSB0cnVlOwoJCX0KCQlpZiAob3V0ICE9IG51bGwpIHsKCQkJb3V0LmNsb3NlKCk7CgkJfQoJCWFzc2VydE51bGwob3V0KTsKCQlhc3NlcnRUcnVlKGV4Y2VwdGlvblRocm93bik7Cgl9CgoJcHVibGljIHZvaWQgdGVzdFN5bWxpbmtFbmFibGVkKCkgewoJCVN0cmluZyBvcyA9IFBsYXRmb3JtLmdldE9TKCk7CgkJU3RyaW5nIGFyY2ggPSBQbGF0Zm9ybS5nZXRPU0FyY2goKTsKCQlpZiAoUGxhdGZvcm0uT1NfTElOVVguZXF1YWxzKG9zKSB8fCAoUGxhdGZvcm0uT1NfU09MQVJJUy5lcXVhbHMob3MpICYmIFBsYXRmb3JtLkFSQ0hfU1BBUkMuZXF1YWxzKGFyY2gpKSB8fCBQbGF0Zm9ybS5PU19NQUNPU1guZXF1YWxzKG9zKSB8fCBQbGF0Zm9ybS5PU19BSVguZXF1YWxzKG9zKSB8fCBpc1dpbmRvd3NWaXN0YU9ySGlnaGVyKCkpIHsKCQkJYXNzZXJ0VHJ1ZShoYXZlU3ltbGlua3MoKSk7CgkJfSBlbHNlIHsKCQkJYXNzZXJ0RmFsc2UoaGF2ZVN5bWxpbmtzKCkpOwoJCX0KCX0KCgkvKioKCSAqIFRPRE8gRml4IHRoaXMgdGVzdC4gIFNlZSBodHRwczovL2J1Z3MuZWNsaXBzZS5vcmcvYnVncy9zaG93X2J1Zy5jZ2k/aWQ9MTcyMzQ2CgkgKi8KCXB1YmxpYyB2b2lkIF90ZXN0U3ltbGlua0V4dGVuZGVkQ2hhcnMoKSB0aHJvd3MgRXhjZXB0aW9uIHsKCQkvLyBPbmx5IGFjdGl2YXRlIHRoaXMgdGVzdCBpZiB0ZXN0aW5nIG9mIHN5bWJvbGljIGxpbmtzIGlzIHBvc3NpYmxlLgoJCWlmICghY2FuQ3JlYXRlU3ltTGlua3MoKSkgewoJCQlyZXR1cm47CgkJfQoJCUlGaWxlU3RvcmUgY2hpbGREaXIgPSBiYXNlU3RvcmUuZ2V0Q2hpbGQoc3BlY2lhbENoYXJOYW1lKTsKCQllbnN1cmVFeGlzdHMoY2hpbGREaXIsIHRydWUpOwoJCUlGaWxlU3RvcmUgY2hpbGRGaWxlID0gYmFzZVN0b3JlLmdldENoaWxkKCJmZiIgKyBzcGVjaWFsQ2hhck5hbWUpOwoJCWVuc3VyZUV4aXN0cyhjaGlsZEZpbGUsIGZhbHNlKTsKCQlta0xpbmsoYmFzZVN0b3JlLCAibCIgKyBzcGVjaWFsQ2hhck5hbWUsIHNwZWNpYWxDaGFyTmFtZSwgdHJ1ZSk7CgkJbWtMaW5rKGJhc2VTdG9yZSwgImxmIiArIHNwZWNpYWxDaGFyTmFtZSwgImZmIiArIHNwZWNpYWxDaGFyTmFtZSwgZmFsc2UpOwoJCUlGaWxlSW5mb1tdIGluZm9zID0gYmFzZVN0b3JlLmNoaWxkSW5mb3MoRUZTLk5PTkUsIGdldE1vbml0b3IoKSk7CgkJYXNzZXJ0RXF1YWxzKCIwLjEiLCBpbmZvcy5sZW5ndGgsIDQpOwoJCWZvciAoSUZpbGVJbmZvIGluZm8gOiBpbmZvcykgewoJCQlTdHJpbmcgaW5mb05hbWUgPSBpbmZvLmdldE5hbWUoKTsKCQkJYXNzZXJ0VHJ1ZSgiMS4iICsgaW5mb05hbWUsIGluZm9OYW1lLmVuZHNXaXRoKHNwZWNpYWxDaGFyTmFtZSkpOwoJCQlhc3NlcnRUcnVlKCIyLiIgKyBpbmZvTmFtZSwgaW5mby5leGlzdHMoKSk7CgkJCWlmIChpbmZvLmdldE5hbWUoKS5jaGFyQXQoMSkgPT0gJ2YnKSB7CgkJCQlhc3NlcnRGYWxzZSgiMy4iICsgaW5mb05hbWUsIGluZm8uaXNEaXJlY3RvcnkoKSk7CgkJCX0gZWxzZSB7CgkJCQlhc3NlcnRUcnVlKCI0LiIgKyBpbmZvTmFtZSwgaW5mby5pc0RpcmVjdG9yeSgpKTsKCQkJfQoJCQlpZiAoaW5mby5nZXROYW1lKCkuY2hhckF0KDApID09ICdsJykgewoJCQkJYXNzZXJ0VHJ1ZSgiNS4iICsgaW5mb05hbWUsIGluZm8uZ2V0QXR0cmlidXRlKEVGUy5BVFRSSUJVVEVfU1lNTElOSykpOwoJCQkJYXNzZXJ0VHJ1ZSgiNi4iICsgaW5mb05hbWUsIGluZm8uZ2V0U3RyaW5nQXR0cmlidXRlKEVGUy5BVFRSSUJVVEVfTElOS19UQVJHRVQpLmVuZHNXaXRoKHNwZWNpYWxDaGFyTmFtZSkpOwoJCQl9CgkJfQoJfQoKCXB1YmxpYyB2b2lkIHRlc3RTeW1saW5rUHV0TGFzdE1vZGlmaWVkKCkgdGhyb3dzIEV4Y2VwdGlvbiB7CgkJLy8gT25seSBhY3RpdmF0ZSB0aGlzIHRlc3QgaWYgdGVzdGluZyBvZiBzeW1ib2xpYyBsaW5rcyBpcyBwb3NzaWJsZS4KCQlpZiAoIWNhbkNyZWF0ZVN5bUxpbmtzKCkpIHsKCQkJcmV0dXJuOwoJCX0KCQlpZiAoUGxhdGZvcm0uT1NfTUFDT1NYLmVxdWFscyhQbGF0Zm9ybS5nZXRPUygpKSkgewoJCQkvLyBmbGFnIEVGUy5TRVRfTEFTVF9NT0RJRklFRCBpcyBzZXQgYnkgamF2YS5pbyBhbmQgaXQgZmFpbHMgb24gTWFjIE9TCgkJCXJldHVybjsKCQl9CgkJLy9jaGVjayB0aGF0IHB1dEluZm8oKSAid3JpdGVzIHRocm91Z2giIHRoZSBzeW1saW5rCgkJbWFrZUxpbmtTdHJ1Y3R1cmUoKTsKCQlsb25nIG9sZFRpbWUgPSBpRmlsZS5nZXRMYXN0TW9kaWZpZWQoKTsKCQlsb25nIHRpbWVUb1NldCA9IG9sZFRpbWUgLSAxMDAwMDA7CgkJaWxsRmlsZS5zZXRMYXN0TW9kaWZpZWQodGltZVRvU2V0KTsKCQlsbEZpbGUucHV0SW5mbyhpbGxGaWxlLCBFRlMuU0VUX0FUVFJJQlVURVMgfCBFRlMuU0VUX0xBU1RfTU9ESUZJRUQsIGdldE1vbml0b3IoKSk7CgkJaUZpbGUgPSBhRmlsZS5mZXRjaEluZm8oKTsKCQlhc3NlcnRFcXVhbHMoaUZpbGUuZ2V0TGFzdE1vZGlmaWVkKCksIHRpbWVUb1NldCk7CgoJCW9sZFRpbWUgPSBpRGlyLmdldExhc3RNb2RpZmllZCgpOwoJCXRpbWVUb1NldCA9IG9sZFRpbWUgLSAxMDAwMDA7CgkJaWxsRGlyLnNldExhc3RNb2RpZmllZCh0aW1lVG9TZXQpOwoJCWxsRGlyLnB1dEluZm8oaWxsRGlyLCBFRlMuU0VUX0FUVFJJQlVURVMgfCBFRlMuU0VUX0xBU1RfTU9ESUZJRUQsIGdldE1vbml0b3IoKSk7CgkJaURpciA9IGFEaXIuZmV0Y2hJbmZvKCk7CgkJYXNzZXJ0VHJ1ZShpRGlyLmdldExhc3RNb2RpZmllZCgpICE9IG9sZFRpbWUpOwoJCWFzc2VydEVxdWFscyhpRGlyLmdldExhc3RNb2RpZmllZCgpLCB0aW1lVG9TZXQpOwoKCQkvLyBDaGVjayB0aGF0IGxpbmsgcHJvcGVydGllcyBhcmUgbWFpbnRhaW5lZCBldmVuIHRocm91Z2ggcHV0SW5mbwoJCWlsbEZpbGUgPSBsbEZpbGUuZmV0Y2hJbmZvKCk7CgkJaWxsRGlyID0gbGxEaXIuZmV0Y2hJbmZvKCk7CgkJYXNzZXJ0VHJ1ZShpbGxGaWxlLmdldEF0dHJpYnV0ZShFRlMuQVRUUklCVVRFX1NZTUxJTkspKTsKCQlhc3NlcnRUcnVlKGlsbERpci5nZXRBdHRyaWJ1dGUoRUZTLkFUVFJJQlVURV9TWU1MSU5LKSk7CgkJYXNzZXJ0RXF1YWxzKGlsbEZpbGUuZ2V0U3RyaW5nQXR0cmlidXRlKEVGUy5BVFRSSUJVVEVfTElOS19UQVJHRVQpLCAibEZpbGUiKTsKCQlhc3NlcnRFcXVhbHMoaWxsRGlyLmdldFN0cmluZ0F0dHJpYnV0ZShFRlMuQVRUUklCVVRFX0xJTktfVEFSR0VUKSwgImxEaXIiKTsKCX0KCglwdWJsaWMgdm9pZCB0ZXN0U3ltbGlua1B1dFJlYWRPbmx5KCkgdGhyb3dzIEV4Y2VwdGlvbiB7CgkJLy8gT25seSBhY3RpdmF0ZSB0aGlzIHRlc3QgaWYgdGVzdGluZyBvZiBzeW1ib2xpYyBsaW5rcyBpcyBwb3NzaWJsZS4KCQlpZiAoIWNhbkNyZWF0ZVN5bUxpbmtzKCkpIHsKCQkJcmV0dXJuOwoJCX0KCQkvL2NoZWNrIHRoYXQgcHV0SW5mbygpICJ3cml0ZXMgdGhyb3VnaCIgdGhlIHN5bWxpbmsKCQltYWtlTGlua1N0cnVjdHVyZSgpOwoJCWlsbEZpbGUuc2V0QXR0cmlidXRlKEVGUy5BVFRSSUJVVEVfUkVBRF9PTkxZLCB0cnVlKTsKCQlsbEZpbGUucHV0SW5mbyhpbGxGaWxlLCBFRlMuU0VUX0FUVFJJQlVURVMsIGdldE1vbml0b3IoKSk7CgkJaUZpbGUgPSBhRmlsZS5mZXRjaEluZm8oKTsKCQlhc3NlcnRFcXVhbHMoIVNZTUxJTktTX0FSRV9GSVJTVF9DTEFTU19GSUxFU19PUl9ESVJFQ1RPUklFUywgaUZpbGUuZ2V0QXR0cmlidXRlKEVGUy5BVFRSSUJVVEVfUkVBRF9PTkxZKSk7CgoJCWlsbEZpbGUuc2V0QXR0cmlidXRlKEVGUy5BVFRSSUJVVEVfUkVBRF9PTkxZLCBmYWxzZSk7CgkJbGxGaWxlLnB1dEluZm8oaWxsRmlsZSwgRUZTLlNFVF9BVFRSSUJVVEVTLCBnZXRNb25pdG9yKCkpOwoJCWlGaWxlID0gYUZpbGUuZmV0Y2hJbmZvKCk7CgkJYXNzZXJ0RmFsc2UoaUZpbGUuZ2V0QXR0cmlidXRlKEVGUy5BVFRSSUJVVEVfUkVBRF9PTkxZKSk7CgoJCWlsbERpci5zZXRBdHRyaWJ1dGUoRUZTLkFUVFJJQlVURV9SRUFEX09OTFksIHRydWUpOwoJCWxsRGlyLnB1dEluZm8oaWxsRGlyLCBFRlMuU0VUX0FUVFJJQlVURVMsIGdldE1vbml0b3IoKSk7CgkJaURpciA9IGFEaXIuZmV0Y2hJbmZvKCk7CgkJYXNzZXJ0RXF1YWxzKCFTWU1MSU5LU19BUkVfRklSU1RfQ0xBU1NfRklMRVNfT1JfRElSRUNUT1JJRVMsIGlEaXIuZ2V0QXR0cmlidXRlKEVGUy5BVFRSSUJVVEVfUkVBRF9PTkxZKSk7CgoJCWlsbERpci5zZXRBdHRyaWJ1dGUoRUZTLkFUVFJJQlVURV9SRUFEX09OTFksIGZhbHNlKTsKCQlsbERpci5wdXRJbmZvKGlsbERpciwgRUZTLlNFVF9BVFRSSUJVVEVTLCBnZXRNb25pdG9yKCkpOwoJCWlEaXIgPSBhRGlyLmZldGNoSW5mbygpOwoJCWFzc2VydEZhbHNlKGlEaXIuZ2V0QXR0cmlidXRlKEVGUy5BVFRSSUJVVEVfUkVBRF9PTkxZKSk7CgoJCS8vIENoZWNrIHRoYXQgbGluayBwcm9wZXJ0aWVzIGFyZSBtYWludGFpbmVkIGV2ZW4gdGhyb3VnaCBwdXRJbmZvCgkJaWxsRmlsZSA9IGxsRmlsZS5mZXRjaEluZm8oKTsKCQlpbGxEaXIgPSBsbERpci5mZXRjaEluZm8oKTsKCQlhc3NlcnRUcnVlKGlsbEZpbGUuZ2V0QXR0cmlidXRlKEVGUy5BVFRSSUJVVEVfU1lNTElOSykpOwoJCWFzc2VydFRydWUoaWxsRGlyLmdldEF0dHJpYnV0ZShFRlMuQVRUUklCVVRFX1NZTUxJTkspKTsKCQlhc3NlcnRFcXVhbHMoaWxsRmlsZS5nZXRTdHJpbmdBdHRyaWJ1dGUoRUZTLkFUVFJJQlVURV9MSU5LX1RBUkdFVCksICJsRmlsZSIpOwoJCWFzc2VydEVxdWFscyhpbGxEaXIuZ2V0U3RyaW5nQXR0cmlidXRlKEVGUy5BVFRSSUJVVEVfTElOS19UQVJHRVQpLCAibERpciIpOwoJfQoKCXB1YmxpYyB2b2lkIHRlc3RTeW1saW5rUHV0RXhlY3V0YWJsZSgpIHRocm93cyBFeGNlcHRpb24gewoJCWlmICghaXNBdHRyaWJ1dGVTdXBwb3J0ZWQoRUZTLkFUVFJJQlVURV9FWEVDVVRBQkxFKSkgewoJCQlyZXR1cm47CgkJfQoJCS8vIE9ubHkgYWN0aXZhdGUgdGhpcyB0ZXN0IGlmIHRlc3Rpbmcgb2Ygc3ltYm9saWMgbGlua3MgaXMgcG9zc2libGUuCgkJaWYgKCFjYW5DcmVhdGVTeW1MaW5rcygpKQoJCSB7CgkJCXJldHVybjsKCQkvLyBBVFRSSUJVVEVfRVhFQ1VUQUJMRSBpcyBub3Qgc3VwcG9ydGVkIG9uIFdpbmRvd3MsIHNvCgkJLy8gU1lNTElOS1NfQVJFX0ZJUlNUX0NMQVNTX0ZJTEVTX09SX0RJUkVDVE9SSUVTIGlzIGZhbHNlIGluIHRoaXMgY29udGV4dC4KCQl9CgoJCS8vY2hlY2sgdGhhdCBwdXRJbmZvKCkgIndyaXRlcyB0aHJvdWdoIiB0aGUgc3ltbGluawoJCW1ha2VMaW5rU3RydWN0dXJlKCk7CgkJaWxsRmlsZS5zZXRBdHRyaWJ1dGUoRUZTLkFUVFJJQlVURV9FWEVDVVRBQkxFLCB0cnVlKTsKCQlsbEZpbGUucHV0SW5mbyhpbGxGaWxlLCBFRlMuU0VUX0FUVFJJQlVURVMsIGdldE1vbml0b3IoKSk7CgkJaUZpbGUgPSBhRmlsZS5mZXRjaEluZm8oKTsKCQlhc3NlcnRUcnVlKGlGaWxlLmdldEF0dHJpYnV0ZShFRlMuQVRUUklCVVRFX0VYRUNVVEFCTEUpKTsKCgkJaWxsRGlyLnNldEF0dHJpYnV0ZShFRlMuQVRUUklCVVRFX0VYRUNVVEFCTEUsIGZhbHNlKTsKCQlsbERpci5wdXRJbmZvKGlsbERpciwgRUZTLlNFVF9BVFRSSUJVVEVTLCBnZXRNb25pdG9yKCkpOwoJCWlEaXIgPSBhRGlyLmZldGNoSW5mbygpOwoJCWFzc2VydEZhbHNlKGlEaXIuZ2V0QXR0cmlidXRlKEVGUy5BVFRSSUJVVEVfRVhFQ1VUQUJMRSkpOwoKCQkvLyBDaGVjayB0aGF0IGxpbmsgcHJvcGVydGllcyBhcmUgbWFpbnRhaW5lZCBldmVuIHRocm91Z2ggcHV0SW5mbwoJCWlsbEZpbGUgPSBsbEZpbGUuZmV0Y2hJbmZvKCk7CgkJaWxsRGlyID0gbGxEaXIuZmV0Y2hJbmZvKCk7CgkJYXNzZXJ0VHJ1ZShpbGxGaWxlLmdldEF0dHJpYnV0ZShFRlMuQVRUUklCVVRFX1NZTUxJTkspKTsKCQlhc3NlcnRUcnVlKGlsbERpci5nZXRBdHRyaWJ1dGUoRUZTLkFUVFJJQlVURV9TWU1MSU5LKSk7CgkJYXNzZXJ0RXF1YWxzKGlsbEZpbGUuZ2V0U3RyaW5nQXR0cmlidXRlKEVGUy5BVFRSSUJVVEVfTElOS19UQVJHRVQpLCAibEZpbGUiKTsKCQlhc3NlcnRFcXVhbHMoaWxsRGlyLmdldFN0cmluZ0F0dHJpYnV0ZShFRlMuQVRUUklCVVRFX0xJTktfVEFSR0VUKSwgImxEaXIiKTsKCX0KCglwdWJsaWMgdm9pZCB0ZXN0U3ltbGlua1B1dEhpZGRlbigpIHRocm93cyBFeGNlcHRpb24gewoJCWlmICghaXNBdHRyaWJ1dGVTdXBwb3J0ZWQoRUZTLkFUVFJJQlVURV9ISURERU4pKSB7CgkJCXJldHVybjsKCQl9CgkJLy8gT25seSBhY3RpdmF0ZSB0aGlzIHRlc3QgaWYgdGVzdGluZyBvZiBzeW1ib2xpYyBsaW5rcyBpcyBwb3NzaWJsZS4KCQlpZiAoIWNhbkNyZWF0ZVN5bUxpbmtzKCkpCgkJIHsKCQkJcmV0dXJuOwoJCS8vIEFUVFJJQlVURV9ISURERU4gaXMgc3VwcG9ydGVkIG9ubHkgb24gV2luZG93cywgc28KCQkvLyBTWU1MSU5LU19BUkVfRklSU1RfQ0xBU1NfRklMRVNfT1JfRElSRUNUT1JJRVMgaXMgdHJ1ZSBpbiB0aGlzIGNvbnRleHQuCgkJfQoKCQkvLyBDaGVjayB0aGF0IHB1dEluZm8oKSBhcHBsaWVzIHRoZSBhdHRyaWJ1dGUgdG8gdGhlIHN5bWxpbmsgaXRzZWxmLgoJCW1ha2VMaW5rU3RydWN0dXJlKCk7CgkJaWxsRmlsZS5zZXRBdHRyaWJ1dGUoRUZTLkFUVFJJQlVURV9ISURERU4sIHRydWUpOwoJCWxsRmlsZS5wdXRJbmZvKGlsbEZpbGUsIEVGUy5TRVRfQVRUUklCVVRFUywgZ2V0TW9uaXRvcigpKTsKCQlpbGxGaWxlID0gbGxGaWxlLmZldGNoSW5mbygpOwoJCWFzc2VydFRydWUoaWxsRmlsZS5nZXRBdHRyaWJ1dGUoRUZTLkFUVFJJQlVURV9ISURERU4pKTsKCQlpRmlsZSA9IGFGaWxlLmZldGNoSW5mbygpOwoJCWFzc2VydEZhbHNlKGlGaWxlLmdldEF0dHJpYnV0ZShFRlMuQVRUUklCVVRFX0hJRERFTikpOwoKCQlpbGxEaXIuc2V0QXR0cmlidXRlKEVGUy5BVFRSSUJVVEVfSElEREVOLCB0cnVlKTsKCQlsbERpci5wdXRJbmZvKGlsbERpciwgRUZTLlNFVF9BVFRSSUJVVEVTLCBnZXRNb25pdG9yKCkpOwoJCWlsbERpciA9IGxsRGlyLmZldGNoSW5mbygpOwoJCWFzc2VydFRydWUoaWxsRGlyLmdldEF0dHJpYnV0ZShFRlMuQVRUUklCVVRFX0hJRERFTikpOwoJCWlEaXIgPSBhRGlyLmZldGNoSW5mbygpOwoJCWFzc2VydEZhbHNlKGlEaXIuZ2V0QXR0cmlidXRlKEVGUy5BVFRSSUJVVEVfSElEREVOKSk7CgoJCS8vIENoZWNrIHRoYXQgbGluayBwcm9wZXJ0aWVzIGFyZSBtYWludGFpbmVkIGV2ZW4gdGhyb3VnaCBwdXRJbmZvLgoJCWlsbEZpbGUgPSBsbEZpbGUuZmV0Y2hJbmZvKCk7CgkJaWxsRGlyID0gbGxEaXIuZmV0Y2hJbmZvKCk7CgkJYXNzZXJ0VHJ1ZShpbGxGaWxlLmdldEF0dHJpYnV0ZShFRlMuQVRUUklCVVRFX1NZTUxJTkspKTsKCQlhc3NlcnRUcnVlKGlsbERpci5nZXRBdHRyaWJ1dGUoRUZTLkFUVFJJQlVURV9TWU1MSU5LKSk7CgkJYXNzZXJ0RXF1YWxzKGlsbEZpbGUuZ2V0U3RyaW5nQXR0cmlidXRlKEVGUy5BVFRSSUJVVEVfTElOS19UQVJHRVQpLCAibEZpbGUiKTsKCQlhc3NlcnRFcXVhbHMoaWxsRGlyLmdldFN0cmluZ0F0dHJpYnV0ZShFRlMuQVRUUklCVVRFX0xJTktfVEFSR0VUKSwgImxEaXIiKTsKCX0KCgkvLyBSZW1vdmluZyBhIHN5bWxpbmsga2VlcHMgdGhlIGxpbmsgdGFyZ2V0IGludGFjdC4KCS8vIFN5bWxpbmtzIGJlaW5nIGJyb2tlbiBkdWUgdG8gcmVtb3ZlIGFyZSBzZXQgdG8gbm9uLWV4aXN0ZW50LgoJcHVibGljIHZvaWQgdGVzdFN5bWxpbmtSZW1vdmUoKSB0aHJvd3MgRXhjZXB0aW9uIHsKCQkvLyBPbmx5IGFjdGl2YXRlIHRoaXMgdGVzdCBpZiB0ZXN0aW5nIG9mIHN5bWJvbGljIGxpbmtzIGlzIHBvc3NpYmxlLgoJCWlmICghY2FuQ3JlYXRlU3ltTGlua3MoKSkgewoJCQlyZXR1cm47CgkJfQoJCW1ha2VMaW5rU3RydWN0dXJlKCk7CgkJbEZpbGUuZGVsZXRlKEVGUy5OT05FLCBnZXRNb25pdG9yKCkpOwoJCWlsbEZpbGUgPSBsRmlsZS5mZXRjaEluZm8oKTsKCQlhc3NlcnRGYWxzZShpbGxGaWxlLmV4aXN0cygpKTsKCQlpRmlsZSA9IGFGaWxlLmZldGNoSW5mbygpOwoJCWFzc2VydFRydWUoaUZpbGUuZXhpc3RzKCkpOwoKCQlJRmlsZVN0b3JlIGNoaWxkRmlsZSA9IGFEaXIuZ2V0Q2hpbGQoInN1YkZpbGUiKTsKCQllbnN1cmVFeGlzdHMoY2hpbGRGaWxlLCBmYWxzZSk7CgkJbERpci5kZWxldGUoRUZTLk5PTkUsIGdldE1vbml0b3IoKSk7CgkJaWxsRGlyID0gbERpci5mZXRjaEluZm8oKTsKCQlhc3NlcnRGYWxzZShpbGxGaWxlLmV4aXN0cygpKTsKCQlpRGlyID0gYURpci5mZXRjaEluZm8oKTsKCQlhc3NlcnRUcnVlKGlEaXIuZXhpc3RzKCkpOwoJCS8vIENoZWNrIHRoYXQgdGhlIGNvbnRlbnRzIG9mIHRoZSBkaXJlY3RvcnkgYXJlIHByZXNlcnZlZC4KCQlJRmlsZUluZm8gaUZpbGVJbnNpZGVEaXIgPSBjaGlsZEZpbGUuZmV0Y2hJbmZvKCk7CgkJYXNzZXJ0VHJ1ZShpRmlsZUluc2lkZURpci5leGlzdHMoKSk7Cgl9Cgp9Cg==