LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogQ29weXJpZ2h0IChjKSAyMDAwLCAyMDExIElCTSBDb3Jwb3JhdGlvbiBhbmQgb3RoZXJzLgogKiBBbGwgcmlnaHRzIHJlc2VydmVkLiBUaGlzIHByb2dyYW0gYW5kIHRoZSBhY2NvbXBhbnlpbmcgbWF0ZXJpYWxzCiAqIGFyZSBtYWRlIGF2YWlsYWJsZSB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEVjbGlwc2UgUHVibGljIExpY2Vuc2UgdjEuMAogKiB3aGljaCBhY2NvbXBhbmllcyB0aGlzIGRpc3RyaWJ1dGlvbiwgYW5kIGlzIGF2YWlsYWJsZSBhdAogKiBodHRwOi8vd3d3LmVjbGlwc2Uub3JnL2xlZ2FsL2VwbC12MTAuaHRtbAogKgogKiBDb250cmlidXRvcnM6CiAqICAgICBJQk0gQ29ycG9yYXRpb24gLSBpbml0aWFsIEFQSSBhbmQgaW1wbGVtZW50YXRpb24KICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovCgpwYWNrYWdlIG9yZy5lY2xpcHNlLmpkdC5jb3JlLnRlc3RzLnBlcmZvcm1hbmNlOwoKaW1wb3J0IGphdmEuaW8uKjsKaW1wb3J0IGphdmEubmV0LlVSTDsKaW1wb3J0IGphdmEudGV4dC5EYXRlRm9ybWF0OwppbXBvcnQgamF2YS50ZXh0Lk51bWJlckZvcm1hdDsKaW1wb3J0IGphdmEudXRpbC4qOwoKaW1wb3J0IGp1bml0LmZyYW1ld29yay4qOwppbXBvcnQgb3JnLmVjbGlwc2UuY29yZS5yZXNvdXJjZXMuKjsKaW1wb3J0IG9yZy5lY2xpcHNlLmNvcmUucnVudGltZS4qOwppbXBvcnQgb3JnLmVjbGlwc2UuY29yZS5ydW50aW1lLnByZWZlcmVuY2VzLklFY2xpcHNlUHJlZmVyZW5jZXM7CmltcG9ydCBvcmcuZWNsaXBzZS5jb3JlLnJ1bnRpbWUucHJlZmVyZW5jZXMuSW5zdGFuY2VTY29wZTsKaW1wb3J0IG9yZy5lY2xpcHNlLmpkdC5jb3JlLio7CmltcG9ydCBvcmcuZWNsaXBzZS5qZHQuY29yZS50ZXN0cy5idWlsZGVyLlRlc3RpbmdFbnZpcm9ubWVudDsKaW1wb3J0IG9yZy5lY2xpcHNlLmpkdC5jb3JlLnRlc3RzLmp1bml0LmV4dGVuc2lvbi5UZXN0Q2FzZTsKaW1wb3J0IG9yZy5lY2xpcHNlLmpkdC5jb3JlLnRlc3RzLm1vZGVsLkFic3RyYWN0SmF2YU1vZGVsVGVzdHM7CmltcG9ydCBvcmcuZWNsaXBzZS5qZHQuY29yZS50ZXN0cy5wZXJmb3JtYW5jZS51dGlsLkpkdENvcmVQZXJmb3JtYW5jZU1ldGVyOwppbXBvcnQgb3JnLmVjbGlwc2UuamR0LmNvcmUudGVzdHMucGVyZm9ybWFuY2UudXRpbC5TdGF0aXN0aWNzOwppbXBvcnQgb3JnLmVjbGlwc2UuamR0LmNvcmUudGVzdHMudXRpbC5VdGlsOwppbXBvcnQgb3JnLmVjbGlwc2UuamR0LmludGVybmFsLmNvbXBpbGVyLmJhdGNoLk1haW47CmltcG9ydCBvcmcuZWNsaXBzZS5qZHQuaW50ZXJuYWwuY29tcGlsZXIuaW1wbC5Db21waWxlck9wdGlvbnM7CmltcG9ydCBvcmcuZWNsaXBzZS5qZHQuaW50ZXJuYWwuY29yZS5KYXJQYWNrYWdlRnJhZ21lbnRSb290OwppbXBvcnQgb3JnLmVjbGlwc2UuamR0LmludGVybmFsLmNvcmUuSmF2YUNvcmVQcmVmZXJlbmNlSW5pdGlhbGl6ZXI7CmltcG9ydCBvcmcuZWNsaXBzZS5qZHQuaW50ZXJuYWwuY29yZS5KYXZhTW9kZWxNYW5hZ2VyOwppbXBvcnQgb3JnLmVjbGlwc2UuamR0LmludGVybmFsLmNvcmUuSmF2YVByb2plY3Q7CmltcG9ydCBvcmcuZWNsaXBzZS5qZHQuaW50ZXJuYWwuY29yZS5zZWFyY2guaW5kZXhpbmcuSW5kZXhNYW5hZ2VyOwppbXBvcnQgb3JnLmVjbGlwc2UudGVzdC5pbnRlcm5hbC5wZXJmb3JtYW5jZS5kYXRhLkRhdGFQb2ludDsKaW1wb3J0IG9yZy5lY2xpcHNlLnRlc3QucGVyZm9ybWFuY2UuRGltZW5zaW9uOwppbXBvcnQgb3JnLmVjbGlwc2UudGVzdC5wZXJmb3JtYW5jZS5QZXJmb3JtYW5jZTsKCgoKcHVibGljIGFic3RyYWN0IGNsYXNzIEZ1bGxTb3VyY2VXb3Jrc3BhY2VUZXN0cyBleHRlbmRzIFRlc3RDYXNlIHsKCgkvLyBEZWJ1ZyB2YXJpYWJsZXMKCWZpbmFsIHN0YXRpYyBib29sZWFuIERFQlVHID0gInRydWUiLmVxdWFscyhTeXN0ZW0uZ2V0UHJvcGVydHkoImRlYnVnIikpOwoJZmluYWwgc3RhdGljIGJvb2xlYW4gUFJJTlQgPSAidHJ1ZSIuZXF1YWxzKFN5c3RlbS5nZXRQcm9wZXJ0eSgicHJpbnQiKSk7CgkvKioKCSAqIEZsYWcgdG8gdmFsaWRhdGUgdGVzdCBydW4gZW52aXJvbm1lbnQuCgkgKiA8cD4KCSAqIFRoaXMgcHJvcGVydHkgaGFzIGJlZW4gYWRkZWQgdG8gc3BlZWQtdXAgY2hlY2stdXAgb2YgbG9jYWwgc2hlbGxzIHRvIHJ1biB0aGUKCSAqIGVudGlyZSBwZXJmb3JtYW5jZSB0ZXN0cy4KCSAqIDxwPgoJICogV0FSTklORzogaWYgdGhpcyBwcm9wZXJ0eSBpcyBzZXQsICpub3RoaW5nIGF0IGFsbCogd2lsbCBiZSBydW4sIG5laXRoZXIgbWVhc3VyZSBub3Igd2FybS11cC4KCSAqLwoJZmluYWwgc3RhdGljIGJvb2xlYW4gVE9VQ0ggPSAidHJ1ZSIuZXF1YWxzKFN5c3RlbS5nZXRQcm9wZXJ0eSgidG91Y2giKSk7CgoJLy8gT3B0aW9ucwoJZmluYWwgc3RhdGljIEhhc2h0YWJsZSBJTklUSUFMX09QVElPTlMgPSBKYXZhQ29yZS5nZXRPcHRpb25zKCk7CglmaW5hbCBzdGF0aWMgU3RyaW5nIENPTVBMSUFOQ0UgPSBTeXN0ZW0uZ2V0UHJvcGVydHkoImNvbXBsaWFuY2UiKTsKCXN0YXRpYyB7CgkJSGFzaHRhYmxlIG9wdGlvbnMgPSBJTklUSUFMX09QVElPTlM7CgkJU3RyaW5nIGNvbXBsaWFuY2UgPSBjb21wbGlhbmNlKCk7CgkJaWYgKGNvbXBsaWFuY2UgPT0gbnVsbCkgewoJCQlTeXN0ZW0ub3V0LnByaW50bG4oIlVzZWQgZGVmYXVsdCBjb21wbGlhbmNlOiAiK29wdGlvbnMuZ2V0KEphdmFDb3JlLkNPTVBJTEVSX0NPTVBMSUFOQ0UpKTsKCQl9IGVsc2UgewoJCQlTeXN0ZW0ub3V0LnByaW50bG4oIlVzZWQgY29tcGxpYW5jZTogIitjb21wbGlhbmNlKTsKCQkJb3B0aW9ucy5wdXQoQ29tcGlsZXJPcHRpb25zLk9QVElPTl9Db21wbGlhbmNlLCBjb21wbGlhbmNlKTsKCQkJb3B0aW9ucy5wdXQoQ29tcGlsZXJPcHRpb25zLk9QVElPTl9Tb3VyY2UsIGNvbXBsaWFuY2UpOwoJCQlvcHRpb25zLnB1dChDb21waWxlck9wdGlvbnMuT1BUSU9OX1RhcmdldFBsYXRmb3JtLCBjb21wbGlhbmNlKTsKCQkJSmF2YUNvcmUuc2V0T3B0aW9ucyhvcHRpb25zKTsKCQl9Cgl9Cglwcm90ZWN0ZWQgc3RhdGljIFN0cmluZyBjb21wbGlhbmNlKCkgewoJCVN0cmluZyBjb21wbGlhbmNlID0gbnVsbDsKCQlpZiAoIjEuMyIuZXF1YWxzKENPTVBMSUFOQ0UpKSB7CgkJCWNvbXBsaWFuY2UgPSBDb21waWxlck9wdGlvbnMuVkVSU0lPTl8xXzM7CgkJfSBlbHNlIGlmICgiMS40Ii5lcXVhbHMoQ09NUExJQU5DRSkpIHsKCQkJY29tcGxpYW5jZSA9IENvbXBpbGVyT3B0aW9ucy5WRVJTSU9OXzFfNDsKCQl9IGVsc2UgaWYgKCIxLjUiLmVxdWFscyhDT01QTElBTkNFKSB8fCAiNS4wIi5lcXVhbHMoQ09NUExJQU5DRSkpIHsKCQkJY29tcGxpYW5jZSA9IENvbXBpbGVyT3B0aW9ucy5WRVJTSU9OXzFfNTsKCQl9IGVsc2UgaWYgKCIxLjYiLmVxdWFscyhDT01QTElBTkNFKSB8fCAiNi4wIi5lcXVhbHMoQ09NUExJQU5DRSkpIHsKCQkJY29tcGxpYW5jZSA9IENvbXBpbGVyT3B0aW9ucy5WRVJTSU9OXzFfNjsKCQl9CgkJcmV0dXJuIGNvbXBsaWFuY2U7Cgl9CgoJLy8gR2FyYmFnZSBjb2xsZWN0IGNvbnN0YW50cwoJZmluYWwgc3RhdGljIGludCBNQVhfR0MgPSAxMDsgLy8gTWF4IGdjIGl0ZXJhdGlvbnMKCWZpbmFsIHN0YXRpYyBpbnQgVElNRV9HQyA9IDUwMDsgLy8gU2xlZXAgdG8gd2FpdCBnYyB0byBydW4gKGluIG1zKQoJZmluYWwgc3RhdGljIGludCBERUxUQV9HQyA9IDEwMDA7IC8vIFRocmVzaG9sZCB0byByZW1haW5pbmcgZnJlZSBtZW1vcnkKCgkvLyBXb3Jrc3BhY2UgdmFyaWFibGVzCglwcm90ZWN0ZWQgc3RhdGljIFRlc3RpbmdFbnZpcm9ubWVudCBFTlYgPSBudWxsOwoJcHJvdGVjdGVkIHN0YXRpYyBJSmF2YVByb2plY3RbXSBBTExfUFJPSkVDVFM7Cglwcm90ZWN0ZWQgc3RhdGljIElKYXZhUHJvamVjdCBKRFRfQ09SRV9QUk9KRUNUOwoJcHJvdGVjdGVkIHN0YXRpYyBJQ29tcGlsYXRpb25Vbml0IFBBUlNFUl9XT1JLSU5HX0NPUFk7Cglwcm90ZWN0ZWQgZmluYWwgc3RhdGljIFN0cmluZyBCSUdfUFJPSkVDVF9OQU1FID0gIkJpZ1Byb2plY3QiOwoJcHJvdGVjdGVkIHN0YXRpYyBKYXZhUHJvamVjdCBCSUdfUFJPSkVDVDsKCXByb3RlY3RlZCBzdGF0aWMgZmluYWwgU3RyaW5nIEJJR19KQVIxX05BTUUgPSAiYmlnMS5qYXIiOwoJcHJvdGVjdGVkIHN0YXRpYyBmaW5hbCBTdHJpbmcgQklHX0pBUjJfTkFNRSA9ICJiaWcyLmphciI7Ci8vCXByb3RlY3RlZCBmaW5hbCBzdGF0aWMgU3RyaW5nIEpVTklUX1BST0pFQ1RfTkFNRSA9ICJqdW5pdCI7Ci8vCXByb3RlY3RlZCBzdGF0aWMgSUphdmFQcm9qZWN0IEpVTklUX1BST0pFQ1Q7CgoJLy8gQ29tcGlsYWl0b24gdmFyaWFibGUKCXB1YmxpYyBzdGF0aWMgZmluYWwgU3RyaW5nIENPTVBJTEVSX09VVFBVVF9ESVI7CglzdGF0aWMgewoJCVN0cmluZyBvdXRwdXREaXIgPSBudWxsOwoJCVN0cmluZyBjb250YWluZXIgPSBTeXN0ZW0uZ2V0UHJvcGVydHkoInVzZXIuaG9tZSIpOwoJCWlmIChjb250YWluZXIgPT0gbnVsbCl7CgkJCUlXb3Jrc3BhY2Ugd29ya3NwYWNlID0gUmVzb3VyY2VzUGx1Z2luLmdldFdvcmtzcGFjZSgpOwoJCQlJV29ya3NwYWNlUm9vdCB3b3Jrc3BhY2VSb290ID0gd29ya3NwYWNlLmdldFJvb3QoKTsKCQkJRmlsZSBwbHVnaW5EaXIgPSB3b3Jrc3BhY2VSb290LmdldFByb2plY3QoSmF2YUNvcmUuUExVR0lOX0lEKS5nZXRMb2NhdGlvbigpLnRvRmlsZSgpOwoJCQl0cnkgewoJCQkJb3V0cHV0RGlyID0gcGx1Z2luRGlyLmdldENhbm9uaWNhbFBhdGgoKSArIEZpbGUuc2VwYXJhdG9yICsgImJpbiI7CgkJCX0gY2F0Y2ggKElPRXhjZXB0aW9uIGUpIHsKCQkJCS8vIHNraXAKCQkJfQoJCX0gZWxzZSB7CgkJCW91dHB1dERpciA9IFV0aWwudG9OYXRpdmVQYXRoKGNvbnRhaW5lcikgKyBGaWxlLnNlcGFyYXRvciArICJiaW4iOwoJCX0KCQlpZiAob3V0cHV0RGlyID09IG51bGwpIHsKCQkJQ09NUElMRVJfT1VUUFVUX0RJUiA9ICJub25lIjsKCQl9IGVsc2UgewoJCQlDT01QSUxFUl9PVVRQVVRfRElSID0gIlwiIitvdXRwdXREaXIrIlwiIjsKCQl9Cgl9CgoKCS8vIEluZGV4IHZhcmlhYmxlcwoJcHJvdGVjdGVkIHN0YXRpYyBJbmRleE1hbmFnZXIgSU5ERVhfTUFOQUdFUiA9IEphdmFNb2RlbE1hbmFnZXIuZ2V0SW5kZXhNYW5hZ2VyKCk7CgoJLy8gVGVzdHMgaW5mb3MKCXByb3RlY3RlZCBzdGF0aWMgaW50IEFMTF9URVNUU19DT1VOVCA9IDA7Cglwcm90ZWN0ZWQgc3RhdGljIGludCBURVNUX1BPU0lUSU9OID0gMDsKCXByb3RlY3RlZCBzdGF0aWMgTGlzdCBURVNUU19OQU1FX0xJU1Q7CgoJLyoqCgkgKiBDb3VudCBvZiBtZWFzdXJlcyBkb25lIGZvciBhbGwgdGVzdHMuCgkgKiA8Yj4KCSAqIERlZmF1bHQgdmFsdWUgaXMgMTAgYnV0IGNhbiBiZSBtb2RpZmllZCB1c2luZyBzeXN0ZW0gcHJvcGVydHkgIm1lYXN1cmVzIi4KCSAqIDxiPgoJICogRm9yIGV4YW1wbGUsICItRG1lYXN1cmVzPTEiIHdpbGwgbWFrZSBhbGwgcGVyZm9ybWFuY2UgdGVzdCBzdWl0ZXMgdG8gcnVuCgkgKiBvbmx5IDEgaXRlcmF0aW9uIGZvciBlYWNoIHRlc3QuCgkgKi8KCXByb3RlY3RlZCBmaW5hbCBzdGF0aWMgaW50IE1FQVNVUkVTX0NPVU5UOwoJc3RhdGljIHsKCQlTdHJpbmcgbWVhc3VyZXMgPSBTeXN0ZW0uZ2V0UHJvcGVydHkoIm1lYXN1cmVzIiwgIjEwIik7CgkJaW50IGNvdW50ID0gMTA7CgkJdHJ5IHsKCQkJY291bnQgPSBJbnRlZ2VyLnBhcnNlSW50KG1lYXN1cmVzKTsKCQkJaWYgKGNvdW50IDwgMCB8fCBjb3VudCA+IDIwKSB7CgkJCQlTeXN0ZW0ub3V0LnByaW50bG4oIklORk86IE1lYXN1cmVzIHBhcmFtZXRlciAoIitjb3VudCsiKSBpcyBpZ25vcmVkIGFzIGl0IGlzIGFuIGludmFsaWQgdmFsdWUhIChzaG91bGQgYmUgYmV0d2VlbiAwIGFuZCAyMCkiKTsKCQkJCWNvdW50ID0gMTA7CgkJCX0gZWxzZSBpZiAoY291bnQgIT0gMTApIHsKCQkJCVN5c3RlbS5vdXQucHJpbnRsbigiV0FSTklORzogTWVhc3VyZXMgY291bnQgaGFzIGJlZW4gY2hhbmdlZCB3aGlsZSBydW5uaW5nIHRoaXMgdGVzdCA9ICIrY291bnQrIiBpbnN0ZWFkIG9mIDEwIG5vcm1hbGx5ISIpOwoJCQl9CgkJfQoJCWNhdGNoIChOdW1iZXJGb3JtYXRFeGNlcHRpb24gbmZlKSB7CgkJCS8vIHVzZSBkZWZhdWx0IHZhbHVlCgkJCVN5c3RlbS5vdXQucHJpbnRsbigiSU5GTzogU3BlY2lmaWVkICdtZWFzdXJlcycgVk0gYXJndW1lbnQgKD0iK21lYXN1cmVzKyIpIGlzIGlnbm9yZWQgYXMgaXQgaXMgbm90IGFuIGludGVnZXIgKDAtMjApISIpOwoJCX0KCQlNRUFTVVJFU19DT1VOVCA9IGNvdW50OwoJfQoKCS8vIFNjZW5hcmlvIGluZm9ybWF0aW9uCglTdHJpbmcgc2NlbmFyaW9SZWFkYWJsZU5hbWUsIHNjZW5hcmlvU2hvcnROYW1lOwoJU3RyaW5nQnVmZmVyIHNjZW5hcmlvQ29tbWVudDsKCXN0YXRpYyBNYXAgU0NFTkFSSUlfQ09NTUVOVCA9IG5ldyBIYXNoTWFwKCk7CgoJLy8gVGltZSBtZWFzdXJpbmcKCWludCBuYk1lYXN1cmVzOwoJbG9uZyBzdGFydE1lYXN1cmluZywgdGVzdER1cmF0aW9uOwoKCS8vIEVycm9yIHRocmVzaG9sZC4gU3RhdGlzdGljIHNob3VsZCBub3QgYmUgdGFrZSBpbnRvIGFjY291bnQgd2hlbiBpdCdzIHJlYWNoZWQKCXByb3RlY3RlZCBmaW5hbCBzdGF0aWMgZG91YmxlIEVSUk9SX1RIUkVTSE9MRCA9IDAuMDA1OyAvLyBkZWZhdWx0IGlzIDAuNSUKCXByb3RlY3RlZCBmaW5hbCBzdGF0aWMgU3RyaW5nIEVSUk9SX1NUUklORzsKCXN0YXRpYyB7CgkJTnVtYmVyRm9ybWF0IHZhbHVlRm9ybWF0ID0gTnVtYmVyRm9ybWF0LmdldE51bWJlckluc3RhbmNlKCk7CgkJdmFsdWVGb3JtYXQuc2V0TWF4aW11bUZyYWN0aW9uRGlnaXRzKDEpOwoJCUVSUk9SX1NUUklORyA9IHZhbHVlRm9ybWF0LmZvcm1hdChFUlJPUl9USFJFU0hPTEQqMTAwKTsKCX0KCgkvKioKCSAqIFZhcmlhYmxlIHVzZWQgZm9yIGxvZyBmaWxlcy4KCSAqIExvZyBmaWxlcyBhcmUgdXNlZCBpbiBjb25qb25jdGlvbiB3aXRoIHtAbGluayBKZHRDb3JlUGVyZm9ybWFuY2VNZXRlcn0gY2xhc3MuCgkgKiBUaGVzZSBhcmUgZmlsZSB3aGVyZSBDUFUgdGltZXMgb2YgZWFjaCB0ZXN0IG9mIHN1YmNsYXNzZXMgYXJlIHN0b3JlZC4KCSAqIFRoaXMgc3BlY2lmaWMgd2F5IHRvIHJ1biBwZXJmb3JtYW5jZSB0ZXN0cyBpcyBhY3RpdmF0ZWQgYnkgc3BlY2lmeWluZwoJICogZm9sbG93aW5nIG9wdGlvbnM6CgkgKgkJLURQZXJmb3JtYW5jZU1ldGVyRmFjdG9yeT1vcmcuZWNsaXBzZS5qZHQuY29yZS50ZXN0cy5wZXJmb3JtYW5jZTpvcmcuZWNsaXBzZS5qZHQuY29yZS50ZXN0cy5wZXJmb3JtYW5jZS51dGlsLkpkdENvcmVQZXJmb3JtYW5jZU1ldGVyRmFjdG9yeQoJICoJCS1EbG9nRGlyPWRpcmVjdG9yeSB3aGVyZSB5b3Ugd2FudCB0byB3cml0ZSBsb2cgZmlsZXMgKGZvciBleGFtcGxlIGQ6L3Vzci9PVEkvdGVzdHMvcGVyZnMvc3RhdHMpCgkgKgoJICovCgkvLyBTdG9yZSBkaXJlY3Rvcnkgd2hlcmUgdG8gcHV0IGZpbGVzCglwcml2YXRlIGZpbmFsIHN0YXRpYyBGaWxlIElOVkFMSURfRElSID0gbmV3IEZpbGUoIkludmFsaWQiKTsKCXByb3RlY3RlZCBzdGF0aWMgRmlsZSBMT0dfRElSOwoJLy8gVHlwZXMgb2Ygc3RhdGlzdGljIHdoaWNoIGNhbiBiZSBzdG9yZWQuCglwcm90ZWN0ZWQgZmluYWwgc3RhdGljIFN0cmluZ1tdIERJTV9OQU1FUyA9IHsgImNwdSIsICJlbGFwc2VkIiwgImhlYXAiIH07CgkvLyBNYWluIHZlcnNpb24gd2hpY2ggaXMgbG9nZ2VkCglwcm90ZWN0ZWQgZmluYWwgc3RhdGljIFN0cmluZyBMT0dfVkVSU0lPTjsKCXN0YXRpYyB7CgkJU3RyaW5nIHZlcnNpb24gPSBuZXcgTWFpbihudWxsLypvdXRXcml0ZXIqLywgbnVsbC8qZXJyV3JpdGVyKi8sIGZhbHNlLypzeXN0ZW1FeGl0Ki8sIG51bGwvKm9wdGlvbnMqLywgbnVsbC8qcHJvZ3Jlc3MqLykuYmluZCgiY29tcGlsZXIudmVyc2lvbiIpOwoJCXZlcnNpb24gPSB2ZXJzaW9uLnN1YnN0cmluZygwLCB2ZXJzaW9uLmluZGV4T2YoJywnKSk7CgkJaWYgKHZlcnNpb24uc3RhcnRzV2l0aCgiMC4iKSkgewoJCQl2ZXJzaW9uID0gInZfIit2ZXJzaW9uLnN1YnN0cmluZygyKTsKCQl9CgkJTE9HX1ZFUlNJT04gPSB2ZXJzaW9uOwoJfQoJLy8gUGF0Y2ggdmVyc2lvbiBjdXJyZW50bHkgYXBwbGllZDogbWF5IGJlIG51bGwhCglwcm90ZWN0ZWQgZmluYWwgc3RhdGljIFN0cmluZyBQQVRDSF9JRCA9IFN5c3RlbS5nZXRQcm9wZXJ0eSgicGF0Y2giKTsKCXByb3RlY3RlZCBzdGF0aWMgU3RyaW5nIFJVTl9JRDsKCgkvLyBGb3JtYXQgdG8gc3RvcmUvZGlzcGxheSBudW1iZXJzCglwcml2YXRlIE51bWJlckZvcm1hdCBwZXJjZW50Rm9ybWF0ID0gTnVtYmVyRm9ybWF0LmdldFBlcmNlbnRJbnN0YW5jZSgpOwoJcHJpdmF0ZSBmaW5hbCBOdW1iZXJGb3JtYXQgZDJGb3JtYXQgPSBOdW1iZXJGb3JtYXQuZ2V0TnVtYmVySW5zdGFuY2UoKTsKCXsKCQl0aGlzLnBlcmNlbnRGb3JtYXQuc2V0TWF4aW11bUZyYWN0aW9uRGlnaXRzKDEpOwoJCXRoaXMuZDJGb3JtYXQuc2V0TWF4aW11bUZyYWN0aW9uRGlnaXRzKDIpOwoJfQoKCS8vIEZpbHRlciB0byBnZXQgb25seSB0aGUgMy4wIHBsdWdpbnMKCWNsYXNzIEZ1bGxTb3VyY2VQcm9qZWN0c0ZpbHRlciBpbXBsZW1lbnRzIEZpbGVGaWx0ZXIgewoJCXB1YmxpYyBib29sZWFuIGFjY2VwdChGaWxlIHByb2plY3QpIHsKCQkJaWYgKHByb2plY3QuaXNEaXJlY3RvcnkoKSkgewoJCQkJU3RyaW5nVG9rZW5pemVyIHRva2VuaXplciA9IG5ldyBTdHJpbmdUb2tlbml6ZXIocHJvamVjdC5nZXROYW1lKCksICIuIik7CgkJCQlTdHJpbmcgdG9rZW4gPSB0b2tlbml6ZXIubmV4dFRva2VuKCk7CgkJCQlpZiAodG9rZW4uZXF1YWxzKCJvcmciKSAmJiB0b2tlbml6ZXIuaGFzTW9yZVRva2VucygpKSB7CgkJCQkJdG9rZW4gPSB0b2tlbml6ZXIubmV4dFRva2VuKCk7CgkJCQkJaWYgKHRva2VuLmVxdWFscygianVuaXQiKSAmJiAhdG9rZW5pemVyLmhhc01vcmVUb2tlbnMoKSkgewoJCQkJCQlyZXR1cm4gdHJ1ZTsKCQkJCQl9CgkJCQkJaWYgKHRva2VuLmVxdWFscygiYXBhY2hlIikpIHsKCQkJCQkJdG9rZW4gPSB0b2tlbml6ZXIubmV4dFRva2VuKCk7CgkJCQkJCWlmICh0b2tlbi5lcXVhbHMoImFudCIpIHx8IHRva2VuLmVxdWFscygibHVjZW5lIikpIHsKCQkJCQkJCXJldHVybiB0cnVlOwoJCQkJCQl9CgkJCQkJCXJldHVybiBmYWxzZTsKCQkJCQl9CgkJCQkJaWYgKHRva2VuLmVxdWFscygiZWNsaXBzZSIpICYmIHRva2VuaXplci5oYXNNb3JlVG9rZW5zKCkpIHsKCQkJCQkJcmV0dXJuIHRydWU7CgkJCQkJfQoJCQkJfQoJCQl9CgkJCXJldHVybiBmYWxzZTsKCQl9Cgl9CgoJLyoqCgkgKiBJbml0aWFsaXplIGxvZyBkaXJlY3RvcnkuCgkgKgoJICogRGlyZWN0b3J5IHdoZXJlIGxvZyBmaWxlcyBtdXN0IGJlIHB1dCBpcyBzcGVjaWZpZWQgYnkgU3lzdGVtIHByb3BlcnR5IDxjb2RlPmxvZ0RpcjwvY29kZT4uCgkgKiBGb3IgZXhhbXBsZSwgaWYgdXNlciB3YW50IHRvIHN0b3JlIGxvZyBmaWxlcyBpbiBkOi91c3IvT1RJL3Rlc3RzL3BlcmZzL3N0YXRzLAoJICogdGhlbiBoZSBoYXMgdG8gc3BlY2lmeTogLURsb2dEaXI9ZDovdXNyL09USS90ZXN0cy9wZXJmcy9zdGF0cyBpbiBWTSBBcmd1bWVudHMgb2YgaGlzCgkgKiBwZXJmb3JtYW5jZSB0ZXN0IGxhdW5jaCBjb25maWd1cmF0aW9uLgoJICoKCSAqIENBVVRJT046IFBhcmVudCBkaXJlY3RvcnkgYXQgbGVhc3QgPGI+bXVzdDwvYj4gZXhpc3QgYmVmb3JlIHJ1bm5pbmcgdGVzdCBvdGhlcndpc2UKCSAqIGl0IHdvbid0IGJlIGNyZWF0ZWQgYW5kIHRpbWVzIHdvbid0IGJlIGxvZ2dlZC4KCSAqIFRoaXMgd2FzIGludGVudGlvbmFsIHRvIGF2b2lkIHVuZXhwZWN0ZWQgbG9nIGZpbGVzIGNyZWF0aW9uIChlc3BlY2lhbGx5IGR1cmluZyBuaWdodGx5L2ludGVncmF0aW9uIGJ1aWxkcykuCgkgKi8KCXByb3RlY3RlZCBzdGF0aWMgdm9pZCBpbml0TG9nRGlyKCkgewoJCVN0cmluZyBsb2dEaXIgPSBTeXN0ZW0uZ2V0UHJvcGVydHkoImxvZ0RpciIpOwoJCUZpbGUgZGlyID0gbnVsbDsKCQlpZiAobG9nRGlyICE9IG51bGwpIHsKCQkJLy8gVmVyaWZ5IHRoYXQgcGFyZW50IGxvZyBkaXIgaXMgdmFsaWQgaWYgZXhpc3QKCQkJZGlyID0gbmV3IEZpbGUobG9nRGlyKTsKCQkJaWYgKGRpci5leGlzdHMoKSkgewoJCQkJaWYgKCFkaXIuaXNEaXJlY3RvcnkoKSkgewoJCQkJCVN5c3RlbS5lcnIucHJpbnRsbihsb2dEaXIrIiBpcyBub3QgYSB2YWxpZCBkaXJlY3RvcnksIGxvZyBmaWxlcyB3aWxsIE5PVCBiZSB3cml0dGVuISIpOwoJCQkJCWRpciA9IElOVkFMSURfRElSOwoJCQkJfQoJCQl9IGVsc2UgewoJCQkJLy8gQ3JlYXRlIHBhcmVudCBkaXIgaWYgbmVjZXNzYXJ5CgkJCQlpbnQgbj0wOwoJCQkJYm9vbGVhbiBjcmVhdGVkID0gZmFsc2U7CgkJCQl3aGlsZSAoIWNyZWF0ZWQgJiYgbjwzKSB7CgkJCQkJY3JlYXRlZCA9IGRpci5ta2RpcigpOwoJCQkJCWlmICghY3JlYXRlZCkgewoJCQkJCQlkaXIgPSBkaXIuZ2V0UGFyZW50RmlsZSgpOwoJCQkJCX0KCQkJCQluKys7CgkJCQl9CgkJCQlpZiAoIWNyZWF0ZWQpIHsKCQkJCQlTeXN0ZW0uZXJyLnByaW50bG4oIkNhbm5vdCBjcmVhdGUgIitsb2dEaXIrIiwgbG9nIGZpbGVzIHdpbGwgTk9UIGJlIHdyaXR0ZW4hIik7CgkJCQkJZGlyID0gSU5WQUxJRF9ESVI7CgkJCQl9CgkJCX0KCgkJCS8vIENyZWF0ZSBMb2cgZGlyCgkJCVN0cmluZ1tdIHN1YmRpcnMgPSAoUEFUQ0hfSUQgPT0gbnVsbCkKCQkJCT8gbmV3IFN0cmluZ1tdIHtMT0dfVkVSU0lPTiwgUlVOX0lEIH0KCQkJCTogbmV3IFN0cmluZ1tdIHtMT0dfVkVSU0lPTiwgUEFUQ0hfSUQsIFJVTl9JRCB9OwoJCQlmb3IgKGludCBpPTA7IGk8c3ViZGlycy5sZW5ndGg7IGkrKykgewoJCQkJZGlyID0gbmV3IEZpbGUoZGlyLCBzdWJkaXJzW2ldKTsKCQkJCWlmIChkaXIuZXhpc3RzKCkpIHsKCQkJCQlpZiAoIWRpci5pc0RpcmVjdG9yeSgpKSB7CgkJCQkJCVN5c3RlbS5lcnIucHJpbnRsbihkaXIuZ2V0UGF0aCgpKyIgaXMgbm90IGEgdmFsaWQgZGlyZWN0b3J5LCBsb2cgZmlsZXMgd2lsbCBOT1QgYmUgd3JpdHRlbiEiKTsKCQkJCQkJZGlyPSBJTlZBTElEX0RJUjsKCQkJCQkJYnJlYWs7CgkJCQkJfQoJCQkJfSBlbHNlIGlmICghZGlyLm1rZGlycygpKSB7CgkJCQkJU3lzdGVtLmVyci5wcmludGxuKCJDYW5ub3QgY3JlYXRlICIrZGlyLmdldFBhdGgoKSsiLCBsb2cgZmlsZXMgd2lsbCBOT1QgYmUgd3JpdHRlbiEiKTsKCQkJCQlkaXIgPSBJTlZBTElEX0RJUjsKCQkJCQlicmVhazsKCQkJCX0KCQkJfQoJCX0KCQlMT0dfRElSID0gZGlyOwoJfQoKCS8qKgoJICogQHBhcmFtIG5hbWUKCSAqLwoJcHVibGljIEZ1bGxTb3VyY2VXb3Jrc3BhY2VUZXN0cyhTdHJpbmcgbmFtZSkgewoJCXN1cGVyKG5hbWUpOwoJfQoKCS8qKgoJICogQ3JlYXRlIHRlc3Qgc3VpdGUgZm9yIGEgZ2l2ZW4gVGVzdENhc2UgY2xhc3MuCgkgKgoJICogVXNlIHRoaXMgbWV0aG9kIGZvciBhbGwgSkRUL0NvcmUgcGVyZm9ybWFuY2UgdGVzdCB1c2luZyBmdWxsIHNvdXJjZSB3b3Jrc3BhY2UuCgkgKiBBbGwgdGVzdCBjb3VudCBpcyBjb21wdXRlZCB0byBrbm93IHdoZW4gdGVzdHMgYXJlIGFib3V0IHRvIGJlIGZpbmlzaGVkLgoJICoKCSAqIEBwYXJhbSB0ZXN0Q2xhc3MgVGVzdENhc2UgdGVzdCBjbGFzcwoJICogQHJldHVybiB0ZXN0IHN1aXRlCgkgKi8KCXN0YXRpYyBUZXN0IGJ1aWxkU3VpdGUoQ2xhc3MgdGVzdENsYXNzKSB7CgoJCS8vIENyZWF0ZSB0ZXN0cwoJCVN0cmluZyBjbGFzc05hbWUgPSB0ZXN0Q2xhc3MuZ2V0TmFtZSgpOwoJCVRlc3RTdWl0ZSBzdWl0ZSA9IG5ldyBUZXN0U3VpdGUoY2xhc3NOYW1lKTsKCQlMaXN0IHRlc3RzID0gYnVpbGRUZXN0c0xpc3QodGVzdENsYXNzKTsKCQlpbnQgc2l6ZSA9IHRlc3RzLnNpemUoKTsKCQlURVNUU19OQU1FX0xJU1QgPSBuZXcgQXJyYXlMaXN0KHNpemUpOwoJCWZvciAoaW50IGk9MDsgaTxzaXplOyBpKyspIHsKCQkJRnVsbFNvdXJjZVdvcmtzcGFjZVRlc3RzIHRlc3QgPSAoRnVsbFNvdXJjZVdvcmtzcGFjZVRlc3RzKXRlc3RzLmdldChpKTsKCQkJc3VpdGUuYWRkVGVzdCh0ZXN0KTsKCQkJVEVTVFNfTkFNRV9MSVNULmFkZCh0ZXN0LmdldE5hbWUoKSk7CgkJfQoJCUFMTF9URVNUU19DT1VOVCArPSBzdWl0ZS50ZXN0Q291bnQoKTsKCgkJLy8gSW5pdCBsb2cgZGlyIGlmIG5lY2Vzc2FyeQoJCWlmIChMT0dfRElSID09IG51bGwpIHsKCQkJaWYgKFJVTl9JRCA9PSBudWxsKSB7CgkJCQlSVU5fSUQgPSBzdWl0ZVR5cGVTaG9ydE5hbWUodGVzdENsYXNzKTsKCQkJfQoJCQlpbml0TG9nRGlyKCk7CgkJfQoKCQkvLyBSZXR1cm4gY3JlYXRlZCB0ZXN0cwoJCXJldHVybiBzdWl0ZTsKCX0KCgkvKioKCSAqIENyZWF0ZSBwcmludCBzdHJlYW1zIChvbmUgZm9yIGVhY2ggdHlwZSBvZiBzdGF0aXN0aWMpLgoJICogTG9nIGZpbGUgbmFtZXMgaGF2ZSBhbGwgc2FtZSBwcmVmaXggYmFzZWQgb24gdGVzdCBjbGFzcyBuYW1lLAoJICogaW5jbHVkZSB0eXBlIG9mIHN0YXRpc3RpYyBzdG9yZWQgaW4gaXQgYW5kIGFsd2F5cyBoYXZlIGV4dGVuc2lvbiAiLmxvZyIuCgkgKgoJICogSWYgbG9nIGZpbGUgZG9lcyBub3QgZXhpc3QsIHRoZW4gYWRkIGNvbHVtbiBoZWFkZXJzIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIGZpbGUuCgkgKgoJICogVGhpcyBtZXRob2QgZG9lcyBub3RoaW5nIGlmIGxvZyBmaWxlcyBkaXJlY3RvcnkgaGFzIG5vdCBiZWVuIGluaXRpYWxpemVkCgkgKiAod2hpY2ggc2hvdWxkIGJlIHRoZSBjYXNlIG1vc3Qgb2YgdGltZXMgYW5kIGVzcGVjaWFsbHkgd2hpbGUgcnVubmluZyBuaWdodGx5L2ludGVncmF0aW9uIGJ1aWxkIHBlcmZvcm1hbmNlIHRlc3RzKS4KCSAqLwoJc3RhdGljIHZvaWQgY3JlYXRlUHJpbnRTdHJlYW0oQ2xhc3MgdGVzdENsYXNzLCBQcmludFN0cmVhbVtdIGxvZ1N0cmVhbXMsIGludCBjb3VudCwgU3RyaW5nIHByZWZpeCkgewoJCWlmIChMT0dfRElSICE9IG51bGwpIHsKCQkJZm9yIChpbnQgaT0wLCBsbj1ESU1fTkFNRVMubGVuZ3RoOyBpPGxuOyBpKyspIHsKCQkJCVN0cmluZyBzdWl0ZVR5cGVOYW1lID0gc3VpdGVUeXBlU2hvcnROYW1lKHRlc3RDbGFzcyk7CgkJCQlGaWxlIGxvZ0ZpbGUgPSBuZXcgRmlsZShMT0dfRElSLCBzdWl0ZVR5cGVOYW1lKydfJytESU1fTkFNRVNbaV0rIi5sb2ciKTsKCQkJCWlmIChUT1VDSCkgewoJCQkJCVN5c3RlbS5vdXQucHJpbnRsbigiTG9nIGZpbGUgIitsb2dGaWxlLmdldFBhdGgoKSsiIHdvdWxkIGJlIG9wZW5lZC4iKTsKCQkJCQlyZXR1cm47CgkJCQl9CgkJCQl0cnkgewoJCQkJCWJvb2xlYW4gZmlsZUV4aXN0ID0gbG9nRmlsZS5leGlzdHMoKTsKCQkJCQlpZiAobG9nU3RyZWFtc1tpXSAhPSBudWxsKSB7IC8vIGNsb3NpbmcgcHJldmlvdXMgc2VyaWVzOyBsYXN0IHNlcmllcyBpcyBjbG9zZWQgYnkgdGhlIHByb2Nlc3MKCQkJCQkJbG9nU3RyZWFtc1tpXS5jbG9zZSgpOwoJCQkJCX0KCQkJCQlsb2dTdHJlYW1zW2ldID0gbmV3IFByaW50U3RyZWFtKG5ldyBGaWxlT3V0cHV0U3RyZWFtKGxvZ0ZpbGUsIHRydWUpKTsKCQkJCQlpZiAobG9nU3RyZWFtc1tpXSAhPSBudWxsKSB7CgkJCQkJCWlmICghZmlsZUV4aXN0KSB7CgkJCQkJCQlsb2dTdHJlYW1zW2ldLnByaW50KCJEYXRlICBcdFRpbWUgIFx0Iik7CgkJCQkJCQlmb3IgKGludCBqPTA7IGo8Y291bnQ7IGorKykgewoJCQkJCQkJCVN0cmluZyB0ZXN0TmFtZSA9ICgoU3RyaW5nKSBURVNUU19OQU1FX0xJU1QuZ2V0KGopKS5zdWJzdHJpbmcoNCsocHJlZml4PT1udWxsPzA6cHJlZml4Lmxlbmd0aCgpKSk7IC8vIDQ9InRlc3QiLmxlbmd0aCgpCgkJCQkJCQkJbG9nU3RyZWFtc1tpXS5wcmludCh0ZXN0TmFtZSsnXHQnKTsKCQkJCQkJCX0KCQkJCQkJCWxvZ1N0cmVhbXNbaV0ucHJpbnRsbigiQ29tbWVudCIpOwoKCQkJCQkJfQoJCQkJCQkvLyBMb2cgZGF0ZSBhbmQgdGltZQoJCQkJCQlEYXRlIGRhdGUgPSBuZXcgRGF0ZShTeXN0ZW0uY3VycmVudFRpbWVNaWxsaXMoKSk7CgkJCQkJCWxvZ1N0cmVhbXNbaV0ucHJpbnQoRGF0ZUZvcm1hdC5nZXREYXRlSW5zdGFuY2UoMykuZm9ybWF0KGRhdGUpKydcdCcpOwoJCQkJCQlsb2dTdHJlYW1zW2ldLnByaW50KERhdGVGb3JtYXQuZ2V0VGltZUluc3RhbmNlKDMpLmZvcm1hdChkYXRlKSsnXHQnKTsKCQkJCQkJU3lzdGVtLm91dC5wcmludGxuKCJMb2cgZmlsZSAiK2xvZ0ZpbGUuZ2V0UGF0aCgpKyIgb3BlbmVkLiIpOwoJCQkJCX0gZWxzZSB7CgkJCQkJCVN5c3RlbS5lcnIucHJpbnRsbigiQ2Fubm90IG9wZW4gIitsb2dGaWxlLmdldFBhdGgoKSsiISEhIik7CgkJCQkJfQoJCQkJfSBjYXRjaCAoRmlsZU5vdEZvdW5kRXhjZXB0aW9uIGUpIHsKCQkJCQlTeXN0ZW0uZXJyLnByaW50bG4oIkNhbm5vdCBmaW5kIGZpbGUgIitsb2dGaWxlLmdldFBhdGgoKSsiISEhIik7CgkJCQl9CgkJCX0KCQl9Cgl9CgoJLyoKCSAqIFJldHVybnMgdGhlIE9TIHBhdGggdG8gdGhlIGRpcmVjdG9yeSB0aGF0IGNvbnRhaW5zIHRoaXMgcGx1Z2luLgoJICovCglzdGF0aWMgU3RyaW5nIGdldFBsdWdpbkRpcmVjdG9yeVBhdGgoKSB7CgkJdHJ5IHsKCQkJVVJMIHBsYXRmb3JtVVJMID0gUGxhdGZvcm0uZ2V0QnVuZGxlKCJvcmcuZWNsaXBzZS5qZHQuY29yZS50ZXN0cy5wZXJmb3JtYW5jZSIpLmdldEVudHJ5KCIvIik7CgkJCXJldHVybiBuZXcgRmlsZShGaWxlTG9jYXRvci50b0ZpbGVVUkwocGxhdGZvcm1VUkwpLmdldEZpbGUoKSkuZ2V0QWJzb2x1dGVQYXRoKCk7CgkJfSBjYXRjaCAoSU9FeGNlcHRpb24gZSkgewoJCQllLnByaW50U3RhY2tUcmFjZSgpOwoJCX0KCQlyZXR1cm4gbnVsbDsKCX0KCgkvKioKCSAqIFJldHVybiBhIHNob3J0IG5hbWUgZm9yIGEgZ2l2ZW4gc3VpdGUgdGVzdC4KCSAqIFR5cGljYWxseSByZW1vdmUgcHJlZml4ICJGdWxsU291cmNlV29ya3NwYWNlIiBhbmQgc3VmZml4ICJUZXN0IgoJICovCglwcm90ZWN0ZWQgc3RhdGljIFN0cmluZyBzdWl0ZVR5cGVTaG9ydE5hbWUoQ2xhc3MgdGVzdENsYXNzKSB7CgkJU3RyaW5nIGNsYXNzTmFtZSA9IHRlc3RDbGFzcy5nZXROYW1lKCk7CgkJaW50IHN0YXJ0SW5kZXggPSBjbGFzc05hbWUuaW5kZXhPZigiRnVsbFNvdXJjZVdvcmtzcGFjZSIpOwoJCWludCBlbmRJbmRleCA9IGNsYXNzTmFtZS5sYXN0SW5kZXhPZigiVGVzdCIpOwoJCWlmIChzdGFydEluZGV4IDwgMCkgcmV0dXJuIG51bGw7CgkJc3RhcnRJbmRleCArPSAiRnVsbFNvdXJjZVdvcmtzcGFjZSIubGVuZ3RoKCk7CgkJcmV0dXJuIGNsYXNzTmFtZS5zdWJzdHJpbmcoc3RhcnRJbmRleCwgZW5kSW5kZXgpOwoJfQoKCS8qKgoJICogTG9nIHRlc3QgcGVyZm9ybWFuY2UgcmVzdWx0IGFuZCBjbG9zZSBzdHJlYW0gaWYgaXQgd2FzIGxhc3Qgb25lLgoJICovCglwcm90ZWN0ZWQgdm9pZCBsb2dQZXJmUmVzdWx0KFByaW50U3RyZWFtW10gbG9nU3RyZWFtcywgaW50IGNvdW50KSB7CgkJaWYgKFRPVUNIKSByZXR1cm47CgoJCS8vIFBlcmZzIGNvbW1lbnQgYnVmZmVycwoJCWludCBsZW5ndGggPSBESU1fTkFNRVMubGVuZ3RoOwoJCVN0cmluZ1tdIGNvbW1lbnRzID0gbmV3IFN0cmluZ1tsZW5ndGhdOwoKCQkvLyBMb2cgcGVyZiByZXN1bHQKCQlib29sZWFuIGhhdmVTdGF0cyA9IEpkdENvcmVQZXJmb3JtYW5jZU1ldGVyLlNUQVRJU1RJQ1MgIT0gbnVsbDsKCQlpZiAoaGF2ZVN0YXRzKSB7CgkJCURhdGFQb2ludFtdIGRhdGFQb2ludHMgPSAoRGF0YVBvaW50W10pIEpkdENvcmVQZXJmb3JtYW5jZU1ldGVyLlNUQVRJU1RJQ1MuZ2V0KHRoaXMuc2NlbmFyaW9SZWFkYWJsZU5hbWUpOwoJCQlpZiAoZGF0YVBvaW50cyAhPSBudWxsKSB7CgkJCQlTdGF0aXN0aWNzIHN0YXRpc3RpY3MgPSBuZXcgU3RhdGlzdGljcyhkYXRhUG9pbnRzKTsKCQkJCWZvciAoaW50IGlkeD0wOyBpZHg8bGVuZ3RoOyBpZHgrKykgewoJCQkJCXN0b3JlRGltZW5zaW9uKGxvZ1N0cmVhbXMsIGNvbW1lbnRzLCBzdGF0aXN0aWNzLCBpZHgpOwoJCQkJfQoJCQl9IGVsc2UgewoJCQkJdHJ5IHsKCQkJCQloYXZlU3RhdHMgPSBmYWxzZTsKCQkJCQlUaHJlYWQuc2xlZXAoMTAwMCk7CgkJCQkJU3lzdGVtLmVyci5wcmludGxuKHRoaXMuc2NlbmFyaW9TaG9ydE5hbWUrIjogd2Ugc2hvdWxkIGhhdmUgc3RvcmVkIHN0YXRpc3RpY3MhIik7CgkJCQkJVGhyZWFkLnNsZWVwKDEwMDApOwoJCQkJfSBjYXRjaCAoSW50ZXJydXB0ZWRFeGNlcHRpb24gZSkgewoJCQkJCS8vIGRvIG5vdGhpbmcKCQkJCX0KCQkJfQoJCX0KCgkJLy8gVXBkYXRlIGNvbW1lbnQgYnVmZmVycwoJCVN0cmluZ0J1ZmZlcltdIHNjZW5hcmlvQ29tbWVudHMgPSAoU3RyaW5nQnVmZmVyW10pIFNDRU5BUklJX0NPTU1FTlQuZ2V0KGdldENsYXNzKCkpOwoJCWlmIChzY2VuYXJpb0NvbW1lbnRzID09IG51bGwpIHsKCQkJc2NlbmFyaW9Db21tZW50cyA9IG5ldyBTdHJpbmdCdWZmZXJbbGVuZ3RoXTsKCQkJU0NFTkFSSUlfQ09NTUVOVC5wdXQoZ2V0Q2xhc3MoKSwgc2NlbmFyaW9Db21tZW50cyk7CgkJfQoJCWZvciAoaW50IGk9MDsgaTxsZW5ndGg7IGkrKykgewoJCQlpZiAodGhpcy5zY2VuYXJpb0NvbW1lbnQgIT0gbnVsbCB8fCBjb21tZW50c1tpXSAhPSBudWxsKSB7CgkJCQlpZiAoc2NlbmFyaW9Db21tZW50c1tpXSA9PSBudWxsKSB7CgkJCQkJc2NlbmFyaW9Db21tZW50c1tpXSA9IG5ldyBTdHJpbmdCdWZmZXIoKTsKCQkJCX0gZWxzZSB7CgkJCQkJc2NlbmFyaW9Db21tZW50c1tpXS5hcHBlbmQoJyAnKTsKCQkJCX0KCQkJCWlmICh0aGlzLnNjZW5hcmlvQ29tbWVudCA9PSBudWxsKSB7CgkJCQkJc2NlbmFyaW9Db21tZW50c1tpXS5hcHBlbmQoIlsiK1RFU1RfUE9TSVRJT04rIl0iKTsKCQkJCX0gZWxzZSB7CgkJCQkJc2NlbmFyaW9Db21tZW50c1tpXS5hcHBlbmQodGhpcy5zY2VuYXJpb0NvbW1lbnQpOwoJCQkJfQoJCQkJaWYgKGNvbW1lbnRzW2ldICE9IG51bGwpIHsKCQkJCQlpZiAodGhpcy5zY2VuYXJpb0NvbW1lbnQgIT0gbnVsbCkgc2NlbmFyaW9Db21tZW50c1tpXS5hcHBlbmQoJywnKTsKCQkJCQlzY2VuYXJpb0NvbW1lbnRzW2ldLmFwcGVuZChjb21tZW50c1tpXSk7CgkJCQl9CgkJCX0KCQl9CgoJCS8vIENsb3NlIGxvZwoJCWlmIChjb3VudCA9PSAwKSB7CgkJCWZvciAoaW50IGk9MCwgbG49bG9nU3RyZWFtcy5sZW5ndGg7IGk8bG47IGkrKykgewoJCQkJaWYgKGxvZ1N0cmVhbXNbaV0gIT0gbnVsbCkgewoJCQkJCWlmIChoYXZlU3RhdHMpIHsKCQkJCQkJaWYgKHNjZW5hcmlvQ29tbWVudHNbaV0gIT0gbnVsbCkgewoJCQkJCQkJbG9nU3RyZWFtc1tpXS5wcmludChzY2VuYXJpb0NvbW1lbnRzW2ldLnRvU3RyaW5nKCkpOwoJCQkJCQl9CgkJCQkJCWxvZ1N0cmVhbXNbaV0ucHJpbnRsbigpOwoJCQkJCX0KCQkJCQlsb2dTdHJlYW1zW2ldLmNsb3NlKCk7CgkJCQl9CgkJCX0KCQkJVEVTVF9QT1NJVElPTiA9IDA7CgkJfQoJfQoKCXByaXZhdGUgdm9pZCBzdG9yZURpbWVuc2lvbihQcmludFN0cmVhbVtdIGxvZ1N0cmVhbXMsIFN0cmluZ1tdIGNvbW1lbnRzLCBTdGF0aXN0aWNzIHN0YXRpc3RpY3MsIGludCBpbmRleCkgewoJICAgIFN5c3RlbS5vdXQucHJpbnRsbigiCS0gIitzdGF0aXN0aWNzLnRvU3RyaW5nKGluZGV4KSk7CgkgICAgZG91YmxlIHN0ZGRldiA9IHN0YXRpc3RpY3MuZ2V0U3RkZGV2KGluZGV4KTsKCSAgICBkb3VibGUgYXZlcmFnZSA9IHN0YXRpc3RpY3MuZ2V0QXZlcmFnZShpbmRleCk7CgkgICAgbG9uZyBjb3VudCA9IHN0YXRpc3RpY3MuZ2V0Q291bnQoaW5kZXgpOwoJICAgIGRvdWJsZSBlcnJvciA9IHN0ZGRldiAvIE1hdGguc3FydChjb3VudCk7CgkgICAgaWYgKChlcnJvci9hdmVyYWdlKSA+IEVSUk9SX1RIUkVTSE9MRCkgewoJICAgIAkvL2lmIChsb2dTdHJlYW1zWzBdICE9IG51bGwpIGxvZ1N0cmVhbXNbMF0ucHJpbnQoIiciKTsgLy8gZGlzYWJsZSBvdmVyIHRocmVzaG9sZCByZXN1bHQgZm9yIHhscyB0YWJsZQoJICAgIAlTeXN0ZW0ub3V0LnByaW50bG4oIglXQVJOSU5HOiAiK0RJTV9OQU1FU1tpbmRleF0rIiBlcnJvciBpcyBvdmVyICIrRVJST1JfU1RSSU5HKyIlOiAiK3RoaXMuZDJGb3JtYXQuZm9ybWF0KHN0ZGRldikrIi9zcXJ0KCIrY291bnQrIik9IisgdGhpcy5wZXJjZW50Rm9ybWF0LmZvcm1hdChlcnJvci9hdmVyYWdlKSk7CgkgICAgCWNvbW1lbnRzW2luZGV4XSA9ICJlcnI9IiArIHRoaXMucGVyY2VudEZvcm1hdC5mb3JtYXQoZXJyb3IvYXZlcmFnZSk7CgkgICAgfQoJICAgIGlmIChsb2dTdHJlYW1zW2luZGV4XSAhPSBudWxsKSB7CgkgICAgCWxvZ1N0cmVhbXNbaW5kZXhdLnByaW50KCIiK3N0YXRpc3RpY3MuZ2V0U3VtKGluZGV4KSsiXHQiKTsKCSAgICB9CiAgICB9CgoJLyoqCgkgKiBQZXJmb3JtIGdjIHNldmVyYWwgdGltZXMgdG8gYmUgc3VyZSB0aGF0IGl0IHdvbid0IHRha2UgdGltZSB3aGlsZSBleGVjdXRpbmcgY3VycmVudCB0ZXN0LgoJICovCglwcm90ZWN0ZWQgdm9pZCBydW5HYygpIHsKCQlpbnQgaXRlcmF0aW9ucyA9IDA7CgkJbG9uZyBkZWx0YT0wLCBmcmVlPTA7CgkJZm9yIChpbnQgaT0wOyBpPE1BWF9HQzsgaSsrKSB7CgkJCWZyZWUgPSBSdW50aW1lLmdldFJ1bnRpbWUoKS5mcmVlTWVtb3J5KCk7CgkJCVN5c3RlbS5nYygpOwoJCQlkZWx0YSA9IFJ1bnRpbWUuZ2V0UnVudGltZSgpLmZyZWVNZW1vcnkoKSAtIGZyZWU7Ci8vCQkJaWYgKERFQlVHKSBTeXN0ZW0ub3V0LnByaW50bG4oIkxvb3AgZ2MgIisgKytpdGVyYXRpb25zICsgIiAoZnJlZT0iK2ZyZWUrIiwgZGVsdGE9IitkZWx0YSsiKSIpOwoJCQl0cnkgewoJCQkJVGhyZWFkLnNsZWVwKFRJTUVfR0MpOwoJCQl9IGNhdGNoIChJbnRlcnJ1cHRlZEV4Y2VwdGlvbiBlKSB7CgkJCQkvLyBkbyBub3RoaW5nCgkJCX0KCQl9CgkJaWYgKGl0ZXJhdGlvbnMgPT0gTUFYX0dDICYmIGRlbHRhID4gREVMVEFfR0MpIHsKCQkJLy8gcGVyaGFwcyBnYyB3YXMgbm90IHdlbGwgZXhlY3V0ZWQKCQkJU3lzdGVtLm91dC5wcmludGxuKCJXQVJOSU5HOiAiK3RoaXMuc2NlbmFyaW9TaG9ydE5hbWUrIiBzdGlsbCBnZXQgIitkZWx0YSsiIHVuZnJlZWFibGUgbWVtb3J5IChmcmVlPSIrZnJlZSsiLHRvdGFsPSIrUnVudGltZS5nZXRSdW50aW1lKCkudG90YWxNZW1vcnkoKSsiKSBhZnRlciAiK01BWF9HQysiIGdjLi4uIik7CgkJCXRyeSB7CgkJCQlUaHJlYWQuc2xlZXAoMTAwMCk7CgkJCX0gY2F0Y2ggKEludGVycnVwdGVkRXhjZXB0aW9uIGUpIHsKCQkJCS8vIGRvIG5vdGhpbmcKCQkJfQoJCX0KCX0KCgkvKioKCSAqIE92ZXJyaWRlIHN1cGVyIGltcGxlbWVudGF0aW9uIHRvOgoJICogPHVsPgoJICoJCTxsaT5zdG9yZSBzY2VuYXJpbyBuYW1lcyBhbmQgY29tbWVudCAob25lIHNjZW5hcmlvIHBlciB0ZXN0KTwvbGk+CgkgKgkJPGxpPmluaXQgd29ya3NwYWNlIGlmIGZpcnN0IHRlc3QgcnVuPC9saT4KCSAqCQk8bGk+aW5jcmVtZW50IHRlc3QgcG9zaXRpb248L2xpPgoJICoJPC91bD4KCSAqIEBzZWUgb3JnLmVjbGlwc2UudGVzdC5wZXJmb3JtYW5jZS5QZXJmb3JtYW5jZVRlc3RDYXNlI3NldFVwKCkKCSAqLwoJcHJvdGVjdGVkIHZvaWQgc2V0VXAoKSB0aHJvd3MgRXhjZXB0aW9uIHsKCQlzdXBlci5zZXRVcCgpOwoKCQkvLyBTdG9yZSBzY2VuYXJpbyByZWFkYWJsZSBuYW1lCgkJU3RyaW5nIHNjZW5hcmlvID0gUGVyZm9ybWFuY2UuZ2V0RGVmYXVsdCgpLmdldERlZmF1bHRTY2VuYXJpb0lkKHRoaXMpOwoJCXRoaXMuc2NlbmFyaW9SZWFkYWJsZU5hbWUgPSBzY2VuYXJpby5zdWJzdHJpbmcoc2NlbmFyaW8ubGFzdEluZGV4T2YoJy4nKSsxLCBzY2VuYXJpby5sZW5ndGgoKS0yKTsKCQl0aGlzLnNjZW5hcmlvU2hvcnROYW1lID0gdGhpcy5zY2VuYXJpb1JlYWRhYmxlTmFtZS5zdWJzdHJpbmcodGhpcy5zY2VuYXJpb1JlYWRhYmxlTmFtZS5sYXN0SW5kZXhPZignIycpKzUvKjErInRlc3QiLmxlbmd0aCgpKi8sIHRoaXMuc2NlbmFyaW9SZWFkYWJsZU5hbWUubGVuZ3RoKCkpOwoJCXRoaXMuc2NlbmFyaW9Db21tZW50ID0gbnVsbDsKCgkJLy8gU2V0IHRlc3RpbmcgZW52aXJvbm1lbnQgaWYgbnVsbAoJCWlmIChFTlYgPT0gbnVsbCkgewoJCQlFTlYgPSBuZXcgVGVzdGluZ0Vudmlyb25tZW50KCk7CgkJCUVOVi5vcGVuRW1wdHlXb3Jrc3BhY2UoKTsKCQkJc2V0VXBGdWxsU291cmNlV29ya3NwYWNlKCk7Ci8vCQkJaWYgKEpVTklUX1BST0pFQ1QgPT0gbnVsbCkgewovLwkJCQlzZXRVcEp1bml0UHJvamVjdCgpOwovLwkJCX0KCQl9CgoJCS8vIFZlcmlmeSB0aGF0IGFsbCB1c2VkIHByb2plY3RzIHdlcmUgZm91bmQgaW4gd2tzcAoJCWFzc2VydE5vdE51bGwoIldlIHNob3VsZCBoYXZlIGZvdW5kICIrSmF2YUNvcmUuUExVR0lOX0lEKyIgcHJvamVjdCBpbiB3b3Jrc3BhY2UhISEiLCBKRFRfQ09SRV9QUk9KRUNUKTsKCgkJLy8gSW5jcmVtZW50IHRlc3QgcG9zaXRpb24KCQlURVNUX1BPU0lUSU9OKys7CgoJCS8vIEFib3J0IGlmIG9ubHkgdG91Y2gKCQlpZiAoVE9VQ0gpIHsKCQkJU3RyaW5nIHRlc3RQcmludE5hbWUgPSAiJyIrdGhpcy5zY2VuYXJpb1Nob3J0TmFtZSsiJyB0ZXN0IjsKCQkJU3lzdGVtLm91dC5wcmludGxuKCJUb3VjaCAiK3Rlc3RQcmludE5hbWUrIiB0byB2ZXJpZnkgdGhhdCBpdCB3aWxsIHJ1biBjb3JyZWN0bHkuIik7CgkJCXRocm93IG5ldyBFcnJvcih0ZXN0UHJpbnROYW1lKyIgZXhlY3V0aW9uIGhhcyBiZWVuIGFib3J0ZWQhIik7CgkJfQoKCQkvLyBQcmludCB0ZXN0IG5hbWUKCQlTeXN0ZW0ub3V0LnByaW50bG4oIj09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09Iik7CgkJU3lzdGVtLm91dC5wcmludGxuKCJSdW5uaW5nICIrdGhpcy5zY2VuYXJpb1JlYWRhYmxlTmFtZSsiLi4uIik7CgoJCS8vIFRpbWUgbWVhc3VyaW5nCgkJdGhpcy50ZXN0RHVyYXRpb24gPSAwOwoJCXRoaXMubmJNZWFzdXJlcyA9IDA7CgoJCS8vIFdhaXQgMiBzZWNvbmRzCgkJVGhyZWFkLnNsZWVwKDIwMDApOwoJfQoKCS8qCgkgKiBTZXQgdXAgZnVsbCBzb3VyY2Ugd29ya3BzYWNlIGZyb20gemlwIGZpbGUuCgkgKi8KCXByaXZhdGUgdm9pZCBzZXRVcEZ1bGxTb3VyY2VXb3Jrc3BhY2UoKSB0aHJvd3MgSU9FeGNlcHRpb24sIENvcmVFeGNlcHRpb24gewoKCQkvLyBHZXQgd2tzcCBpbmZvCgkJSVdvcmtzcGFjZSB3b3Jrc3BhY2UgPSBSZXNvdXJjZXNQbHVnaW4uZ2V0V29ya3NwYWNlKCk7CgkJZmluYWwgSVdvcmtzcGFjZVJvb3Qgd29ya3NwYWNlUm9vdCA9IHdvcmtzcGFjZS5nZXRSb290KCk7CgkJU3RyaW5nIHRhcmdldFdvcmtzcGFjZVBhdGggPSB3b3Jrc3BhY2VSb290LmdldExvY2F0aW9uKCkudG9GaWxlKCkuZ2V0Q2Fub25pY2FsUGF0aCgpOwoKCQkvLyBNb2RpZnkgcmVzb3VyY2VzIHdvcmtzcGFjZSBwcmVmZXJlbmNlcyB0byBhdm9pZCBkaXN0dXJiaW5nIHRlc3RzIHdoaWxlIHJ1bm5pbmcgdGhlbQoJCUlFY2xpcHNlUHJlZmVyZW5jZXMgcmVzb3VyY2VzUHJlZmVyZW5jZXMgPSBJbnN0YW5jZVNjb3BlLklOU1RBTkNFLmdldE5vZGUoUmVzb3VyY2VzUGx1Z2luLlBJX1JFU09VUkNFUyk7CgkJcmVzb3VyY2VzUHJlZmVyZW5jZXMucHV0KFJlc291cmNlc1BsdWdpbi5QUkVGX0FVVE9fUkVGUkVTSCwgImZhbHNlIik7CgkJd29ya3NwYWNlLmdldERlc2NyaXB0aW9uKCkuc2V0U25hcHNob3RJbnRlcnZhbChMb25nLk1BWF9WQUxVRSk7CgkJd29ya3NwYWNlLmdldERlc2NyaXB0aW9uKCkuc2V0QXV0b0J1aWxkaW5nKGZhbHNlKTsKCgkJLy8gR2V0IHByb2plY3RzIGRpcmVjdG9yaWVzCgkJRmlsZSB3a3NwRGlyID0gbmV3IEZpbGUodGFyZ2V0V29ya3NwYWNlUGF0aCk7CgkJRnVsbFNvdXJjZVByb2plY3RzRmlsdGVyIGZpbHRlciA9IG5ldyBGdWxsU291cmNlUHJvamVjdHNGaWx0ZXIoKTsKCQlGaWxlW10gZGlyZWN0b3JpZXMgPSB3a3NwRGlyLmxpc3RGaWxlcyhmaWx0ZXIpOwoJCWxvbmcgc3RhcnQgPSBTeXN0ZW0uY3VycmVudFRpbWVNaWxsaXMoKTsKCQlpbnQgZGlyTGVuZ3RoID0gZGlyZWN0b3JpZXMubGVuZ3RoOwoJCWlmIChkaXJMZW5ndGggPCA2MikgewoJCQlTdHJpbmcgZnVsbFNvdXJjZVppcFBhdGggPSBnZXRQbHVnaW5EaXJlY3RvcnlQYXRoKCkgKyBGaWxlLnNlcGFyYXRvciArICJmdWxsLXNvdXJjZS1SM18wLnppcCI7CgkJCVN5c3RlbS5vdXQucHJpbnRsbigiVW56aXBwaW5nICIrZnVsbFNvdXJjZVppcFBhdGgpOwoJCQlTeXN0ZW0ub3V0LnByaW50KCIJaW4gIit0YXJnZXRXb3Jrc3BhY2VQYXRoKyIuLi4iKTsKCQkJVXRpbC51bnppcChmdWxsU291cmNlWmlwUGF0aCwgdGFyZ2V0V29ya3NwYWNlUGF0aCk7CgkJCVN5c3RlbS5vdXQucHJpbnRsbigiIGRvbmUgaW4gIisoU3lzdGVtLmN1cnJlbnRUaW1lTWlsbGlzKCktc3RhcnQpKyJtcy4iKTsKCQkJZGlyZWN0b3JpZXMgPSB3a3NwRGlyLmxpc3RGaWxlcyhmaWx0ZXIpOwoJCQlkaXJMZW5ndGggPSBkaXJlY3Rvcmllcy5sZW5ndGg7CgkJfQoKCQkvLyBJbml0IGVudmlyb25tZW50IHdpdGggZXhpc3RpbmcgcG9yamVjdHMKCQlTeXN0ZW0ub3V0LnByaW50KCJDcmVhdGUgYW5kIG9wZW4gcHJvamVjdHMgaW4gZW52aXJvbm1lbnQuLi4iKTsKCQlzdGFydCA9IFN5c3RlbS5jdXJyZW50VGltZU1pbGxpcygpOwoJCWZvciAoaW50IGkgPSAwOyBpIDwgZGlyTGVuZ3RoOyBpKyspIHsKCQkJU3RyaW5nIGRpck5hbWUgPSBkaXJlY3Rvcmllc1tpXS5nZXROYW1lKCk7CgkJCUlQcm9qZWN0IHByb2plY3QgPSB3b3Jrc3BhY2VSb290LmdldFByb2plY3QoZGlyTmFtZSk7CgkJCWlmIChwcm9qZWN0LmV4aXN0cygpKSB7CgkJCQlFTlYuYWRkUHJvamVjdChwcm9qZWN0KTsKCQkJfSBlbHNlIHsKCQkJCUVOVi5hZGRQcm9qZWN0KGRpck5hbWUpOwoJCQl9CgkJfQoJCVN5c3RlbS5vdXQucHJpbnRsbigiKCIrKFN5c3RlbS5jdXJyZW50VGltZU1pbGxpcygpLXN0YXJ0KSsibXMpIik7CgoJCS8vIENyZWF0ZSBsaWIgZW50cmllcyBmb3IgdGhlIEpES3MKCQlTdHJpbmcganJlTGliUGF0aCA9IEphdmFDb3JlLmdldENsYXNzcGF0aFZhcmlhYmxlKCJKUkVfTElCIikudG9PU1N0cmluZygpOwoJCVN5c3RlbS5vdXQucHJpbnQoIkNyZWF0ZSBsaWIgZW50cmllcyBmb3IgdGhlIEpES3MuLi4iKTsKCQlzdGFydCA9IFN5c3RlbS5jdXJyZW50VGltZU1pbGxpcygpOwoJCVN0cmluZ1tdIGpka0xpYnMgPSBVdGlsLmdldEphdmFDbGFzc0xpYnMoKTsKCQlpbnQgamRrTGlic0xlbmd0aCA9IGpka0xpYnMubGVuZ3RoOwoJCUlDbGFzc3BhdGhFbnRyeVtdIGpka0VudHJpZXMgPSBuZXcgSUNsYXNzcGF0aEVudHJ5W2pka0xpYnNMZW5ndGhdOwoJCWludCBqZGtFbnRyaWVzQ291bnQgPSAwOwoJCWZvciAoaW50IGk9MDsgaTxqZGtMaWJzTGVuZ3RoOyBpKyspIHsKCQkJaWYgKCFqZGtMaWJzW2ldLmVxdWFscyhqcmVMaWJQYXRoKSkgeyAvLyBkbyBub3QgaW5jbHVkZSBKUkVfTElCIGluIGFkZGl0aW9uYWwgSkRLIGVudHJpZXMKCQkJCWpka0VudHJpZXNbamRrRW50cmllc0NvdW50KytdID0gSmF2YUNvcmUubmV3TGlicmFyeUVudHJ5KG5ldyBQYXRoKGpka0xpYnNbaV0pLCBudWxsLCBudWxsKTsKCQkJfQoJCX0KCQlTeXN0ZW0ub3V0LnByaW50bG4oamRrTGlic0xlbmd0aCsiIGZvdW5kICgiKyhTeXN0ZW0uY3VycmVudFRpbWVNaWxsaXMoKS1zdGFydCkrIm1zKSIpOwoKCQkvLyBTZXQgY2xhc3NwYXRocyAod29ya2Fyb3VuZCBidWcgNzMyNTMgUHJvamVjdCByZWZlcmVuY2VzIG5vdCBzZXQgb24gcHJvamVjdCBvcGVuKQoJCVN5c3RlbS5vdXQucHJpbnQoIlNldCBwcm9qZWN0cyBjbGFzc3BhdGhzLi4uIik7CgkJc3RhcnQgPSBTeXN0ZW0uY3VycmVudFRpbWVNaWxsaXMoKTsKCQlBTExfUFJPSkVDVFMgPSBKYXZhQ29yZS5jcmVhdGUod29ya3NwYWNlUm9vdCkuZ2V0SmF2YVByb2plY3RzKCk7CgkJaW50IHByb2plY3RzTGVuZ3RoID0gQUxMX1BST0pFQ1RTLmxlbmd0aDsKCQlmb3IgKGludCBpID0gMDsgaSA8IHByb2plY3RzTGVuZ3RoOyBpKyspIHsKCQkJU3RyaW5nIHByb2plY3ROYW1lID0gQUxMX1BST0pFQ1RTW2ldLmdldEVsZW1lbnROYW1lKCk7CgkJCWlmIChCSUdfUFJPSkVDVF9OQU1FLmVxdWFscyhwcm9qZWN0TmFtZSkpIGNvbnRpbnVlOyAvLyB3aWxsIGJlIHNldCBsYXRlcgoJCQlpZiAoSmF2YUNvcmUuUExVR0lOX0lELmVxdWFscyhwcm9qZWN0TmFtZSkpIHsKCQkJCUpEVF9DT1JFX1BST0pFQ1QgPSBBTExfUFJPSkVDVFNbaV07Ci8vCQkJfSBlbHNlIGlmIChKVU5JVF9QUk9KRUNUX05BTUUuZXF1YWxzKHByb2plY3ROYW1lKSkgewovLwkJCQlKVU5JVF9QUk9KRUNUID0gQUxMX1BST0pFQ1RTW2ldOwoJCQl9CgoJCQkvLyBTZXQgamRrIGphcnMgb250byB0aGUgcHJvamVjdCBjbGFzc3BhdGgKCQkJSUNsYXNzcGF0aEVudHJ5W10gZW50cmllcyA9IEFMTF9QUk9KRUNUU1tpXS5nZXRSYXdDbGFzc3BhdGgoKTsKCQkJaW50IGVudHJpZXNMZW5ndGggPSBlbnRyaWVzLmxlbmd0aDsKCQkJdHJ5IHsKCQkJCVN5c3RlbS5hcnJheWNvcHkoZW50cmllcywgMCwgZW50cmllcyA9IG5ldyBJQ2xhc3NwYXRoRW50cnlbamRrRW50cmllc0NvdW50K2VudHJpZXNMZW5ndGhdLCAwLCBlbnRyaWVzTGVuZ3RoKTsKCQkJCVN5c3RlbS5hcnJheWNvcHkoamRrRW50cmllcywgMCwgZW50cmllcywgZW50cmllc0xlbmd0aCwgamRrRW50cmllc0NvdW50KTsKCQkJCUFMTF9QUk9KRUNUU1tpXS5zZXRSYXdDbGFzc3BhdGgoZW50cmllcywgbnVsbCk7CgkJCX0KCQkJY2F0Y2ggKEphdmFNb2RlbEV4Y2VwdGlvbiBqbWUpIHsKCQkJCS8vIHNraXAgbmFtZSBjb2xsaXNpb24gYXMgaXQgbWVhbnMgdGhhdCBKUkUgbGliIHdlcmUgYWxyZWFkeSBzZXQgb24gdGhlIGNsYXNzcGF0aAoJCQkJaWYgKGptZS5nZXRTdGF0dXMoKS5nZXRDb2RlKCkgIT0gSUphdmFNb2RlbFN0YXR1c0NvbnN0YW50cy5OQU1FX0NPTExJU0lPTikgewoJCQkJCXRocm93IGptZTsKCQkJCX0KCQkJfQoKCQkJLy8gTWFrZSBCaWcgcHJvamVjdCBkZXBlbmRlbnQgZnJvbSBqZHQuY29yZSBvbmUKLy8JCQlJQ2xhc3NwYXRoRW50cnlbXSBiaWdQcm9qZWN0RW50cmllcyA9IEJJR19QUk9KRUNULmdldFJhd0NsYXNzcGF0aCgpOwovLwkJCWludCBicGVMZW5ndGggPSBiaWdQcm9qZWN0RW50cmllcy5sZW5ndGg7Ci8vCQkJU3lzdGVtLmFycmF5Y29weShiaWdQcm9qZWN0RW50cmllcywgMCwgYmlnUHJvamVjdEVudHJpZXMgPSBuZXcgSUNsYXNzcGF0aEVudHJ5W2JwZUxlbmd0aCsxXSwgMCwgYnBlTGVuZ3RoKTsKLy8JCQliaWdQcm9qZWN0RW50cmllc1ticGVMZW5ndGhdID0gSmF2YUNvcmUubmV3UHJvamVjdEVudHJ5KEpEVF9DT1JFX1BST0pFQ1QuZ2V0UGF0aCgpKTsKCQl9CgkJU3lzdGVtLm91dC5wcmludGxuKCIoIisoU3lzdGVtLmN1cnJlbnRUaW1lTWlsbGlzKCktc3RhcnQpKyJtcykiKTsKCgkJLy8gSW5pdGlhbGl6ZSBQYXJzZXIgd29rcmluZyBjb3B5CgkJSUphdmFFbGVtZW50IGVsZW1lbnQgPSBKRFRfQ09SRV9QUk9KRUNULmZpbmRUeXBlKCJvcmcuZWNsaXBzZS5qZHQuaW50ZXJuYWwuY29tcGlsZXIucGFyc2VyLlBhcnNlciIpOwoJCWFzc2VydFRydWUoIlBhcnNlciBzaG91bGQgZXhpc3QgaW4gb3JnLmVjbGlwc2UuamR0LmNvcmUgcHJvamVjdCEiLCBlbGVtZW50ICE9IG51bGwgJiYgZWxlbWVudC5leGlzdHMoKSk7CgkJUEFSU0VSX1dPUktJTkdfQ09QWSA9IChJQ29tcGlsYXRpb25Vbml0KSBlbGVtZW50LmdldFBhcmVudCgpOwoJfQoKCS8qCgkgKiBDcmVhdGUgSlVuaXQgcHJvamVjdCBhbmQgYWRkIGl0IHRvIHRoZSB3b3Jrc3BhY2UKCSAqCglwcml2YXRlIHZvaWQgc2V0VXBKdW5pdFByb2plY3QoKSB0aHJvd3MgQ29yZUV4Y2VwdGlvbiwgSU9FeGNlcHRpb24gewoJCUlXb3Jrc3BhY2Ugd29ya3NwYWNlID0gUmVzb3VyY2VzUGx1Z2luLmdldFdvcmtzcGFjZSgpOwoJCUlXb3Jrc3BhY2VSb290IHdvcmtzcGFjZVJvb3QgPSB3b3Jrc3BhY2UuZ2V0Um9vdCgpOwoJCWZpbmFsIFN0cmluZyB0YXJnZXRXb3Jrc3BhY2VQYXRoID0gd29ya3NwYWNlUm9vdC5nZXRMb2NhdGlvbigpLnRvRmlsZSgpLmdldENhbm9uaWNhbFBhdGgoKTsKCgkJLy8gUHJpbnQgZm9yIGxvZyBpbiBjYXNlIG9mIHByb2plY3QgY3JlYXRpb24gdHJvdWJsZXMuLi4KCQlTeXN0ZW0ub3V0LnByaW50bG4oIkNyZWF0ZSAnIitKVU5JVF9QUk9KRUNUX05BTUUrIicgcHJvamVjdCBpbiAiK3dvcmtzcGFjZVJvb3QuZ2V0TG9jYXRpb24oKSsiOiIpOwoJCWxvbmcgc3RhcnQgPSBTeXN0ZW0uY3VycmVudFRpbWVNaWxsaXMoKTsKCgkJLy8gUHJpbnQgZm9yIGxvZyBpbiBjYXNlIG9mIHByb2plY3QgY3JlYXRpb24gdHJvdWJsZXMuLi4KCQlTdHJpbmcgZ2VuZXJpY3NaaXBQYXRoID0gZ2V0UGx1Z2luRGlyZWN0b3J5UGF0aCgpICsgRmlsZS5zZXBhcmF0b3IgKyBKVU5JVF9QUk9KRUNUX05BTUUgKyAic3JjLnppcCI7CgkJc3RhcnQgPSBTeXN0ZW0uY3VycmVudFRpbWVNaWxsaXMoKTsKCQlTeXN0ZW0ub3V0LnByaW50bG4oIlVuemlwcGluZyAiK2dlbmVyaWNzWmlwUGF0aCk7CgkJU3lzdGVtLm91dC5wcmludCgiCWluICIrdGFyZ2V0V29ya3NwYWNlUGF0aCsiLi4uIik7CgoJCS8vIFVuemlwIGZpbGUKCQlVdGlsLnVuemlwKGdlbmVyaWNzWmlwUGF0aCwgdGFyZ2V0V29ya3NwYWNlUGF0aCk7CgkJU3lzdGVtLm91dC5wcmludGxuKCIgIisoU3lzdGVtLmN1cnJlbnRUaW1lTWlsbGlzKCktc3RhcnQpKyJtcy4iKTsKCgkJLy8gQWRkIHByb2plY3QgdG8gd29ya3NwYWNlCgkJU3lzdGVtLm91dC5wcmludCgiCS0gYWRkIHByb2plY3QgdG8gZnVsbCBzb3VyY2Ugd29ya3NwYWNlLi4uIik7CgkJc3RhcnQgPSBTeXN0ZW0uY3VycmVudFRpbWVNaWxsaXMoKTsKCQlFTlYuYWRkUHJvamVjdChKVU5JVF9QUk9KRUNUX05BTUUpOwoJCUpVTklUX1BST0pFQ1QgPSBjcmVhdGVKYXZhUHJvamVjdChKVU5JVF9QUk9KRUNUX05BTUUsIG5ldyBTdHJpbmdbXXsgInNyYyIgfSwgImJpbiIsICIxLjUiKTsKCQlKVU5JVF9QUk9KRUNULnNldFJhd0NsYXNzcGF0aChKVU5JVF9QUk9KRUNULmdldFJlc29sdmVkQ2xhc3NwYXRoKHRydWUpLCBudWxsKTsKCgkJLy8gUHJpbnQgZm9yIGxvZyBpbiBjYXNlIG9mIHByb2plY3QgY3JlYXRpb24gdHJvdWJsZXMuLi4KCQlTeXN0ZW0ub3V0LnByaW50bG4oIiAiKyhTeXN0ZW0uY3VycmVudFRpbWVNaWxsaXMoKS1zdGFydCkrIm1zLiIpOwoJfQoJKi8KCgkvKioKCSAqIEBkZXByZWNhdGVkIFVzZSB7QGxpbmsgI3RhZ0FzR2xvYmFsU3VtbWFyeShTdHJpbmcsRGltZW5zaW9uLGJvb2xlYW4pfSBpbnN0ZWFkCgkgKi8KCXB1YmxpYyB2b2lkIHRhZ0FzR2xvYmFsU3VtbWFyeShTdHJpbmcgc2hvcnROYW1lLCBEaW1lbnNpb24gZGltZW5zaW9uKSB7CgkJdGFnQXNHbG9iYWxTdW1tYXJ5KHNob3J0TmFtZSwgZGltZW5zaW9uLCBmYWxzZSk7IC8vIGRvIE5PVCBwdXQgaW4gZmluZ2VycHJpbnQKCX0KCXByb3RlY3RlZCB2b2lkIHRhZ0FzR2xvYmFsU3VtbWFyeShTdHJpbmcgc2hvcnROYW1lLCBib29sZWFuIGZpbmdlcnByaW50KSB7CgkJdGFnQXNHbG9iYWxTdW1tYXJ5KHNob3J0TmFtZSwgRGltZW5zaW9uLkVMQVBTRURfUFJPQ0VTUywgZmluZ2VycHJpbnQpOwoJfQoJcHJvdGVjdGVkIHZvaWQgdGFnQXNHbG9iYWxTdW1tYXJ5KFN0cmluZyBzaG9ydE5hbWUsIERpbWVuc2lvbiBkaW1lbnNpb24sIGJvb2xlYW4gZmluZ2VycHJpbnQpIHsKCQlpZiAoREVCVUcpIFN5c3RlbS5vdXQucHJpbnRsbihzaG9ydE5hbWUpOwoJCWlmIChmaW5nZXJwcmludCkgc3VwZXIudGFnQXNHbG9iYWxTdW1tYXJ5KHNob3J0TmFtZSwgZGltZW5zaW9uKTsKCX0KCS8qKgoJICogQGRlcHJlY2F0ZWQgV2UgZG8gbm90IHVzZSB0aGlzIG1ldGhvZC4uLgoJICovCglwdWJsaWMgdm9pZCB0YWdBc0dsb2JhbFN1bW1hcnkoU3RyaW5nIHNob3J0TmFtZSwgRGltZW5zaW9uW10gZGltZW5zaW9ucykgewoJCVN5c3RlbS5vdXQucHJpbnRsbigiRVJST1I6IHRhZ0FzR2xvYmFsU3VtbWFyeShTdHJpbmcsIERpbWVuc2lvbltdKSBpcyBub3QgaW1wbGVtZW50ZWQhISEiKTsKCX0KCS8qKgoJICogQGRlcHJlY2F0ZWQgVXNlIHtAbGluayAjdGFnQXNTdW1tYXJ5KFN0cmluZyxEaW1lbnNpb24sYm9vbGVhbil9IGluc3RlYWQKCSAqLwoJcHVibGljIHZvaWQgdGFnQXNTdW1tYXJ5KFN0cmluZyBzaG9ydE5hbWUsIERpbWVuc2lvbiBkaW1lbnNpb24pIHsKCQl0YWdBc1N1bW1hcnkoc2hvcnROYW1lLCBkaW1lbnNpb24sIGZhbHNlKTsgLy8gZG8gTk9UIHB1dCBpbiBmaW5nZXJwcmludAoJfQoJcHJvdGVjdGVkIHZvaWQgdGFnQXNTdW1tYXJ5KFN0cmluZyBzaG9ydE5hbWUsIGJvb2xlYW4gZmluZ2VycHJpbnQpIHsKCQl0YWdBc1N1bW1hcnkoc2hvcnROYW1lLCBEaW1lbnNpb24uRUxBUFNFRF9QUk9DRVNTLCBmaW5nZXJwcmludCk7Cgl9CglwdWJsaWMgdm9pZCB0YWdBc1N1bW1hcnkoU3RyaW5nIHNob3J0TmFtZSwgRGltZW5zaW9uIGRpbWVuc2lvbiwgYm9vbGVhbiBmaW5nZXJwcmludCkgewoJCWlmIChERUJVRykgU3lzdGVtLm91dC5wcmludGxuKHNob3J0TmFtZSk7CgkJaWYgKGZpbmdlcnByaW50KSBzdXBlci50YWdBc1N1bW1hcnkoc2hvcnROYW1lLCBkaW1lbnNpb24pOwoJfQoJLyoqCgkgKiBAZGVwcmVjYXRlZCBXZSBkbyBub3QgdXNlIHRoaXMgbWV0aG9kLi4uCgkgKi8KCXB1YmxpYyB2b2lkIHRhZ0FzU3VtbWFyeShTdHJpbmcgc2hvcnROYW1lLCBEaW1lbnNpb25bXSBkaW1lbnNpb25zKSB7CgkJU3lzdGVtLm91dC5wcmludGxuKCJFUlJPUjogdGFnQXNHbG9iYWxTdW1tYXJ5KFN0cmluZywgRGltZW5zaW9uW10pIGlzIG5vdCBpbXBsZW1lbnRlZCEhISIpOwoJfQoJcHVibGljIHZvaWQgdGFnQXNTdW1tYXJ5KFN0cmluZyBzaG9ydE5hbWUsIERpbWVuc2lvbltdIGRpbWVuc2lvbnMsIGJvb2xlYW4gZmluZ2VycHJpbnQpIHsKCQlpZiAoREVCVUcpIFN5c3RlbS5vdXQucHJpbnRsbihzaG9ydE5hbWUpOwoJCWlmIChmaW5nZXJwcmludCkgc3VwZXIudGFnQXNTdW1tYXJ5KHNob3J0TmFtZSwgZGltZW5zaW9ucyk7Cgl9CglwdWJsaWMgdm9pZCBzdGFydE1lYXN1cmluZygpIHsKCQlpZiAoUFJJTlQgJiYgdGhpcy5uYk1lYXN1cmVzPT0wKSBTeXN0ZW0ub3V0LnByaW50bG4oIglNZWFzdXJlcyAofkVsYXBzZWQgUHJvY2VzcyB0aW1lKToiKTsKCQl0aGlzLnN0YXJ0TWVhc3VyaW5nID0gU3lzdGVtLmN1cnJlbnRUaW1lTWlsbGlzKCk7CgkJc3VwZXIuc3RhcnRNZWFzdXJpbmcoKTsKCX0KCXB1YmxpYyB2b2lkIHN0b3BNZWFzdXJpbmcoKSB7CgkJc3VwZXIuc3RvcE1lYXN1cmluZygpOwoJCXRoaXMubmJNZWFzdXJlcysrOwoJCWxvbmcgZHVyYXRpb24gPSBTeXN0ZW0uY3VycmVudFRpbWVNaWxsaXMoKSAtIHRoaXMuc3RhcnRNZWFzdXJpbmc7CgkJaWYgKFBSSU5UKSBTeXN0ZW0ub3V0LnByaW50bG4oIgkJLSBusCAiK3RoaXMubmJNZWFzdXJlcysiOiAiK2R1cmF0aW9uKyJtcyIpOwoJCXRoaXMudGVzdER1cmF0aW9uICs9IGR1cmF0aW9uOwoJfQoJcHVibGljIHZvaWQgY29tbWl0TWVhc3VyZW1lbnRzKCkgewoJCWlmIChQUklOVCkgewoJCQlTeXN0ZW0ub3V0LnByaW50bG4oIglUZXN0IGR1cmF0aW9uID0gIit0aGlzLnRlc3REdXJhdGlvbisibXMiKTsKCQkJU3lzdGVtLm91dC5wcmludGxuKCIJVGltZSBhdmVyYWdlID0gIisoKCh0aGlzLnRlc3REdXJhdGlvbioxMDAwKS90aGlzLm5iTWVhc3VyZXMpLzEwMDApKTsKCQl9CgkJc3VwZXIuY29tbWl0TWVhc3VyZW1lbnRzKCk7Cgl9CgkvKioKCSAqIE92ZXJyaWRlIHN1cGVyIGltcGxlbWVudGF0aW9uIHRvOgoJICoJPHVsPgoJICoJCTxsaT5kZWNyZW1lbnQgYWxsIHRlc3QgY291bnQ8L2xpPgoJICoJCTxsaT5yZXNldCB3b3Jrc3BhY2UgYW5kIGJhY2sgdG8gaW5pdGlhbCBvcHRpb25zIGlmIGxhc3QgdGVzdCBydW48L2xpPgoJICo8L3VsPgoJICogQHNlZSBvcmcuZWNsaXBzZS50ZXN0LnBlcmZvcm1hbmNlLlBlcmZvcm1hbmNlVGVzdENhc2UjdGVhckRvd24oKQoJICovCglwcm90ZWN0ZWQgdm9pZCB0ZWFyRG93bigpIHRocm93cyBFeGNlcHRpb24gewoJCUFMTF9URVNUU19DT1VOVC0tOwoJCWlmIChBTExfVEVTVFNfQ09VTlQgPT0gMCkgewovLwkJCUVOVi5yZXNldFdvcmtzcGFjZSgpOwoJCQlKYXZhQ29yZS5zZXRPcHRpb25zKElOSVRJQUxfT1BUSU9OUyk7CgkJfQoJCXN1cGVyLnRlYXJEb3duKCk7Cgl9CgoJLyoKCSAqIERlbGV0ZSBhIGRpcmVjdG9yeSBmcm9tIGZpbGUgc3lzdGVtLgoJICogQHBhcmFtIGRpcmVjdG9yeQoJICoKCXByb3RlY3RlZCB2b2lkIGNsZWFudXBEaXJlY3RvcnkoRmlsZSBkaXJlY3RvcnkpIHsKCQlpZiAoIWRpcmVjdG9yeS5pc0RpcmVjdG9yeSgpIHx8ICFkaXJlY3RvcnkuZXhpc3RzKCkpIHsKCQkJcmV0dXJuOwoJCX0KCQlTdHJpbmdbXSBmaWxlTmFtZXMgPSBkaXJlY3RvcnkubGlzdCgpOwoJCWZvciAoaW50IGkgPSAwOyBpIDwgZmlsZU5hbWVzLmxlbmd0aDsgaSsrKSB7CgkJCUZpbGUgZmlsZSA9IG5ldyBGaWxlKGRpcmVjdG9yeSwgZmlsZU5hbWVzW2ldKTsKCQkJaWYgKGZpbGUuaXNEaXJlY3RvcnkoKSkgewoJCQkJY2xlYW51cERpcmVjdG9yeShmaWxlKTsKCQkJfSBlbHNlIHsKCQkJCWlmICghZmlsZS5kZWxldGUoKSkKCQkJCQlTeXN0ZW0ub3V0LnByaW50bG4oIkNvdWxkIG5vdCBkZWxldGUgZmlsZSAiICsgZmlsZS5nZXRQYXRoKCkpOyAvLyROT04tTkxTLTEkCgkJCX0KCQl9CgkJaWYgKCFkaXJlY3RvcnkuZGVsZXRlKCkpCgkJCVN5c3RlbS5vdXQucHJpbnRsbigiQ291bGQgbm90IGRlbGV0ZSBkaXJlY3RvcnkgIiArIGRpcmVjdG9yeS5nZXRQYXRoKCkpOyAvLyROT04tTkxTLTEkCgl9CgkqLwoKCS8qCgkgKiBDbGVhciBnaXZlbiBvcHRpb25zCgkgKi8KCU1hcCBjbGVhck9wdGlvbnMoTWFwIG9wdGlvbnMpIHsKCQkvLyB0dXJuIGFsbCBlcnJvcnMgYW5kIHdhcm5pbmdzIGludG8gaWdub3JlLiBUaGUgY3VzdG9taXphYmxlIHNldCBvZiBjb21waWxlcgoJCS8vIG9wdGlvbnMgb25seSBjb250YWlucyBhZGRpdGlvbmFsIEVjbGlwc2Ugb3B0aW9ucy4gVGhlIHN0YW5kYXJkIEpESyBjb21waWxlcgoJCS8vIG9wdGlvbnMgY2FuJ3QgYmUgY2hhbmdlZCBhbnl3YXkuCgkJZm9yIChJdGVyYXRvciBpdGVyPSBvcHRpb25zLmtleVNldCgpLml0ZXJhdG9yKCk7IGl0ZXIuaGFzTmV4dCgpOykgewoJCQlTdHJpbmcga2V5PSAoU3RyaW5nKWl0ZXIubmV4dCgpOwoJCQlTdHJpbmcgdmFsdWU9IChTdHJpbmcpb3B0aW9ucy5nZXQoa2V5KTsKCQkJaWYgKCJlcnJvciIuZXF1YWxzKHZhbHVlKSB8fCAid2FybmluZyIuZXF1YWxzKHZhbHVlKSkgeyAgLy8kTk9OLU5MUy0xJC8vJE5PTi1OTFMtMiQKCQkJCS8vIFN5c3RlbS5vdXQucHJpbnRsbigiSWdub3JpbmcgLSAiICsga2V5KTsKCQkJCW9wdGlvbnMucHV0KGtleSwgImlnbm9yZSIpOyAvLyROT04tTkxTLTEkCgkJCX0gZWxzZSBpZiAoImVuYWJsZWQiLmVxdWFscyh2YWx1ZSkpIHsKCQkJCS8vIFN5c3RlbS5vdXQucHJpbnRsbigiCS0gZGlzYWJsaW5nICIgKyBrZXkpOwoJCQkJb3B0aW9ucy5wdXQoa2V5LCAiZGlzYWJsZWQiKTsKCQkJfQoJCX0KCQlvcHRpb25zLnB1dChKYXZhQ29yZS5DT01QSUxFUl9UQVNLX1RBR1MsICIiKTsKCQlyZXR1cm4gb3B0aW9uczsKCX0KCgkvKioKCSAqIEBzZWUgb3JnLmVjbGlwc2UuamR0LmNvcmUudGVzdHMubW9kZWwuQWJzdHJhY3RKYXZhTW9kZWxUZXN0cyNjcmVhdGVKYXZhUHJvamVjdChTdHJpbmcsIFN0cmluZ1tdLCBTdHJpbmdbXSwgU3RyaW5nW11bXSwgU3RyaW5nW11bXSwgU3RyaW5nW10sIFN0cmluZ1tdW10sIFN0cmluZ1tdW10sIGJvb2xlYW5bXSwgU3RyaW5nLCBTdHJpbmdbXSwgU3RyaW5nW11bXSwgU3RyaW5nW11bXSwgU3RyaW5nKQoJICovCglwcm90ZWN0ZWQgSUphdmFQcm9qZWN0IGNyZWF0ZUphdmFQcm9qZWN0KGZpbmFsIFN0cmluZyBwcm9qZWN0TmFtZSwgZmluYWwgU3RyaW5nW10gc291cmNlRm9sZGVycywgZmluYWwgU3RyaW5nIHByb2plY3RPdXRwdXQsIGZpbmFsIFN0cmluZyBjb21wbGlhbmNlKSB0aHJvd3MgQ29yZUV4Y2VwdGlvbiB7CgkJZmluYWwgSUphdmFQcm9qZWN0W10gcmVzdWx0ID0gbmV3IElKYXZhUHJvamVjdFsxXTsKCQlJV29ya3NwYWNlUnVubmFibGUgY3JlYXRlID0gbmV3IElXb3Jrc3BhY2VSdW5uYWJsZSgpIHsKCQkJcHVibGljIHZvaWQgcnVuKElQcm9ncmVzc01vbml0b3IgbW9uaXRvcikgdGhyb3dzIENvcmVFeGNlcHRpb24gewoKCQkJCS8vIGNyZWF0ZSBjbGFzc3BhdGggZW50cmllcwoJCQkJSVByb2plY3QgcHJvamVjdCA9IEVOVi5nZXRQcm9qZWN0KHByb2plY3ROYW1lKTsKCQkJCUlQYXRoIHByb2plY3RQYXRoID0gcHJvamVjdC5nZXRGdWxsUGF0aCgpOwoJCQkJaW50IHNvdXJjZUxlbmd0aCA9IHNvdXJjZUZvbGRlcnMgPT0gbnVsbCA/IDAgOiBzb3VyY2VGb2xkZXJzLmxlbmd0aDsKCQkJCUlDbGFzc3BhdGhFbnRyeVtdIGVudHJpZXMgPSBuZXcgSUNsYXNzcGF0aEVudHJ5W3NvdXJjZUxlbmd0aCsxXTsKCQkJCWZvciAoaW50IGk9IDA7IGkgPCBzb3VyY2VMZW5ndGg7IGkrKykgewoJCQkJCUlQYXRoIHNvdXJjZVBhdGggPSBuZXcgUGF0aChzb3VyY2VGb2xkZXJzW2ldKTsKCQkJCQlpbnQgc2VnbWVudENvdW50ID0gc291cmNlUGF0aC5zZWdtZW50Q291bnQoKTsKCQkJCQlpZiAoc2VnbWVudENvdW50ID4gMCkgewoJCQkJCQkvLyBjcmVhdGUgZm9sZGVyIGFuZCBpdHMgcGFyZW50cwoJCQkJCQlJQ29udGFpbmVyIGNvbnRhaW5lciA9IHByb2plY3Q7CgkJCQkJCWZvciAoaW50IGogPSAwOyBqIDwgc2VnbWVudENvdW50OyBqKyspIHsKCQkJCQkJCUlGb2xkZXIgZm9sZGVyID0gY29udGFpbmVyLmdldEZvbGRlcihuZXcgUGF0aChzb3VyY2VQYXRoLnNlZ21lbnQoaikpKTsKCQkJCQkJCWlmICghZm9sZGVyLmV4aXN0cygpKSB7CgkJCQkJCQkJZm9sZGVyLmNyZWF0ZSh0cnVlLCB0cnVlLCBudWxsKTsKCQkJCQkJCX0KCQkJCQkJCWNvbnRhaW5lciA9IGZvbGRlcjsKCQkJCQkJfQoJCQkJCX0KCQkJCQkvLyBjcmVhdGUgc291cmNlIGVudHJ5CgkJCQkJZW50cmllc1tpXSA9CgkJCQkJCUphdmFDb3JlLm5ld1NvdXJjZUVudHJ5KAoJCQkJCQkJcHJvamVjdFBhdGguYXBwZW5kKHNvdXJjZVBhdGgpLAoJCQkJCQkJbmV3IElQYXRoWzBdLAoJCQkJCQkJbmV3IElQYXRoWzBdLAoJCQkJCQkJbnVsbAoJCQkJCQkpOwoJCQkJfQoKCQkJCS8vIEFkZCBKUkVfTElCIGVudHJ5CgkJCQllbnRyaWVzW3NvdXJjZUxlbmd0aF0gPSBKYXZhQ29yZS5uZXdWYXJpYWJsZUVudHJ5KAoJCQkJCQkJCW5ldyBQYXRoKCJKUkVfTElCIiksCgkJCQkJCQkJbnVsbCwKCQkJCQkJCQludWxsKTsKCgkJCQkvLyBjcmVhdGUgcHJvamVjdCdzIG91dHB1dCBmb2xkZXIKCQkJCUlQYXRoIG91dHB1dFBhdGggPSBuZXcgUGF0aChwcm9qZWN0T3V0cHV0KTsKCQkJCWlmIChvdXRwdXRQYXRoLnNlZ21lbnRDb3VudCgpID4gMCkgewoJCQkJCUlGb2xkZXIgb3V0cHV0ID0gcHJvamVjdC5nZXRGb2xkZXIob3V0cHV0UGF0aCk7CgkJCQkJaWYgKCFvdXRwdXQuZXhpc3RzKCkpIHsKCQkJCQkJb3V0cHV0LmNyZWF0ZSh0cnVlLCB0cnVlLCBudWxsKTsKCQkJCQl9CgkJCQl9CgoJCQkJLy8gc2V0IGNsYXNzcGF0aCBhbmQgb3V0cHV0IGxvY2F0aW9uCgkJCQlJSmF2YVByb2plY3QgamF2YVByb2plY3QgPSBFTlYuZ2V0SmF2YVByb2plY3QocHJvamVjdE5hbWUpOwoJCQkJamF2YVByb2plY3Quc2V0UmF3Q2xhc3NwYXRoKGVudHJpZXMsIHByb2plY3RQYXRoLmFwcGVuZChvdXRwdXRQYXRoKSwgbnVsbCk7CgoJCQkJLy8gc2V0IGNvbXBsaWFuY2UgbGV2ZWwgb3B0aW9ucwoJCQkJaWYgKCIxLjUiLmVxdWFscyhjb21wbGlhbmNlKSkgewoJCQkJCU1hcCBvcHRpb25zID0gbmV3IEhhc2hNYXAoKTsKCQkJCQlvcHRpb25zLnB1dChDb21waWxlck9wdGlvbnMuT1BUSU9OX0NvbXBsaWFuY2UsIENvbXBpbGVyT3B0aW9ucy5WRVJTSU9OXzFfNSk7CgkJCQkJb3B0aW9ucy5wdXQoQ29tcGlsZXJPcHRpb25zLk9QVElPTl9Tb3VyY2UsIENvbXBpbGVyT3B0aW9ucy5WRVJTSU9OXzFfNSk7CgkJCQkJb3B0aW9ucy5wdXQoQ29tcGlsZXJPcHRpb25zLk9QVElPTl9UYXJnZXRQbGF0Zm9ybSwgQ29tcGlsZXJPcHRpb25zLlZFUlNJT05fMV81KTsKCQkJCQlqYXZhUHJvamVjdC5zZXRPcHRpb25zKG9wdGlvbnMpOwoJCQkJfQoKCQkJCXJlc3VsdFswXSA9IGphdmFQcm9qZWN0OwoJCQl9CgkJfTsKCQlSZXNvdXJjZXNQbHVnaW4uZ2V0V29ya3NwYWNlKCkucnVuKGNyZWF0ZSwgbnVsbCk7CgkJcmV0dXJuIHJlc3VsdFswXTsKCX0KCglwcml2YXRlIHZvaWQgY29sbGVjdEFsbEZpbGVzKEZpbGUgcm9vdCwgQXJyYXlMaXN0IGNvbGxlY3RvciwgRmlsZUZpbHRlciBmaWxlRmlsdGVyKSB7CgkJRmlsZVtdIGZpbGVzID0gcm9vdC5saXN0RmlsZXMoZmlsZUZpbHRlcik7CgkJZm9yIChpbnQgaSA9IDA7IGkgPCBmaWxlcy5sZW5ndGg7IGkrKykgewoJCQlmaW5hbCBGaWxlIGN1cnJlbnRGaWxlID0gZmlsZXNbaV07CgkJCWlmIChjdXJyZW50RmlsZS5pc0RpcmVjdG9yeSgpKSB7CgkJCQljb2xsZWN0QWxsRmlsZXMoY3VycmVudEZpbGUsIGNvbGxlY3RvciwgZmlsZUZpbHRlcik7CgkJCX0gZWxzZSB7CgkJCQljb2xsZWN0b3IuYWRkKGN1cnJlbnRGaWxlKTsKCQkJfQoJCX0KCX0KCglwcm90ZWN0ZWQgRmlsZVtdIGdldEFsbEZpbGVzKEZpbGUgcm9vdCwgRmlsZUZpbHRlciBmaWxlRmlsdGVyKSB7CgkJQXJyYXlMaXN0IGZpbGVzID0gbmV3IEFycmF5TGlzdCgpOwoJCWlmIChyb290LmlzRGlyZWN0b3J5KCkpIHsKCQkJY29sbGVjdEFsbEZpbGVzKHJvb3QsIGZpbGVzLCBmaWxlRmlsdGVyKTsKCQkJRmlsZVtdIHJlc3VsdCA9IG5ldyBGaWxlW2ZpbGVzLnNpemUoKV07CgkJCWZpbGVzLnRvQXJyYXkocmVzdWx0KTsKCQkJcmV0dXJuIHJlc3VsdDsKCQl9IGVsc2UgewoJCQlyZXR1cm4gbnVsbDsKCQl9Cgl9CgoJLyoqCgkgKiBSZXR1cm5zIHRoZSBzcGVjaWZpZWQgY29tcGlsYXRpb24gdW5pdCBpbiB0aGUgZ2l2ZW4gcHJvamVjdCwgcm9vdCwgYW5kCgkgKiBwYWNrYWdlIGZyYWdtZW50IG9yIDxjb2RlPm51bGw8L2NvZGU+IGlmIGl0IGRvZXMgbm90IGV4aXN0LgoJICovCglwcm90ZWN0ZWQgSUNsYXNzRmlsZSBnZXRDbGFzc0ZpbGUoSUphdmFQcm9qZWN0IHByb2plY3QsIFN0cmluZyByb290UGF0aCwgU3RyaW5nIHBhY2thZ2VOYW1lLCBTdHJpbmcgY2xhc3NOYW1lKSB0aHJvd3MgSmF2YU1vZGVsRXhjZXB0aW9uIHsKCQlJUGFja2FnZUZyYWdtZW50IHBrZz0gZ2V0UGFja2FnZUZyYWdtZW50KHByb2plY3QsIHJvb3RQYXRoLCBwYWNrYWdlTmFtZSk7CgkJaWYgKHBrZyA9PSBudWxsKSB7CgkJCXJldHVybiBudWxsOwoJCX0KCQlyZXR1cm4gcGtnLmdldENsYXNzRmlsZShjbGFzc05hbWUpOwoJfQoKCS8qKgoJICogUmV0dXJucyBjb21waWxhdGlvbiB1bml0IHdpdGggZ2l2ZW4gbmFtZSBpbiBnaXZlbiBwcm9qZWN0IGFuZCBwYWNrYWdlLgoJICogQHBhcmFtIHByb2plY3ROYW1lCgkgKiBAcGFyYW0gcGFja2FnZU5hbWUKCSAqIEBwYXJhbSB1bml0TmFtZQoJICogQHJldHVybiBvcmcuZWNsaXBzZS5qZHQuY29yZS5JQ29tcGlsYXRpb25Vbml0CgkgKi8KCXByb3RlY3RlZCBJQ29tcGlsYXRpb25Vbml0IGdldENvbXBpbGF0aW9uVW5pdChTdHJpbmcgcHJvamVjdE5hbWUsIFN0cmluZyBwYWNrYWdlTmFtZSwgU3RyaW5nIHVuaXROYW1lKSB0aHJvd3MgSmF2YU1vZGVsRXhjZXB0aW9uIHsKCQlJSmF2YVByb2plY3QgamF2YVByb2plY3QgPSBnZXRQcm9qZWN0KHByb2plY3ROYW1lKTsKCQlpZiAoamF2YVByb2plY3QgPT0gbnVsbCkgcmV0dXJuIG51bGw7CgkJSVR5cGUgdHlwZSA9IGphdmFQcm9qZWN0LmZpbmRUeXBlKHBhY2thZ2VOYW1lLCB1bml0TmFtZSk7CgkJaWYgKHR5cGUgIT0gbnVsbCkgewoJCQlyZXR1cm4gdHlwZS5nZXRDb21waWxhdGlvblVuaXQoKTsKCQl9CgkJcmV0dXJuIG51bGw7Cgl9CgoJLyoqCgkgKiBSZXR1cm5zIHRoZSBzcGVjaWZpZWQgcGFja2FnZSBmcmFnbWVudCBpbiB0aGUgZ2l2ZW4gcHJvamVjdCBhbmQgcm9vdCwgb3IKCSAqIDxjb2RlPm51bGw8L2NvZGU+IGlmIGl0IGRvZXMgbm90IGV4aXN0LgoJICogVGhlIHJvb3RQYXRoIG11c3QgYmUgc3BlY2lmaWVkIGFzIGEgcHJvamVjdCByZWxhdGl2ZSBwYXRoLiBUaGUgZW1wdHkKCSAqIHBhdGggcmVmZXJzIHRvIHRoZSBkZWZhdWx0IHBhY2thZ2UgZnJhZ21lbnQuCgkgKi8KCXByb3RlY3RlZCBJUGFja2FnZUZyYWdtZW50IGdldFBhY2thZ2VGcmFnbWVudChJSmF2YVByb2plY3QgcHJvamVjdCwgU3RyaW5nIHJvb3RQYXRoLCBTdHJpbmcgcGFja2FnZU5hbWUpIHRocm93cyBKYXZhTW9kZWxFeGNlcHRpb24gewoJCUlQYWNrYWdlRnJhZ21lbnRSb290IHJvb3Q9IGdldFBhY2thZ2VGcmFnbWVudFJvb3QocHJvamVjdCwgcm9vdFBhdGgpOwoJCWlmIChyb290ID09IG51bGwpIHsKCQkJcmV0dXJuIG51bGw7CgkJfQoJCXJldHVybiByb290LmdldFBhY2thZ2VGcmFnbWVudChwYWNrYWdlTmFtZSk7Cgl9CgoJLyoqCgkgKiBSZXR1cm5zIHRoZSBzcGVjaWZpZWQgcGFja2FnZSBmcmFnbWVudCByb290IGluIHRoZSBnaXZlbiBwcm9qZWN0LCBvcgoJICogPGNvZGU+bnVsbDwvY29kZT4gaWYgaXQgZG9lcyBub3QgZXhpc3QuCgkgKiBJZiByZWxhdGl2ZSwgdGhlIHJvb3RQYXRoIG11c3QgYmUgc3BlY2lmaWVkIGFzIGEgcHJvamVjdCByZWxhdGl2ZSBwYXRoLgoJICogVGhlIGVtcHR5IHBhdGggcmVmZXJzIHRvIHRoZSBwYWNrYWdlIGZyYWdtZW50IHJvb3QgdGhhdCBpcyB0aGUgcHJvamVjdAoJICogZm9sZGVyIGl0ZXNsZi4KCSAqIElmIGFic29sdXRlLCB0aGUgcm9vdFBhdGggcmVmZXJzIHRvIGVpdGhlciBhbiBleHRlcm5hbCBqYXIsIG9yIGEgcmVzb3VyY2UKCSAqIGludGVybmFsIHRvIHRoZSB3b3Jrc3BhY2UKCSAqLwoJcHVibGljIElQYWNrYWdlRnJhZ21lbnRSb290IGdldFBhY2thZ2VGcmFnbWVudFJvb3QoCgkJSUphdmFQcm9qZWN0IHByb2plY3QsCgkJU3RyaW5nIHJvb3RQYXRoKQoJCXRocm93cyBKYXZhTW9kZWxFeGNlcHRpb24gewoKCQlpZiAocHJvamVjdCA9PSBudWxsKSB7CgkJCXJldHVybiBudWxsOwoJCX0KCQlJUGF0aCBwYXRoID0gbmV3IFBhdGgocm9vdFBhdGgpOwoJCWlmIChwYXRoLmlzQWJzb2x1dGUoKSkgewoJCQlJV29ya3NwYWNlUm9vdCB3b3Jrc3BhY2VSb290ID0gUmVzb3VyY2VzUGx1Z2luLmdldFdvcmtzcGFjZSgpLmdldFJvb3QoKTsKCQkJSVJlc291cmNlIHJlc291cmNlID0gd29ya3NwYWNlUm9vdC5maW5kTWVtYmVyKHBhdGgpOwoJCQlJUGFja2FnZUZyYWdtZW50Um9vdCByb290OwoJCQlpZiAocmVzb3VyY2UgPT0gbnVsbCkgewoJCQkJLy8gZXh0ZXJuYWwgamFyCgkJCQlyb290ID0gcHJvamVjdC5nZXRQYWNrYWdlRnJhZ21lbnRSb290KHJvb3RQYXRoKTsKCQkJfSBlbHNlIHsKCQkJCS8vIHJlc291cmNlIGluIHRoZSB3b3Jrc3BhY2UKCQkJCXJvb3QgPSBwcm9qZWN0LmdldFBhY2thZ2VGcmFnbWVudFJvb3QocmVzb3VyY2UpOwoJCQl9CgkJCXJldHVybiByb290OwoJCX0gZWxzZSB7CgkJCUlQYWNrYWdlRnJhZ21lbnRSb290W10gcm9vdHMgPSBwcm9qZWN0LmdldFBhY2thZ2VGcmFnbWVudFJvb3RzKCk7CgkJCWlmIChyb290cyA9PSBudWxsIHx8IHJvb3RzLmxlbmd0aCA9PSAwKSB7CgkJCQlyZXR1cm4gbnVsbDsKCQkJfQoJCQlmb3IgKGludCBpID0gMDsgaSA8IHJvb3RzLmxlbmd0aDsgaSsrKSB7CgkJCQlJUGFja2FnZUZyYWdtZW50Um9vdCByb290ID0gcm9vdHNbaV07CgkJCQlpZiAoIXJvb3QuaXNFeHRlcm5hbCgpCgkJCQkJJiYgcm9vdC5nZXRVbmRlcmx5aW5nUmVzb3VyY2UoKS5nZXRQcm9qZWN0UmVsYXRpdmVQYXRoKCkuZXF1YWxzKHBhdGgpKSB7CgkJCQkJcmV0dXJuIHJvb3Q7CgkJCQl9CgkJCX0KCQl9CgkJcmV0dXJuIGdldEV4dGVybmFsSmFyRmlsZShwcm9qZWN0LCByb290UGF0aCk7Cgl9CgoJLyoqCgkgKiBSZXR1cm5zIHByb2plY3QgY29ycmVzcG9uZGluZyB0byBnaXZlbiBuYW1lIG9yIG51bGwgaWYgbm9uZSBpcyBmb3VuZC4KCSAqIEBwYXJhbSBwcm9qZWN0TmFtZQoJICogQHJldHVybiBJSmF2YVByb2plY3QKCSAqLwoJcHJvdGVjdGVkIElKYXZhUHJvamVjdCBnZXRQcm9qZWN0KFN0cmluZyBwcm9qZWN0TmFtZSkgewoJCWZvciAoaW50IGk9MCwgbGVuZ3RoID0gQUxMX1BST0pFQ1RTLmxlbmd0aDsgaTxsZW5ndGg7IGkrKykgewoJCQlpZiAoQUxMX1BST0pFQ1RTW2ldLmdldEVsZW1lbnROYW1lKCkuZXF1YWxzKHByb2plY3ROYW1lKSkKCQkJCXJldHVybiBBTExfUFJPSkVDVFNbaV07CgkJfQoJCXJldHVybiBudWxsOwoJfQoKCS8qKgoJICogUmV0dXJucyBhbGwgY29tcGlsYXRpb24gdW5pdHMgb2YgYSBnaXZlbiBwcm9qZWN0LgoJICogQHBhcmFtIGphdmFQcm9qZWN0IFByb2plY3QgdG8gY29sbGVjdCB1bml0cwoJICogQHJldHVybiBMaXN0IG9mIG9yZy5lY2xpcHNlLmpkdC5jb3JlLklDb21waWxhdGlvblVuaXQKCSAqLwoJcHJvdGVjdGVkIExpc3QgZ2V0UHJvamVjdENvbXBpbGF0aW9uVW5pdHMoSUphdmFQcm9qZWN0IGphdmFQcm9qZWN0KSB0aHJvd3MgSmF2YU1vZGVsRXhjZXB0aW9uIHsKCQlJUGFja2FnZUZyYWdtZW50Um9vdFtdIGZyYWdtZW50Um9vdHMgPSBqYXZhUHJvamVjdC5nZXRQYWNrYWdlRnJhZ21lbnRSb290cygpOwoJCWludCBsZW5ndGggPSBmcmFnbWVudFJvb3RzLmxlbmd0aDsKCQlMaXN0IGFsbFVuaXRzID0gbmV3IEFycmF5TGlzdCgpOwoJCWZvciAoaW50IGk9MDsgaTxsZW5ndGg7IGkrKykgewoJCQlpZiAoZnJhZ21lbnRSb290c1tpXSBpbnN0YW5jZW9mIEphclBhY2thZ2VGcmFnbWVudFJvb3QpIGNvbnRpbnVlOwoJCQlJSmF2YUVsZW1lbnRbXSBwYWNrYWdlcz0gZnJhZ21lbnRSb290c1tpXS5nZXRDaGlsZHJlbigpOwoJCQlmb3IgKGludCBrPSAwOyBrIDwgcGFja2FnZXMubGVuZ3RoOyBrKyspIHsKCQkJCUlQYWNrYWdlRnJhZ21lbnQgcGFjayA9IChJUGFja2FnZUZyYWdtZW50KSBwYWNrYWdlc1trXTsKCQkJCUlDb21waWxhdGlvblVuaXRbXSB1bml0cyA9IHBhY2suZ2V0Q29tcGlsYXRpb25Vbml0cygpOwoJCQkJZm9yIChpbnQgdT0wOyB1PHVuaXRzLmxlbmd0aDsgdSsrKSB7CgkJCQkJYWxsVW5pdHMuYWRkKHVuaXRzW3VdKTsKCQkJCX0KCQkJfQoJCX0KCQlyZXR1cm4gYWxsVW5pdHM7Cgl9CgoJcHJvdGVjdGVkIElQYWNrYWdlRnJhZ21lbnRSb290IGdldEV4dGVybmFsSmFyRmlsZShJSmF2YVByb2plY3QgcHJvamVjdCwgU3RyaW5nIGphclNpbXBsZU5hbWUpIHRocm93cyBKYXZhTW9kZWxFeGNlcHRpb24gewoJCUlQYWNrYWdlRnJhZ21lbnRSb290W10gcm9vdHMgPSBwcm9qZWN0LmdldFBhY2thZ2VGcmFnbWVudFJvb3RzKCk7CgkJaWYgKHJvb3RzID09IG51bGwgfHwgcm9vdHMubGVuZ3RoID09IDApIHsKCQkJcmV0dXJuIG51bGw7CgkJfQoJCWZvciAoaW50IGkgPSAwOyBpIDwgcm9vdHMubGVuZ3RoOyBpKyspIHsKCQkJSVBhY2thZ2VGcmFnbWVudFJvb3Qgcm9vdCA9IHJvb3RzW2ldOwoJCQlpZiAocm9vdC5pc0V4dGVybmFsKCkgJiYgcm9vdC5nZXRFbGVtZW50TmFtZSgpLmVxdWFscyhqYXJTaW1wbGVOYW1lKSkgewoJCQkJcmV0dXJuIHJvb3Q7CgkJCX0KCQl9CgkJcmV0dXJuIG51bGw7Cgl9CgkvKgoJICogU2ltdWxhdGUgYSBzYXZlL2V4aXQgb2YgdGhlIHdvcmtzcGFjZQoJICovCglwcm90ZWN0ZWQgdm9pZCBzaW11bGF0ZUV4aXQoKSB0aHJvd3MgQ29yZUV4Y2VwdGlvbiB7CgkJQWJzdHJhY3RKYXZhTW9kZWxUZXN0cy53YWl0Rm9yQXV0b0J1aWxkKCk7CgkJUmVzb3VyY2VzUGx1Z2luLmdldFdvcmtzcGFjZSgpLnNhdmUodHJ1ZS8qZnVsbCBzYXZlKi8sIG51bGwvKm5vIHByb2dyZXNzKi8pOwoJCUphdmFNb2RlbE1hbmFnZXIuZ2V0SmF2YU1vZGVsTWFuYWdlcigpLnNodXRkb3duKCk7Cgl9CgkvKgoJICogU2ltdWxhdGUgYSBzYXZlL2V4aXQvcmVzdGFydCBvZiB0aGUgd29ya3NwYWNlCgkgKi8KCXByb3RlY3RlZCB2b2lkIHNpbXVsYXRlRXhpdFJlc3RhcnQoKSB0aHJvd3MgQ29yZUV4Y2VwdGlvbiB7CgkJc2ltdWxhdGVFeGl0KCk7CgkJc2ltdWxhdGVSZXN0YXJ0KCk7Cgl9CgkvKgoJICogU2ltdWxhdGUgYSByZXN0YXJ0IG9mIHRoZSB3b3Jrc3BhY2UKCSAqLwoJcHJvdGVjdGVkIHZvaWQgc2ltdWxhdGVSZXN0YXJ0KCkgdGhyb3dzIENvcmVFeGNlcHRpb24gewoJCUphdmFNb2RlbE1hbmFnZXIuZG9Ob3RVc2UoKTsgLy8gcmVzZXQgdGhlIE1BTkFHRVIgc2luZ2xldG9uCgkJSmF2YU1vZGVsTWFuYWdlci5nZXRKYXZhTW9kZWxNYW5hZ2VyKCkuc3RhcnR1cCgpOwoJCW5ldyBKYXZhQ29yZVByZWZlcmVuY2VJbml0aWFsaXplcigpLmluaXRpYWxpemVEZWZhdWx0UHJlZmVyZW5jZXMoKTsKCX0KCgkvKioKCSAqIFNwbGl0IGEgbGlzdCBvZiBjb21waWxhdGlvbiB1bml0cyBpbiBzZXZlcmFsIGFycmF5cy4KCSAqIEBwYXJhbSB1bml0cyBMaXN0IG9mIG9yZy5lY2xpcHNlLmpkdC5jb3JlLklDb21waWxhdGlvblVuaXQKCSAqIEBwYXJhbSBzcGxpdFNpemUgU2l6ZSBvZiB0aGUgYXJyYXlzCgkgKiBAcmV0dXJuIExpc3Qgb2YgSUNvbXBpbGF0aW9uVW5pdFtdCgkgKi8KCXByb3RlY3RlZCBMaXN0IHNwbGl0TGlzdEluU21hbGxBcnJheXMoTGlzdCB1bml0cywgaW50IHNwbGl0U2l6ZSkgdGhyb3dzIEphdmFNb2RlbEV4Y2VwdGlvbiB7CgkJaW50IHNpemUgPSB1bml0cy5zaXplKCk7CgkJaWYgKHNpemUgPT0gMCkgcmV0dXJuIENvbGxlY3Rpb25zLkVNUFRZX0xJU1Q7CgkJaW50IGxlbmd0aCA9IHNpemUgLyBzcGxpdFNpemU7CgkJaW50IHJlbWluZCA9IHNpemUlc3BsaXRTaXplOwoJCUxpc3Qgc3BsaXR0ZWQgPSBuZXcgQXJyYXlMaXN0KHJlbWluZD09MD9sZW5ndGg6bGVuZ3RoKzEpOwoJCWlmIChsZW5ndGggPT0gMCkgewoJCQlJQ29tcGlsYXRpb25Vbml0W10gc3VibGlzdCA9IG5ldyBJQ29tcGlsYXRpb25Vbml0W3NpemVdOwoJCQl1bml0cy50b0FycmF5KHN1Ymxpc3QpOwoJCQlzcGxpdHRlZC5hZGQoc3VibGlzdCk7CgkJCXJldHVybiBzcGxpdHRlZDsKCQl9CgkJaW50IHB0ciA9IDA7CgkJZm9yIChpbnQgaT0gMDsgaTxsZW5ndGg7IGkrKyl7CgkJCUlDb21waWxhdGlvblVuaXRbXSBzdWJsaXN0ID0gbmV3IElDb21waWxhdGlvblVuaXRbc3BsaXRTaXplXTsKCQkJdW5pdHMuc3ViTGlzdChwdHIsIHB0citzcGxpdFNpemUpLnRvQXJyYXkoc3VibGlzdCk7CgkJCXNwbGl0dGVkLmFkZChzdWJsaXN0KTsKCQkJcHRyICs9IHNwbGl0U2l6ZTsKCQl9CgkJaWYgKHJlbWluZCA+IDApIHsKCQkJaWYgKHJlbWluZDwgMTApIHsKCQkJCUlDb21waWxhdGlvblVuaXRbXSBsYXN0TGlzdCA9IChJQ29tcGlsYXRpb25Vbml0W10pIHNwbGl0dGVkLnJlbW92ZShsZW5ndGgtMSk7CgkJCQlTeXN0ZW0uYXJyYXljb3B5KGxhc3RMaXN0LCAwLCBsYXN0TGlzdCA9IG5ldyBJQ29tcGlsYXRpb25Vbml0W3NwbGl0U2l6ZStyZW1pbmRdLCAwLCBzcGxpdFNpemUpOwoJCQkJZm9yIChpbnQgaT1wdHIsIGo9c3BsaXRTaXplOyBpPHNpemU7IGkrKywgaisrKSB7CgkJCQkJbGFzdExpc3Rbal0gPSAoSUNvbXBpbGF0aW9uVW5pdCkgdW5pdHMuZ2V0KGkpOwoJCQkJfQoJCQkJc3BsaXR0ZWQuYWRkKGxhc3RMaXN0KTsKCQkJfSBlbHNlIHsKCQkJCUlDb21waWxhdGlvblVuaXRbXSBzdWJsaXN0ID0gbmV3IElDb21waWxhdGlvblVuaXRbcmVtaW5kXTsKCQkJCXVuaXRzLnN1Ykxpc3QocHRyLCBzaXplKS50b0FycmF5KHN1Ymxpc3QpOwoJCQkJc3BsaXR0ZWQuYWRkKHN1Ymxpc3QpOwoJCQl9CgkJfQoJCXJldHVybiBzcGxpdHRlZDsKCX0KCgkvKgoJICogQ3JlYXRlIGhhc2h0YWJsZSBvZiBub25lIG9yIGFsbCB3YXJuaW5nIG9wdGlvbnMuCgkgKiBQb3NzaWJsZSBraW5kOgoJICogCS0xOiBubyBvcHRpb25zCgkgKiAgMDogZGVmYXVsdCBvcHRpb25zCgkgKiAgMTogYWxsIG9wdGlvbnMKCSAqLwoJcHJvdGVjdGVkIEhhc2h0YWJsZSB3YXJuaW5nT3B0aW9ucyhpbnQga2luZCkgewoKCQkvLyBWYWx1ZXMKCQlIYXNodGFibGUgb3B0aW9uc01hcCA9IEphdmFDb3JlLmdldERlZmF1bHRPcHRpb25zKCk7CgkJaWYgKGtpbmQgPT0gMCkgewoJCQkvLyBEZWZhdWx0IHNldCBzaW5jZSAzLjEKCQkJb3B0aW9uc01hcC5wdXQoQ29tcGlsZXJPcHRpb25zLk9QVElPTl9SZXBvcnRVbnVzZWRJbXBvcnQsIENvbXBpbGVyT3B0aW9ucy5JR05PUkUpOwoJCX0gZWxzZSB7CgkJCWNsZWFyT3B0aW9ucyhvcHRpb25zTWFwKTsKCQkJYm9vbGVhbiBhbGwgPSBraW5kID09IDE7CgkJCVN0cmluZyBnZW5lcmF0ZSA9IGFsbCA/IENvbXBpbGVyT3B0aW9ucy5HRU5FUkFURSA6IENvbXBpbGVyT3B0aW9ucy5ET19OT1RfR0VORVJBVEU7CgkJCVN0cmluZyB3YXJuaW5nID0gYWxsID8gQ29tcGlsZXJPcHRpb25zLldBUk5JTkcgOiBDb21waWxlck9wdGlvbnMuSUdOT1JFOwoJCQlTdHJpbmcgZW5hYmxlZCA9IGFsbCA/IENvbXBpbGVyT3B0aW9ucy5FTkFCTEVEIDogQ29tcGlsZXJPcHRpb25zLkRJU0FCTEVEOwoJCQlTdHJpbmcgcHJlc2VydmUgPSBhbGwgPyBDb21waWxlck9wdGlvbnMuT1BUSU1JWkVfT1VUIDogQ29tcGlsZXJPcHRpb25zLlBSRVNFUlZFOwoKCQkJLy8gU2V0IG9wdGlvbnMgdmFsdWVzCgkJCW9wdGlvbnNNYXAucHV0KENvbXBpbGVyT3B0aW9ucy5PUFRJT05fTG9jYWxWYXJpYWJsZUF0dHJpYnV0ZSwgZ2VuZXJhdGUpOwoJCQlvcHRpb25zTWFwLnB1dChDb21waWxlck9wdGlvbnMuT1BUSU9OX0xpbmVOdW1iZXJBdHRyaWJ1dGUsIGdlbmVyYXRlKTsKCQkJb3B0aW9uc01hcC5wdXQoQ29tcGlsZXJPcHRpb25zLk9QVElPTl9Tb3VyY2VGaWxlQXR0cmlidXRlLCBnZW5lcmF0ZSk7CgkJCW9wdGlvbnNNYXAucHV0KENvbXBpbGVyT3B0aW9ucy5PUFRJT05fUHJlc2VydmVVbnVzZWRMb2NhbCwgcHJlc2VydmUpOwoJCQlvcHRpb25zTWFwLnB1dChDb21waWxlck9wdGlvbnMuT1BUSU9OX0RvY0NvbW1lbnRTdXBwb3J0LCBlbmFibGVkKTsKCQkJb3B0aW9uc01hcC5wdXQoQ29tcGlsZXJPcHRpb25zLk9QVElPTl9SZXBvcnRNZXRob2RXaXRoQ29uc3RydWN0b3JOYW1lLCB3YXJuaW5nKTsKCQkJb3B0aW9uc01hcC5wdXQoQ29tcGlsZXJPcHRpb25zLk9QVElPTl9SZXBvcnRPdmVycmlkaW5nUGFja2FnZURlZmF1bHRNZXRob2QsIHdhcm5pbmcpOwoJCQlvcHRpb25zTWFwLnB1dChDb21waWxlck9wdGlvbnMuT1BUSU9OX1JlcG9ydERlcHJlY2F0aW9uLCB3YXJuaW5nKTsKCQkJb3B0aW9uc01hcC5wdXQoQ29tcGlsZXJPcHRpb25zLk9QVElPTl9SZXBvcnREZXByZWNhdGlvbkluRGVwcmVjYXRlZENvZGUsIGVuYWJsZWQpOwoJCQlvcHRpb25zTWFwLnB1dChDb21waWxlck9wdGlvbnMuT1BUSU9OX1JlcG9ydERlcHJlY2F0aW9uV2hlbk92ZXJyaWRpbmdEZXByZWNhdGVkTWV0aG9kLCBlbmFibGVkKTsKCQkJb3B0aW9uc01hcC5wdXQoQ29tcGlsZXJPcHRpb25zLk9QVElPTl9SZXBvcnRIaWRkZW5DYXRjaEJsb2NrLCB3YXJuaW5nKTsKCQkJb3B0aW9uc01hcC5wdXQoQ29tcGlsZXJPcHRpb25zLk9QVElPTl9SZXBvcnRVbnVzZWRMb2NhbCwgd2FybmluZyk7CgkJCW9wdGlvbnNNYXAucHV0KENvbXBpbGVyT3B0aW9ucy5PUFRJT05fUmVwb3J0VW51c2VkUGFyYW1ldGVyLCB3YXJuaW5nKTsKCQkJb3B0aW9uc01hcC5wdXQoQ29tcGlsZXJPcHRpb25zLk9QVElPTl9SZXBvcnRVbnVzZWRJbXBvcnQsIHdhcm5pbmcpOwoJCQlvcHRpb25zTWFwLnB1dChDb21waWxlck9wdGlvbnMuT1BUSU9OX1JlcG9ydFN5bnRoZXRpY0FjY2Vzc0VtdWxhdGlvbiwgd2FybmluZyk7CgkJCW9wdGlvbnNNYXAucHV0KENvbXBpbGVyT3B0aW9ucy5PUFRJT05fUmVwb3J0Tm9FZmZlY3RBc3NpZ25tZW50LCB3YXJuaW5nKTsKCQkJb3B0aW9uc01hcC5wdXQoQ29tcGlsZXJPcHRpb25zLk9QVElPTl9SZXBvcnROb25FeHRlcm5hbGl6ZWRTdHJpbmdMaXRlcmFsLCB3YXJuaW5nKTsKCQkJb3B0aW9uc01hcC5wdXQoQ29tcGlsZXJPcHRpb25zLk9QVElPTl9SZXBvcnROb0ltcGxpY2l0U3RyaW5nQ29udmVyc2lvbiwgd2FybmluZyk7CgkJCW9wdGlvbnNNYXAucHV0KENvbXBpbGVyT3B0aW9ucy5PUFRJT05fUmVwb3J0Tm9uU3RhdGljQWNjZXNzVG9TdGF0aWMsIHdhcm5pbmcpOwoJCQlvcHRpb25zTWFwLnB1dChDb21waWxlck9wdGlvbnMuT1BUSU9OX1JlcG9ydEluZGlyZWN0U3RhdGljQWNjZXNzLCB3YXJuaW5nKTsKCQkJb3B0aW9uc01hcC5wdXQoQ29tcGlsZXJPcHRpb25zLk9QVElPTl9SZXBvcnRJbmNvbXBhdGlibGVOb25Jbmhlcml0ZWRJbnRlcmZhY2VNZXRob2QsIHdhcm5pbmcpOwoJCQlvcHRpb25zTWFwLnB1dChDb21waWxlck9wdGlvbnMuT1BUSU9OX1JlcG9ydFVudXNlZFByaXZhdGVNZW1iZXIsIHdhcm5pbmcpOwoJCQlvcHRpb25zTWFwLnB1dChDb21waWxlck9wdGlvbnMuT1BUSU9OX1JlcG9ydExvY2FsVmFyaWFibGVIaWRpbmcsIHdhcm5pbmcpOwoJCQlvcHRpb25zTWFwLnB1dChDb21waWxlck9wdGlvbnMuT1BUSU9OX1JlcG9ydEZpZWxkSGlkaW5nLCB3YXJuaW5nKTsKCQkJb3B0aW9uc01hcC5wdXQoQ29tcGlsZXJPcHRpb25zLk9QVElPTl9SZXBvcnRQb3NzaWJsZUFjY2lkZW50YWxCb29sZWFuQXNzaWdubWVudCwgd2FybmluZyk7CgkJCW9wdGlvbnNNYXAucHV0KENvbXBpbGVyT3B0aW9ucy5PUFRJT05fUmVwb3J0RW1wdHlTdGF0ZW1lbnQsIHdhcm5pbmcpOwoJCQlvcHRpb25zTWFwLnB1dChDb21waWxlck9wdGlvbnMuT1BUSU9OX1JlcG9ydEFzc2VydElkZW50aWZpZXIsIHdhcm5pbmcpOwoJCQlvcHRpb25zTWFwLnB1dChDb21waWxlck9wdGlvbnMuT1BUSU9OX1JlcG9ydFVuZG9jdW1lbnRlZEVtcHR5QmxvY2ssIHdhcm5pbmcpOwoJCQlvcHRpb25zTWFwLnB1dChDb21waWxlck9wdGlvbnMuT1BUSU9OX1JlcG9ydFVubmVjZXNzYXJ5VHlwZUNoZWNrLCB3YXJuaW5nKTsKCQkJb3B0aW9uc01hcC5wdXQoQ29tcGlsZXJPcHRpb25zLk9QVElPTl9SZXBvcnRVbm5lY2Vzc2FyeUVsc2UsIHdhcm5pbmcpOwoJCQlvcHRpb25zTWFwLnB1dChDb21waWxlck9wdGlvbnMuT1BUSU9OX1JlcG9ydEludmFsaWRKYXZhZG9jLCB3YXJuaW5nKTsKCQkJb3B0aW9uc01hcC5wdXQoQ29tcGlsZXJPcHRpb25zLk9QVElPTl9SZXBvcnRJbnZhbGlkSmF2YWRvY1RhZ3MsIGVuYWJsZWQpOwoJCQlvcHRpb25zTWFwLnB1dChDb21waWxlck9wdGlvbnMuT1BUSU9OX1JlcG9ydE1pc3NpbmdKYXZhZG9jVGFncywgd2FybmluZyk7CgkJCW9wdGlvbnNNYXAucHV0KENvbXBpbGVyT3B0aW9ucy5PUFRJT05fUmVwb3J0TWlzc2luZ0phdmFkb2NDb21tZW50cywgd2FybmluZyk7CgkJCW9wdGlvbnNNYXAucHV0KENvbXBpbGVyT3B0aW9ucy5PUFRJT05fUmVwb3J0RmluYWxseUJsb2NrTm90Q29tcGxldGluZ05vcm1hbGx5LCB3YXJuaW5nKTsKCQkJb3B0aW9uc01hcC5wdXQoQ29tcGlsZXJPcHRpb25zLk9QVElPTl9SZXBvcnRVbnVzZWREZWNsYXJlZFRocm93bkV4Y2VwdGlvbiwgd2FybmluZyk7CgkJCW9wdGlvbnNNYXAucHV0KENvbXBpbGVyT3B0aW9ucy5PUFRJT05fUmVwb3J0VW5xdWFsaWZpZWRGaWVsZEFjY2Vzcywgd2FybmluZyk7CgkJCW9wdGlvbnNNYXAucHV0KENvbXBpbGVyT3B0aW9ucy5PUFRJT05fVGFza1RhZ3MsIGFsbCA/IEphdmFDb3JlLkRFRkFVTFRfVEFTS19UQUdTIDogIiIpOwoJCQlvcHRpb25zTWFwLnB1dChDb21waWxlck9wdGlvbnMuT1BUSU9OX1Rhc2tQcmlvcml0aWVzLCBhbGwgPyBKYXZhQ29yZS5ERUZBVUxUX1RBU0tfUFJJT1JJVElFUyA6ICIiKTsKCQkJb3B0aW9uc01hcC5wdXQoQ29tcGlsZXJPcHRpb25zLk9QVElPTl9UYXNrQ2FzZVNlbnNpdGl2ZSwgZW5hYmxlZCk7CgkJCW9wdGlvbnNNYXAucHV0KENvbXBpbGVyT3B0aW9ucy5PUFRJT05fUmVwb3J0VW51c2VkUGFyYW1ldGVyV2hlbkltcGxlbWVudGluZ0Fic3RyYWN0LCBlbmFibGVkKTsKCQkJb3B0aW9uc01hcC5wdXQoQ29tcGlsZXJPcHRpb25zLk9QVElPTl9SZXBvcnRVbnVzZWRQYXJhbWV0ZXJXaGVuT3ZlcnJpZGluZ0NvbmNyZXRlLCBlbmFibGVkKTsKCQkJb3B0aW9uc01hcC5wdXQoQ29tcGlsZXJPcHRpb25zLk9QVElPTl9SZXBvcnRTcGVjaWFsUGFyYW1ldGVySGlkaW5nRmllbGQsIGVuYWJsZWQpOwoJCQlvcHRpb25zTWFwLnB1dChDb21waWxlck9wdGlvbnMuT1BUSU9OX0lubGluZUpzciwgZW5hYmxlZCk7CgkJfQoKCQkvLyBJZ25vcmUgMy4xIG9wdGlvbnMKCQlvcHRpb25zTWFwLnB1dChDb21waWxlck9wdGlvbnMuT1BUSU9OX1JlcG9ydE1pc3NpbmdTZXJpYWxWZXJzaW9uLCBDb21waWxlck9wdGlvbnMuSUdOT1JFKTsKCQlvcHRpb25zTWFwLnB1dChDb21waWxlck9wdGlvbnMuT1BUSU9OX1JlcG9ydEVudW1JZGVudGlmaWVyLCBDb21waWxlck9wdGlvbnMuSUdOT1JFKTsKCgkJLy8gSWdub3JlIDMuMiBvcHRpb25zCgkJb3B0aW9uc01hcC5wdXQoQ29tcGlsZXJPcHRpb25zLk9QVElPTl9SZXBvcnRVbnVzZWRMYWJlbCwgQ29tcGlsZXJPcHRpb25zLklHTk9SRSk7CgoJCS8vIFNldCBjb21wbGlhbmNlCgkJU3RyaW5nIGNvbXBsaWFuY2U9IGNvbXBsaWFuY2UoKTsKCQlpZiAoY29tcGxpYW5jZSAhPSBudWxsKSB7CgkJCW9wdGlvbnNNYXAucHV0KENvbXBpbGVyT3B0aW9ucy5PUFRJT05fQ29tcGxpYW5jZSwgY29tcGxpYW5jZSk7CgkJCW9wdGlvbnNNYXAucHV0KENvbXBpbGVyT3B0aW9ucy5PUFRJT05fU291cmNlLCBjb21wbGlhbmNlKTsKCQkJb3B0aW9uc01hcC5wdXQoQ29tcGlsZXJPcHRpb25zLk9QVElPTl9UYXJnZXRQbGF0Zm9ybSwgY29tcGxpYW5jZSk7CgkJfQoKCQkvLyBSZXR1cm4gY3JlYXRlZCBvcHRpb25zIG1hcAoJCXJldHVybiBvcHRpb25zTWFwOwoJfQoKCXByb3RlY3RlZCBTdHJpbmcgZ2V0RXh0ZXJuYWxQYXRoKCkgewoJCVN0cmluZyBwYXRoID0gIiI7CgkJdHJ5IHsKCQkJcGF0aCA9IFJlc291cmNlc1BsdWdpbi5nZXRXb3Jrc3BhY2UoKS5nZXRSb290KCkuZ2V0TG9jYXRpb24oKS50b0ZpbGUoKS5nZXRQYXJlbnRGaWxlKCkuZ2V0Q2Fub25pY2FsUGF0aCgpOwoJCQlpZiAocGF0aC5jaGFyQXQocGF0aC5sZW5ndGgoKS0xKSAhPSBGaWxlLnNlcGFyYXRvckNoYXIpCgkJCQlwYXRoICs9IEZpbGUuc2VwYXJhdG9yQ2hhcjsKCQl9IGNhdGNoIChJT0V4Y2VwdGlvbiBlKSB7CgkJCWUucHJpbnRTdGFja1RyYWNlKCk7CgkJfQoJCXJldHVybiBwYXRoOwoJfQoKCXByb3RlY3RlZCBTdHJpbmcgZ2V0RXh0ZXJuYWxSZXNvdXJjZVBhdGgoU3RyaW5nIHJlbGF0aXZlUGF0aCkgewoJCXJldHVybiBnZXRFeHRlcm5hbFBhdGgoKSArIHJlbGF0aXZlUGF0aDsKCX0KfQo=