LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogQ29weXJpZ2h0IChjKSAyMDAwLCAyMDEyIElCTSBDb3Jwb3JhdGlvbiBhbmQgb3RoZXJzLgogKiBBbGwgcmlnaHRzIHJlc2VydmVkLiBUaGlzIHByb2dyYW0gYW5kIHRoZSBhY2NvbXBhbnlpbmcgbWF0ZXJpYWxzCiAqIGFyZSBtYWRlIGF2YWlsYWJsZSB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEVjbGlwc2UgUHVibGljIExpY2Vuc2UgdjEuMAogKiB3aGljaCBhY2NvbXBhbmllcyB0aGlzIGRpc3RyaWJ1dGlvbiwgYW5kIGlzIGF2YWlsYWJsZSBhdAogKiBodHRwOi8vd3d3LmVjbGlwc2Uub3JnL2xlZ2FsL2VwbC12MTAuaHRtbAogKgogKiBDb250cmlidXRvcnM6CiAqICAgICBJQk0gQ29ycG9yYXRpb24gLSBpbml0aWFsIEFQSSBhbmQgaW1wbGVtZW50YXRpb24KICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovCgpwYWNrYWdlIG9yZy5lY2xpcHNlLmpkdC5jb3JlLnRlc3RzLnBlcmZvcm1hbmNlOwoKaW1wb3J0IGphdmEuaW8uKjsKaW1wb3J0IGphdmEubmV0LlVSTDsKaW1wb3J0IGphdmEudGV4dC5EYXRlRm9ybWF0OwppbXBvcnQgamF2YS50ZXh0Lk51bWJlckZvcm1hdDsKaW1wb3J0IGphdmEudXRpbC4qOwoKaW1wb3J0IGp1bml0LmZyYW1ld29yay4qOwppbXBvcnQgb3JnLmVjbGlwc2UuY29yZS5yZXNvdXJjZXMuKjsKaW1wb3J0IG9yZy5lY2xpcHNlLmNvcmUucnVudGltZS4qOwppbXBvcnQgb3JnLmVjbGlwc2UuY29yZS5ydW50aW1lLnByZWZlcmVuY2VzLklFY2xpcHNlUHJlZmVyZW5jZXM7CmltcG9ydCBvcmcuZWNsaXBzZS5jb3JlLnJ1bnRpbWUucHJlZmVyZW5jZXMuSW5zdGFuY2VTY29wZTsKaW1wb3J0IG9yZy5lY2xpcHNlLmpkdC5jb3JlLio7CmltcG9ydCBvcmcuZWNsaXBzZS5qZHQuY29yZS50ZXN0cy5idWlsZGVyLlRlc3RpbmdFbnZpcm9ubWVudDsKaW1wb3J0IG9yZy5lY2xpcHNlLmpkdC5jb3JlLnRlc3RzLmp1bml0LmV4dGVuc2lvbi5UZXN0Q2FzZTsKaW1wb3J0IG9yZy5lY2xpcHNlLmpkdC5jb3JlLnRlc3RzLm1vZGVsLkFic3RyYWN0SmF2YU1vZGVsVGVzdHM7CmltcG9ydCBvcmcuZWNsaXBzZS5qZHQuY29yZS50ZXN0cy5wZXJmb3JtYW5jZS51dGlsLkpkdENvcmVQZXJmb3JtYW5jZU1ldGVyOwppbXBvcnQgb3JnLmVjbGlwc2UuamR0LmNvcmUudGVzdHMucGVyZm9ybWFuY2UudXRpbC5TdGF0aXN0aWNzOwppbXBvcnQgb3JnLmVjbGlwc2UuamR0LmNvcmUudGVzdHMudXRpbC5VdGlsOwppbXBvcnQgb3JnLmVjbGlwc2UuamR0LmludGVybmFsLmNvbXBpbGVyLmJhdGNoLk1haW47CmltcG9ydCBvcmcuZWNsaXBzZS5qZHQuaW50ZXJuYWwuY29tcGlsZXIuaW1wbC5Db21waWxlck9wdGlvbnM7CmltcG9ydCBvcmcuZWNsaXBzZS5qZHQuaW50ZXJuYWwuY29yZS5KYXJQYWNrYWdlRnJhZ21lbnRSb290OwppbXBvcnQgb3JnLmVjbGlwc2UuamR0LmludGVybmFsLmNvcmUuSmF2YUNvcmVQcmVmZXJlbmNlSW5pdGlhbGl6ZXI7CmltcG9ydCBvcmcuZWNsaXBzZS5qZHQuaW50ZXJuYWwuY29yZS5KYXZhTW9kZWxNYW5hZ2VyOwppbXBvcnQgb3JnLmVjbGlwc2UuamR0LmludGVybmFsLmNvcmUuSmF2YVByb2plY3Q7CmltcG9ydCBvcmcuZWNsaXBzZS5qZHQuaW50ZXJuYWwuY29yZS5zZWFyY2guaW5kZXhpbmcuSW5kZXhNYW5hZ2VyOwppbXBvcnQgb3JnLmVjbGlwc2UudGVzdC5pbnRlcm5hbC5wZXJmb3JtYW5jZS5kYXRhLkRhdGFQb2ludDsKaW1wb3J0IG9yZy5lY2xpcHNlLnRlc3QucGVyZm9ybWFuY2UuRGltZW5zaW9uOwppbXBvcnQgb3JnLmVjbGlwc2UudGVzdC5wZXJmb3JtYW5jZS5QZXJmb3JtYW5jZTsKCgoKcHVibGljIGFic3RyYWN0IGNsYXNzIEZ1bGxTb3VyY2VXb3Jrc3BhY2VUZXN0cyBleHRlbmRzIFRlc3RDYXNlIHsKCgkvLyBEZWJ1ZyB2YXJpYWJsZXMKCWZpbmFsIHN0YXRpYyBib29sZWFuIERFQlVHID0gInRydWUiLmVxdWFscyhTeXN0ZW0uZ2V0UHJvcGVydHkoImRlYnVnIikpOwoJZmluYWwgc3RhdGljIGJvb2xlYW4gUFJJTlQgPSAidHJ1ZSIuZXF1YWxzKFN5c3RlbS5nZXRQcm9wZXJ0eSgicHJpbnQiKSk7CgkvKioKCSAqIEZsYWcgdG8gdmFsaWRhdGUgdGVzdCBydW4gZW52aXJvbm1lbnQuCgkgKiA8cD4KCSAqIFRoaXMgcHJvcGVydHkgaGFzIGJlZW4gYWRkZWQgdG8gc3BlZWQtdXAgY2hlY2stdXAgb2YgbG9jYWwgc2hlbGxzIHRvIHJ1biB0aGUKCSAqIGVudGlyZSBwZXJmb3JtYW5jZSB0ZXN0cy4KCSAqIDxwPgoJICogV0FSTklORzogaWYgdGhpcyBwcm9wZXJ0eSBpcyBzZXQsICpub3RoaW5nIGF0IGFsbCogd2lsbCBiZSBydW4sIG5laXRoZXIgbWVhc3VyZSBub3Igd2FybS11cC4KCSAqLwoJZmluYWwgc3RhdGljIGJvb2xlYW4gVE9VQ0ggPSAidHJ1ZSIuZXF1YWxzKFN5c3RlbS5nZXRQcm9wZXJ0eSgidG91Y2giKSk7CgoJLy8gT3B0aW9ucwoJZmluYWwgc3RhdGljIEhhc2h0YWJsZSBJTklUSUFMX09QVElPTlMgPSBKYXZhQ29yZS5nZXRPcHRpb25zKCk7CglmaW5hbCBzdGF0aWMgU3RyaW5nIENPTVBMSUFOQ0UgPSBTeXN0ZW0uZ2V0UHJvcGVydHkoImNvbXBsaWFuY2UiKTsKCXN0YXRpYyB7CgkJSGFzaHRhYmxlIG9wdGlvbnMgPSBJTklUSUFMX09QVElPTlM7CgkJU3RyaW5nIGNvbXBsaWFuY2UgPSBjb21wbGlhbmNlKCk7CgkJaWYgKGNvbXBsaWFuY2UgPT0gbnVsbCkgewoJCQlTeXN0ZW0ub3V0LnByaW50bG4oIlVzZWQgZGVmYXVsdCBjb21wbGlhbmNlOiAiK29wdGlvbnMuZ2V0KEphdmFDb3JlLkNPTVBJTEVSX0NPTVBMSUFOQ0UpKTsKCQl9IGVsc2UgewoJCQlTeXN0ZW0ub3V0LnByaW50bG4oIlVzZWQgY29tcGxpYW5jZTogIitjb21wbGlhbmNlKTsKCQkJb3B0aW9ucy5wdXQoQ29tcGlsZXJPcHRpb25zLk9QVElPTl9Db21wbGlhbmNlLCBjb21wbGlhbmNlKTsKCQkJb3B0aW9ucy5wdXQoQ29tcGlsZXJPcHRpb25zLk9QVElPTl9Tb3VyY2UsIGNvbXBsaWFuY2UpOwoJCQlvcHRpb25zLnB1dChDb21waWxlck9wdGlvbnMuT1BUSU9OX1RhcmdldFBsYXRmb3JtLCBjb21wbGlhbmNlKTsKCQkJSmF2YUNvcmUuc2V0T3B0aW9ucyhvcHRpb25zKTsKCQl9Cgl9Cglwcm90ZWN0ZWQgc3RhdGljIFN0cmluZyBjb21wbGlhbmNlKCkgewoJCVN0cmluZyBjb21wbGlhbmNlID0gbnVsbDsKCQlpZiAoIjEuMyIuZXF1YWxzKENPTVBMSUFOQ0UpKSB7CgkJCWNvbXBsaWFuY2UgPSBDb21waWxlck9wdGlvbnMuVkVSU0lPTl8xXzM7CgkJfSBlbHNlIGlmICgiMS40Ii5lcXVhbHMoQ09NUExJQU5DRSkpIHsKCQkJY29tcGxpYW5jZSA9IENvbXBpbGVyT3B0aW9ucy5WRVJTSU9OXzFfNDsKCQl9IGVsc2UgaWYgKCIxLjUiLmVxdWFscyhDT01QTElBTkNFKSB8fCAiNS4wIi5lcXVhbHMoQ09NUExJQU5DRSkpIHsKCQkJY29tcGxpYW5jZSA9IENvbXBpbGVyT3B0aW9ucy5WRVJTSU9OXzFfNTsKCQl9IGVsc2UgaWYgKCIxLjYiLmVxdWFscyhDT01QTElBTkNFKSB8fCAiNi4wIi5lcXVhbHMoQ09NUExJQU5DRSkpIHsKCQkJY29tcGxpYW5jZSA9IENvbXBpbGVyT3B0aW9ucy5WRVJTSU9OXzFfNjsKCQl9CgkJcmV0dXJuIGNvbXBsaWFuY2U7Cgl9CgoJLy8gR2FyYmFnZSBjb2xsZWN0IGNvbnN0YW50cwoJZmluYWwgc3RhdGljIGludCBNQVhfR0MgPSAxMDsgLy8gTWF4IGdjIGl0ZXJhdGlvbnMKCWZpbmFsIHN0YXRpYyBpbnQgVElNRV9HQyA9IDUwMDsgLy8gU2xlZXAgdG8gd2FpdCBnYyB0byBydW4gKGluIG1zKQoJZmluYWwgc3RhdGljIGludCBERUxUQV9HQyA9IDEwMDA7IC8vIFRocmVzaG9sZCB0byByZW1haW5pbmcgZnJlZSBtZW1vcnkKCgkvLyBXb3Jrc3BhY2UgdmFyaWFibGVzCglwcm90ZWN0ZWQgc3RhdGljIFRlc3RpbmdFbnZpcm9ubWVudCBFTlYgPSBudWxsOwoJcHJvdGVjdGVkIHN0YXRpYyBJSmF2YVByb2plY3RbXSBBTExfUFJPSkVDVFM7Cglwcm90ZWN0ZWQgc3RhdGljIElKYXZhUHJvamVjdCBKRFRfQ09SRV9QUk9KRUNUOwoJcHJvdGVjdGVkIHN0YXRpYyBJQ29tcGlsYXRpb25Vbml0IFBBUlNFUl9XT1JLSU5HX0NPUFk7Cglwcm90ZWN0ZWQgZmluYWwgc3RhdGljIFN0cmluZyBCSUdfUFJPSkVDVF9OQU1FID0gIkJpZ1Byb2plY3QiOwoJcHJvdGVjdGVkIHN0YXRpYyBKYXZhUHJvamVjdCBCSUdfUFJPSkVDVDsKCXByb3RlY3RlZCBzdGF0aWMgZmluYWwgU3RyaW5nIEJJR19KQVIxX05BTUUgPSAiYmlnMS5qYXIiOwoJcHJvdGVjdGVkIHN0YXRpYyBmaW5hbCBTdHJpbmcgQklHX0pBUjJfTkFNRSA9ICJiaWcyLmphciI7Ci8vCXByb3RlY3RlZCBmaW5hbCBzdGF0aWMgU3RyaW5nIEpVTklUX1BST0pFQ1RfTkFNRSA9ICJqdW5pdCI7Ci8vCXByb3RlY3RlZCBzdGF0aWMgSUphdmFQcm9qZWN0IEpVTklUX1BST0pFQ1Q7CgoJLy8gQ29tcGlsYXRpb24gdmFyaWFibGUKCXB1YmxpYyBzdGF0aWMgZmluYWwgU3RyaW5nIENPTVBJTEVSX09VVFBVVF9ESVI7CglzdGF0aWMgewoJCVN0cmluZyBvdXRwdXREaXIgPSBudWxsOwoJCVN0cmluZyBjb250YWluZXIgPSBTeXN0ZW0uZ2V0UHJvcGVydHkoInVzZXIuaG9tZSIpOwoJCWlmIChjb250YWluZXIgPT0gbnVsbCl7CgkJCUlXb3Jrc3BhY2Ugd29ya3NwYWNlID0gUmVzb3VyY2VzUGx1Z2luLmdldFdvcmtzcGFjZSgpOwoJCQlJV29ya3NwYWNlUm9vdCB3b3Jrc3BhY2VSb290ID0gd29ya3NwYWNlLmdldFJvb3QoKTsKCQkJRmlsZSBwbHVnaW5EaXIgPSB3b3Jrc3BhY2VSb290LmdldFByb2plY3QoSmF2YUNvcmUuUExVR0lOX0lEKS5nZXRMb2NhdGlvbigpLnRvRmlsZSgpOwoJCQl0cnkgewoJCQkJb3V0cHV0RGlyID0gcGx1Z2luRGlyLmdldENhbm9uaWNhbFBhdGgoKSArIEZpbGUuc2VwYXJhdG9yICsgImJpbiI7CgkJCX0gY2F0Y2ggKElPRXhjZXB0aW9uIGUpIHsKCQkJCS8vIHNraXAKCQkJfQoJCX0gZWxzZSB7CgkJCW91dHB1dERpciA9IFV0aWwudG9OYXRpdmVQYXRoKGNvbnRhaW5lcikgKyBGaWxlLnNlcGFyYXRvciArICJiaW4iOwoJCX0KCQlpZiAob3V0cHV0RGlyID09IG51bGwpIHsKCQkJQ09NUElMRVJfT1VUUFVUX0RJUiA9ICJub25lIjsKCQl9IGVsc2UgewoJCQlDT01QSUxFUl9PVVRQVVRfRElSID0gIlwiIitvdXRwdXREaXIrIlwiIjsKCQl9Cgl9CgoKCS8vIEluZGV4IHZhcmlhYmxlcwoJcHJvdGVjdGVkIHN0YXRpYyBJbmRleE1hbmFnZXIgSU5ERVhfTUFOQUdFUiA9IEphdmFNb2RlbE1hbmFnZXIuZ2V0SW5kZXhNYW5hZ2VyKCk7CgoJLy8gVGVzdHMgaW5mb3MKCXByb3RlY3RlZCBzdGF0aWMgaW50IEFMTF9URVNUU19DT1VOVCA9IDA7Cglwcm90ZWN0ZWQgc3RhdGljIGludCBURVNUX1BPU0lUSU9OID0gMDsKCXByb3RlY3RlZCBzdGF0aWMgTGlzdCBURVNUU19OQU1FX0xJU1Q7CgoJLyoqCgkgKiBDb3VudCBvZiBtZWFzdXJlcyBkb25lIGZvciBhbGwgdGVzdHMuCgkgKiA8Yj4KCSAqIERlZmF1bHQgdmFsdWUgaXMgMTAgYnV0IGNhbiBiZSBtb2RpZmllZCB1c2luZyBzeXN0ZW0gcHJvcGVydHkgIm1lYXN1cmVzIi4KCSAqIDxiPgoJICogRm9yIGV4YW1wbGUsICItRG1lYXN1cmVzPTEiIHdpbGwgbWFrZSBhbGwgcGVyZm9ybWFuY2UgdGVzdCBzdWl0ZXMgdG8gcnVuCgkgKiBvbmx5IDEgaXRlcmF0aW9uIGZvciBlYWNoIHRlc3QuCgkgKi8KCXByb3RlY3RlZCBmaW5hbCBzdGF0aWMgaW50IE1FQVNVUkVTX0NPVU5UOwoJc3RhdGljIHsKCQlTdHJpbmcgbWVhc3VyZXMgPSBTeXN0ZW0uZ2V0UHJvcGVydHkoIm1lYXN1cmVzIiwgIjEwIik7CgkJaW50IGNvdW50ID0gMTA7CgkJdHJ5IHsKCQkJY291bnQgPSBJbnRlZ2VyLnBhcnNlSW50KG1lYXN1cmVzKTsKCQkJaWYgKGNvdW50IDwgMCB8fCBjb3VudCA+IDIwKSB7CgkJCQlTeXN0ZW0ub3V0LnByaW50bG4oIklORk86IE1lYXN1cmVzIHBhcmFtZXRlciAoIitjb3VudCsiKSBpcyBpZ25vcmVkIGFzIGl0IGlzIGFuIGludmFsaWQgdmFsdWUhIChzaG91bGQgYmUgYmV0d2VlbiAwIGFuZCAyMCkiKTsKCQkJCWNvdW50ID0gMTA7CgkJCX0gZWxzZSBpZiAoY291bnQgIT0gMTApIHsKCQkJCVN5c3RlbS5vdXQucHJpbnRsbigiV0FSTklORzogTWVhc3VyZXMgY291bnQgaGFzIGJlZW4gY2hhbmdlZCB3aGlsZSBydW5uaW5nIHRoaXMgdGVzdCA9ICIrY291bnQrIiBpbnN0ZWFkIG9mIDEwIG5vcm1hbGx5ISIpOwoJCQl9CgkJfQoJCWNhdGNoIChOdW1iZXJGb3JtYXRFeGNlcHRpb24gbmZlKSB7CgkJCS8vIHVzZSBkZWZhdWx0IHZhbHVlCgkJCVN5c3RlbS5vdXQucHJpbnRsbigiSU5GTzogU3BlY2lmaWVkICdtZWFzdXJlcycgVk0gYXJndW1lbnQgKD0iK21lYXN1cmVzKyIpIGlzIGlnbm9yZWQgYXMgaXQgaXMgbm90IGFuIGludGVnZXIgKDAtMjApISIpOwoJCX0KCQlNRUFTVVJFU19DT1VOVCA9IGNvdW50OwoJfQoKCS8vIFNjZW5hcmlvIGluZm9ybWF0aW9uCglTdHJpbmcgc2NlbmFyaW9SZWFkYWJsZU5hbWUsIHNjZW5hcmlvU2hvcnROYW1lOwoJU3RyaW5nQnVmZmVyIHNjZW5hcmlvQ29tbWVudDsKCXN0YXRpYyBNYXAgU0NFTkFSSUlfQ09NTUVOVCA9IG5ldyBIYXNoTWFwKCk7CgoJLy8gVGltZSBtZWFzdXJpbmcKCWludCBuYk1lYXN1cmVzOwoJbG9uZyBzdGFydE1lYXN1cmluZywgdGVzdER1cmF0aW9uOwoKCS8vIEVycm9yIHRocmVzaG9sZC4gU3RhdGlzdGljIHNob3VsZCBub3QgYmUgdGFrZSBpbnRvIGFjY291bnQgd2hlbiBpdCdzIHJlYWNoZWQKCXByb3RlY3RlZCBmaW5hbCBzdGF0aWMgZG91YmxlIEVSUk9SX1RIUkVTSE9MRCA9IDAuMDA1OyAvLyBkZWZhdWx0IGlzIDAuNSUKCXByb3RlY3RlZCBmaW5hbCBzdGF0aWMgU3RyaW5nIEVSUk9SX1NUUklORzsKCXN0YXRpYyB7CgkJTnVtYmVyRm9ybWF0IHZhbHVlRm9ybWF0ID0gTnVtYmVyRm9ybWF0LmdldE51bWJlckluc3RhbmNlKCk7CgkJdmFsdWVGb3JtYXQuc2V0TWF4aW11bUZyYWN0aW9uRGlnaXRzKDEpOwoJCUVSUk9SX1NUUklORyA9IHZhbHVlRm9ybWF0LmZvcm1hdChFUlJPUl9USFJFU0hPTEQqMTAwKTsKCX0KCgkvKioKCSAqIFZhcmlhYmxlIHVzZWQgZm9yIGxvZyBmaWxlcy4KCSAqIExvZyBmaWxlcyBhcmUgdXNlZCBpbiBjb25qdW5jdGlvbiB3aXRoIHtAbGluayBKZHRDb3JlUGVyZm9ybWFuY2VNZXRlcn0gY2xhc3MuCgkgKiBUaGVzZSBhcmUgZmlsZSB3aGVyZSBDUFUgdGltZXMgb2YgZWFjaCB0ZXN0IG9mIHN1YmNsYXNzZXMgYXJlIHN0b3JlZC4KCSAqIFRoaXMgc3BlY2lmaWMgd2F5IHRvIHJ1biBwZXJmb3JtYW5jZSB0ZXN0cyBpcyBhY3RpdmF0ZWQgYnkgc3BlY2lmeWluZwoJICogZm9sbG93aW5nIG9wdGlvbnM6CgkgKgkJLURQZXJmb3JtYW5jZU1ldGVyRmFjdG9yeT1vcmcuZWNsaXBzZS5qZHQuY29yZS50ZXN0cy5wZXJmb3JtYW5jZTpvcmcuZWNsaXBzZS5qZHQuY29yZS50ZXN0cy5wZXJmb3JtYW5jZS51dGlsLkpkdENvcmVQZXJmb3JtYW5jZU1ldGVyRmFjdG9yeQoJICoJCS1EbG9nRGlyPWRpcmVjdG9yeSB3aGVyZSB5b3Ugd2FudCB0byB3cml0ZSBsb2cgZmlsZXMgKGZvciBleGFtcGxlIGQ6L3Vzci9PVEkvdGVzdHMvcGVyZnMvc3RhdHMpCgkgKgoJICovCgkvLyBTdG9yZSBkaXJlY3Rvcnkgd2hlcmUgdG8gcHV0IGZpbGVzCglwcml2YXRlIGZpbmFsIHN0YXRpYyBGaWxlIElOVkFMSURfRElSID0gbmV3IEZpbGUoIkludmFsaWQiKTsKCXByb3RlY3RlZCBzdGF0aWMgRmlsZSBMT0dfRElSOwoJLy8gVHlwZXMgb2Ygc3RhdGlzdGljIHdoaWNoIGNhbiBiZSBzdG9yZWQuCglwcm90ZWN0ZWQgZmluYWwgc3RhdGljIFN0cmluZ1tdIERJTV9OQU1FUyA9IHsgImNwdSIsICJlbGFwc2VkIiwgImhlYXAiIH07CgkvLyBNYWluIHZlcnNpb24gd2hpY2ggaXMgbG9nZ2VkCglwcm90ZWN0ZWQgZmluYWwgc3RhdGljIFN0cmluZyBMT0dfVkVSU0lPTjsKCXN0YXRpYyB7CgkJU3RyaW5nIHZlcnNpb24gPSBuZXcgTWFpbihudWxsLypvdXRXcml0ZXIqLywgbnVsbC8qZXJyV3JpdGVyKi8sIGZhbHNlLypzeXN0ZW1FeGl0Ki8sIG51bGwvKm9wdGlvbnMqLywgbnVsbC8qcHJvZ3Jlc3MqLykuYmluZCgiY29tcGlsZXIudmVyc2lvbiIpOwoJCXZlcnNpb24gPSB2ZXJzaW9uLnN1YnN0cmluZygwLCB2ZXJzaW9uLmluZGV4T2YoJywnKSk7CgkJaWYgKHZlcnNpb24uc3RhcnRzV2l0aCgiMC4iKSkgewoJCQl2ZXJzaW9uID0gInZfIit2ZXJzaW9uLnN1YnN0cmluZygyKTsKCQl9CgkJTE9HX1ZFUlNJT04gPSB2ZXJzaW9uOwoJfQoJLy8gUGF0Y2ggdmVyc2lvbiBjdXJyZW50bHkgYXBwbGllZDogbWF5IGJlIG51bGwhCglwcm90ZWN0ZWQgZmluYWwgc3RhdGljIFN0cmluZyBQQVRDSF9JRCA9IFN5c3RlbS5nZXRQcm9wZXJ0eSgicGF0Y2giKTsKCXByb3RlY3RlZCBzdGF0aWMgU3RyaW5nIFJVTl9JRDsKCgkvLyBGb3JtYXQgdG8gc3RvcmUvZGlzcGxheSBudW1iZXJzCglwcml2YXRlIE51bWJlckZvcm1hdCBwZXJjZW50Rm9ybWF0ID0gTnVtYmVyRm9ybWF0LmdldFBlcmNlbnRJbnN0YW5jZSgpOwoJcHJpdmF0ZSBmaW5hbCBOdW1iZXJGb3JtYXQgZDJGb3JtYXQgPSBOdW1iZXJGb3JtYXQuZ2V0TnVtYmVySW5zdGFuY2UoKTsKCXsKCQl0aGlzLnBlcmNlbnRGb3JtYXQuc2V0TWF4aW11bUZyYWN0aW9uRGlnaXRzKDEpOwoJCXRoaXMuZDJGb3JtYXQuc2V0TWF4aW11bUZyYWN0aW9uRGlnaXRzKDIpOwoJfQoKCS8vIEZpbHRlciB0byBnZXQgb25seSB0aGUgMy4wIHBsdWdpbnMKCWNsYXNzIEZ1bGxTb3VyY2VQcm9qZWN0c0ZpbHRlciBpbXBsZW1lbnRzIEZpbGVGaWx0ZXIgewoJCXB1YmxpYyBib29sZWFuIGFjY2VwdChGaWxlIHByb2plY3QpIHsKCQkJaWYgKHByb2plY3QuaXNEaXJlY3RvcnkoKSkgewoJCQkJU3RyaW5nVG9rZW5pemVyIHRva2VuaXplciA9IG5ldyBTdHJpbmdUb2tlbml6ZXIocHJvamVjdC5nZXROYW1lKCksICIuIik7CgkJCQlTdHJpbmcgdG9rZW4gPSB0b2tlbml6ZXIubmV4dFRva2VuKCk7CgkJCQlpZiAodG9rZW4uZXF1YWxzKCJvcmciKSAmJiB0b2tlbml6ZXIuaGFzTW9yZVRva2VucygpKSB7CgkJCQkJdG9rZW4gPSB0b2tlbml6ZXIubmV4dFRva2VuKCk7CgkJCQkJaWYgKHRva2VuLmVxdWFscygianVuaXQiKSAmJiAhdG9rZW5pemVyLmhhc01vcmVUb2tlbnMoKSkgewoJCQkJCQlyZXR1cm4gdHJ1ZTsKCQkJCQl9CgkJCQkJaWYgKHRva2VuLmVxdWFscygiYXBhY2hlIikpIHsKCQkJCQkJdG9rZW4gPSB0b2tlbml6ZXIubmV4dFRva2VuKCk7CgkJCQkJCWlmICh0b2tlbi5lcXVhbHMoImFudCIpIHx8IHRva2VuLmVxdWFscygibHVjZW5lIikpIHsKCQkJCQkJCXJldHVybiB0cnVlOwoJCQkJCQl9CgkJCQkJCXJldHVybiBmYWxzZTsKCQkJCQl9CgkJCQkJaWYgKHRva2VuLmVxdWFscygiZWNsaXBzZSIpICYmIHRva2VuaXplci5oYXNNb3JlVG9rZW5zKCkpIHsKCQkJCQkJcmV0dXJuIHRydWU7CgkJCQkJfQoJCQkJfQoJCQl9CgkJCXJldHVybiBmYWxzZTsKCQl9Cgl9CgoJLyoqCgkgKiBJbml0aWFsaXplIGxvZyBkaXJlY3RvcnkuCgkgKgoJICogRGlyZWN0b3J5IHdoZXJlIGxvZyBmaWxlcyBtdXN0IGJlIHB1dCBpcyBzcGVjaWZpZWQgYnkgU3lzdGVtIHByb3BlcnR5IDxjb2RlPmxvZ0RpcjwvY29kZT4uCgkgKiBGb3IgZXhhbXBsZSwgaWYgdXNlciB3YW50IHRvIHN0b3JlIGxvZyBmaWxlcyBpbiBkOi91c3IvT1RJL3Rlc3RzL3BlcmZzL3N0YXRzLAoJICogdGhlbiBoZSBoYXMgdG8gc3BlY2lmeTogLURsb2dEaXI9ZDovdXNyL09USS90ZXN0cy9wZXJmcy9zdGF0cyBpbiBWTSBBcmd1bWVudHMgb2YgaGlzCgkgKiBwZXJmb3JtYW5jZSB0ZXN0IGxhdW5jaCBjb25maWd1cmF0aW9uLgoJICoKCSAqIENBVVRJT046IFBhcmVudCBkaXJlY3RvcnkgYXQgbGVhc3QgPGI+bXVzdDwvYj4gZXhpc3QgYmVmb3JlIHJ1bm5pbmcgdGVzdCBvdGhlcndpc2UKCSAqIGl0IHdvbid0IGJlIGNyZWF0ZWQgYW5kIHRpbWVzIHdvbid0IGJlIGxvZ2dlZC4KCSAqIFRoaXMgd2FzIGludGVudGlvbmFsIHRvIGF2b2lkIHVuZXhwZWN0ZWQgbG9nIGZpbGVzIGNyZWF0aW9uIChlc3BlY2lhbGx5IGR1cmluZyBuaWdodGx5L2ludGVncmF0aW9uIGJ1aWxkcykuCgkgKi8KCXByb3RlY3RlZCBzdGF0aWMgdm9pZCBpbml0TG9nRGlyKCkgewoJCVN0cmluZyBsb2dEaXIgPSBTeXN0ZW0uZ2V0UHJvcGVydHkoImxvZ0RpciIpOwoJCUZpbGUgZGlyID0gbnVsbDsKCQlpZiAobG9nRGlyICE9IG51bGwpIHsKCQkJLy8gVmVyaWZ5IHRoYXQgcGFyZW50IGxvZyBkaXIgaXMgdmFsaWQgaWYgZXhpc3QKCQkJZGlyID0gbmV3IEZpbGUobG9nRGlyKTsKCQkJaWYgKGRpci5leGlzdHMoKSkgewoJCQkJaWYgKCFkaXIuaXNEaXJlY3RvcnkoKSkgewoJCQkJCVN5c3RlbS5lcnIucHJpbnRsbihsb2dEaXIrIiBpcyBub3QgYSB2YWxpZCBkaXJlY3RvcnksIGxvZyBmaWxlcyB3aWxsIE5PVCBiZSB3cml0dGVuISIpOwoJCQkJCWRpciA9IElOVkFMSURfRElSOwoJCQkJfQoJCQl9IGVsc2UgewoJCQkJLy8gQ3JlYXRlIHBhcmVudCBkaXIgaWYgbmVjZXNzYXJ5CgkJCQlpbnQgbj0wOwoJCQkJYm9vbGVhbiBjcmVhdGVkID0gZmFsc2U7CgkJCQl3aGlsZSAoIWNyZWF0ZWQgJiYgbjwzKSB7CgkJCQkJY3JlYXRlZCA9IGRpci5ta2RpcigpOwoJCQkJCWlmICghY3JlYXRlZCkgewoJCQkJCQlkaXIgPSBkaXIuZ2V0UGFyZW50RmlsZSgpOwoJCQkJCX0KCQkJCQluKys7CgkJCQl9CgkJCQlpZiAoIWNyZWF0ZWQpIHsKCQkJCQlTeXN0ZW0uZXJyLnByaW50bG4oIkNhbm5vdCBjcmVhdGUgIitsb2dEaXIrIiwgbG9nIGZpbGVzIHdpbGwgTk9UIGJlIHdyaXR0ZW4hIik7CgkJCQkJZGlyID0gSU5WQUxJRF9ESVI7CgkJCQl9CgkJCX0KCgkJCS8vIENyZWF0ZSBMb2cgZGlyCgkJCVN0cmluZ1tdIHN1YmRpcnMgPSAoUEFUQ0hfSUQgPT0gbnVsbCkKCQkJCT8gbmV3IFN0cmluZ1tdIHtMT0dfVkVSU0lPTiwgUlVOX0lEIH0KCQkJCTogbmV3IFN0cmluZ1tdIHtMT0dfVkVSU0lPTiwgUEFUQ0hfSUQsIFJVTl9JRCB9OwoJCQlmb3IgKGludCBpPTA7IGk8c3ViZGlycy5sZW5ndGg7IGkrKykgewoJCQkJZGlyID0gbmV3IEZpbGUoZGlyLCBzdWJkaXJzW2ldKTsKCQkJCWlmIChkaXIuZXhpc3RzKCkpIHsKCQkJCQlpZiAoIWRpci5pc0RpcmVjdG9yeSgpKSB7CgkJCQkJCVN5c3RlbS5lcnIucHJpbnRsbihkaXIuZ2V0UGF0aCgpKyIgaXMgbm90IGEgdmFsaWQgZGlyZWN0b3J5LCBsb2cgZmlsZXMgd2lsbCBOT1QgYmUgd3JpdHRlbiEiKTsKCQkJCQkJZGlyPSBJTlZBTElEX0RJUjsKCQkJCQkJYnJlYWs7CgkJCQkJfQoJCQkJfSBlbHNlIGlmICghZGlyLm1rZGlycygpKSB7CgkJCQkJU3lzdGVtLmVyci5wcmludGxuKCJDYW5ub3QgY3JlYXRlICIrZGlyLmdldFBhdGgoKSsiLCBsb2cgZmlsZXMgd2lsbCBOT1QgYmUgd3JpdHRlbiEiKTsKCQkJCQlkaXIgPSBJTlZBTElEX0RJUjsKCQkJCQlicmVhazsKCQkJCX0KCQkJfQoJCX0KCQlMT0dfRElSID0gZGlyOwoJfQoKCS8qKgoJICogQHBhcmFtIG5hbWUKCSAqLwoJcHVibGljIEZ1bGxTb3VyY2VXb3Jrc3BhY2VUZXN0cyhTdHJpbmcgbmFtZSkgewoJCXN1cGVyKG5hbWUpOwoJfQoKCS8qKgoJICogQ3JlYXRlIHRlc3Qgc3VpdGUgZm9yIGEgZ2l2ZW4gVGVzdENhc2UgY2xhc3MuCgkgKgoJICogVXNlIHRoaXMgbWV0aG9kIGZvciBhbGwgSkRUL0NvcmUgcGVyZm9ybWFuY2UgdGVzdCB1c2luZyBmdWxsIHNvdXJjZSB3b3Jrc3BhY2UuCgkgKiBBbGwgdGVzdCBjb3VudCBpcyBjb21wdXRlZCB0byBrbm93IHdoZW4gdGVzdHMgYXJlIGFib3V0IHRvIGJlIGZpbmlzaGVkLgoJICoKCSAqIEBwYXJhbSB0ZXN0Q2xhc3MgVGVzdENhc2UgdGVzdCBjbGFzcwoJICogQHJldHVybiB0ZXN0IHN1aXRlCgkgKi8KCXN0YXRpYyBUZXN0IGJ1aWxkU3VpdGUoQ2xhc3MgdGVzdENsYXNzKSB7CgoJCS8vIENyZWF0ZSB0ZXN0cwoJCVN0cmluZyBjbGFzc05hbWUgPSB0ZXN0Q2xhc3MuZ2V0TmFtZSgpOwoJCVRlc3RTdWl0ZSBzdWl0ZSA9IG5ldyBUZXN0U3VpdGUoY2xhc3NOYW1lKTsKCQlMaXN0IHRlc3RzID0gYnVpbGRUZXN0c0xpc3QodGVzdENsYXNzKTsKCQlpbnQgc2l6ZSA9IHRlc3RzLnNpemUoKTsKCQlURVNUU19OQU1FX0xJU1QgPSBuZXcgQXJyYXlMaXN0KHNpemUpOwoJCWZvciAoaW50IGk9MDsgaTxzaXplOyBpKyspIHsKCQkJRnVsbFNvdXJjZVdvcmtzcGFjZVRlc3RzIHRlc3QgPSAoRnVsbFNvdXJjZVdvcmtzcGFjZVRlc3RzKXRlc3RzLmdldChpKTsKCQkJc3VpdGUuYWRkVGVzdCh0ZXN0KTsKCQkJVEVTVFNfTkFNRV9MSVNULmFkZCh0ZXN0LmdldE5hbWUoKSk7CgkJfQoJCUFMTF9URVNUU19DT1VOVCArPSBzdWl0ZS50ZXN0Q291bnQoKTsKCgkJLy8gSW5pdCBsb2cgZGlyIGlmIG5lY2Vzc2FyeQoJCWlmIChMT0dfRElSID09IG51bGwpIHsKCQkJaWYgKFJVTl9JRCA9PSBudWxsKSB7CgkJCQlSVU5fSUQgPSBzdWl0ZVR5cGVTaG9ydE5hbWUodGVzdENsYXNzKTsKCQkJfQoJCQlpbml0TG9nRGlyKCk7CgkJfQoKCQkvLyBSZXR1cm4gY3JlYXRlZCB0ZXN0cwoJCXJldHVybiBzdWl0ZTsKCX0KCgkvKioKCSAqIENyZWF0ZSBwcmludCBzdHJlYW1zIChvbmUgZm9yIGVhY2ggdHlwZSBvZiBzdGF0aXN0aWMpLgoJICogTG9nIGZpbGUgbmFtZXMgaGF2ZSBhbGwgc2FtZSBwcmVmaXggYmFzZWQgb24gdGVzdCBjbGFzcyBuYW1lLAoJICogaW5jbHVkZSB0eXBlIG9mIHN0YXRpc3RpYyBzdG9yZWQgaW4gaXQgYW5kIGFsd2F5cyBoYXZlIGV4dGVuc2lvbiAiLmxvZyIuCgkgKgoJICogSWYgbG9nIGZpbGUgZG9lcyBub3QgZXhpc3QsIHRoZW4gYWRkIGNvbHVtbiBoZWFkZXJzIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIGZpbGUuCgkgKgoJICogVGhpcyBtZXRob2QgZG9lcyBub3RoaW5nIGlmIGxvZyBmaWxlcyBkaXJlY3RvcnkgaGFzIG5vdCBiZWVuIGluaXRpYWxpemVkCgkgKiAod2hpY2ggc2hvdWxkIGJlIHRoZSBjYXNlIG1vc3Qgb2YgdGltZXMgYW5kIGVzcGVjaWFsbHkgd2hpbGUgcnVubmluZyBuaWdodGx5L2ludGVncmF0aW9uIGJ1aWxkIHBlcmZvcm1hbmNlIHRlc3RzKS4KCSAqLwoJc3RhdGljIHZvaWQgY3JlYXRlUHJpbnRTdHJlYW0oQ2xhc3MgdGVzdENsYXNzLCBQcmludFN0cmVhbVtdIGxvZ1N0cmVhbXMsIGludCBjb3VudCwgU3RyaW5nIHByZWZpeCkgewoJCWlmIChMT0dfRElSICE9IG51bGwpIHsKCQkJZm9yIChpbnQgaT0wLCBsbj1ESU1fTkFNRVMubGVuZ3RoOyBpPGxuOyBpKyspIHsKCQkJCVN0cmluZyBzdWl0ZVR5cGVOYW1lID0gc3VpdGVUeXBlU2hvcnROYW1lKHRlc3RDbGFzcyk7CgkJCQlGaWxlIGxvZ0ZpbGUgPSBuZXcgRmlsZShMT0dfRElSLCBzdWl0ZVR5cGVOYW1lKydfJytESU1fTkFNRVNbaV0rIi5sb2ciKTsKCQkJCWlmIChUT1VDSCkgewoJCQkJCVN5c3RlbS5vdXQucHJpbnRsbigiTG9nIGZpbGUgIitsb2dGaWxlLmdldFBhdGgoKSsiIHdvdWxkIGJlIG9wZW5lZC4iKTsKCQkJCQlyZXR1cm47CgkJCQl9CgkJCQl0cnkgewoJCQkJCWJvb2xlYW4gZmlsZUV4aXN0ID0gbG9nRmlsZS5leGlzdHMoKTsKCQkJCQlpZiAobG9nU3RyZWFtc1tpXSAhPSBudWxsKSB7IC8vIGNsb3NpbmcgcHJldmlvdXMgc2VyaWVzOyBsYXN0IHNlcmllcyBpcyBjbG9zZWQgYnkgdGhlIHByb2Nlc3MKCQkJCQkJbG9nU3RyZWFtc1tpXS5jbG9zZSgpOwoJCQkJCX0KCQkJCQlsb2dTdHJlYW1zW2ldID0gbmV3IFByaW50U3RyZWFtKG5ldyBGaWxlT3V0cHV0U3RyZWFtKGxvZ0ZpbGUsIHRydWUpKTsKCQkJCQlpZiAobG9nU3RyZWFtc1tpXSAhPSBudWxsKSB7CgkJCQkJCWlmICghZmlsZUV4aXN0KSB7CgkJCQkJCQlsb2dTdHJlYW1zW2ldLnByaW50KCJEYXRlICBcdFRpbWUgIFx0Iik7CgkJCQkJCQlmb3IgKGludCBqPTA7IGo8Y291bnQ7IGorKykgewoJCQkJCQkJCVN0cmluZyB0ZXN0TmFtZSA9ICgoU3RyaW5nKSBURVNUU19OQU1FX0xJU1QuZ2V0KGopKS5zdWJzdHJpbmcoNCsocHJlZml4PT1udWxsPzA6cHJlZml4Lmxlbmd0aCgpKSk7IC8vIDQ9InRlc3QiLmxlbmd0aCgpCgkJCQkJCQkJbG9nU3RyZWFtc1tpXS5wcmludCh0ZXN0TmFtZSsnXHQnKTsKCQkJCQkJCX0KCQkJCQkJCWxvZ1N0cmVhbXNbaV0ucHJpbnRsbigiQ29tbWVudCIpOwoKCQkJCQkJfQoJCQkJCQkvLyBMb2cgZGF0ZSBhbmQgdGltZQoJCQkJCQlEYXRlIGRhdGUgPSBuZXcgRGF0ZShTeXN0ZW0uY3VycmVudFRpbWVNaWxsaXMoKSk7CgkJCQkJCWxvZ1N0cmVhbXNbaV0ucHJpbnQoRGF0ZUZvcm1hdC5nZXREYXRlSW5zdGFuY2UoMykuZm9ybWF0KGRhdGUpKydcdCcpOwoJCQkJCQlsb2dTdHJlYW1zW2ldLnByaW50KERhdGVGb3JtYXQuZ2V0VGltZUluc3RhbmNlKDMpLmZvcm1hdChkYXRlKSsnXHQnKTsKCQkJCQkJU3lzdGVtLm91dC5wcmludGxuKCJMb2cgZmlsZSAiK2xvZ0ZpbGUuZ2V0UGF0aCgpKyIgb3BlbmVkLiIpOwoJCQkJCX0gZWxzZSB7CgkJCQkJCVN5c3RlbS5lcnIucHJpbnRsbigiQ2Fubm90IG9wZW4gIitsb2dGaWxlLmdldFBhdGgoKSsiISEhIik7CgkJCQkJfQoJCQkJfSBjYXRjaCAoRmlsZU5vdEZvdW5kRXhjZXB0aW9uIGUpIHsKCQkJCQlTeXN0ZW0uZXJyLnByaW50bG4oIkNhbm5vdCBmaW5kIGZpbGUgIitsb2dGaWxlLmdldFBhdGgoKSsiISEhIik7CgkJCQl9CgkJCX0KCQl9Cgl9CgoJLyoKCSAqIFJldHVybnMgdGhlIE9TIHBhdGggdG8gdGhlIGRpcmVjdG9yeSB0aGF0IGNvbnRhaW5zIHRoaXMgcGx1Z2luLgoJICovCglzdGF0aWMgU3RyaW5nIGdldFBsdWdpbkJpbmFyaWVzRGlyZWN0b3J5UGF0aCgpIHsKCQl0cnkgewoJCQlVUkwgcGxhdGZvcm1VUkwgPSBQbGF0Zm9ybS5nZXRCdW5kbGUoIm9yZy5lY2xpcHNlLmpkdC5jb3JlLnRlc3RzLmJpbmFyaWVzIikuZ2V0RW50cnkoIi8iKTsKCQkJcmV0dXJuIG5ldyBGaWxlKEZpbGVMb2NhdG9yLnRvRmlsZVVSTChwbGF0Zm9ybVVSTCkuZ2V0RmlsZSgpKS5nZXRBYnNvbHV0ZVBhdGgoKTsKCQl9IGNhdGNoIChJT0V4Y2VwdGlvbiBlKSB7CgkJCWUucHJpbnRTdGFja1RyYWNlKCk7CgkJfQoJCXJldHVybiBudWxsOwoJfQoKCS8qKgoJICogUmV0dXJuIGEgc2hvcnQgbmFtZSBmb3IgYSBnaXZlbiBzdWl0ZSB0ZXN0LgoJICogVHlwaWNhbGx5IHJlbW92ZSBwcmVmaXggIkZ1bGxTb3VyY2VXb3Jrc3BhY2UiIGFuZCBzdWZmaXggIlRlc3QiCgkgKi8KCXByb3RlY3RlZCBzdGF0aWMgU3RyaW5nIHN1aXRlVHlwZVNob3J0TmFtZShDbGFzcyB0ZXN0Q2xhc3MpIHsKCQlTdHJpbmcgY2xhc3NOYW1lID0gdGVzdENsYXNzLmdldE5hbWUoKTsKCQlpbnQgc3RhcnRJbmRleCA9IGNsYXNzTmFtZS5pbmRleE9mKCJGdWxsU291cmNlV29ya3NwYWNlIik7CgkJaW50IGVuZEluZGV4ID0gY2xhc3NOYW1lLmxhc3RJbmRleE9mKCJUZXN0Iik7CgkJaWYgKHN0YXJ0SW5kZXggPCAwKSByZXR1cm4gbnVsbDsKCQlzdGFydEluZGV4ICs9ICJGdWxsU291cmNlV29ya3NwYWNlIi5sZW5ndGgoKTsKCQlyZXR1cm4gY2xhc3NOYW1lLnN1YnN0cmluZyhzdGFydEluZGV4LCBlbmRJbmRleCk7Cgl9CgoJLyoqCgkgKiBMb2cgdGVzdCBwZXJmb3JtYW5jZSByZXN1bHQgYW5kIGNsb3NlIHN0cmVhbSBpZiBpdCB3YXMgbGFzdCBvbmUuCgkgKi8KCXByb3RlY3RlZCB2b2lkIGxvZ1BlcmZSZXN1bHQoUHJpbnRTdHJlYW1bXSBsb2dTdHJlYW1zLCBpbnQgY291bnQpIHsKCQlpZiAoVE9VQ0gpIHJldHVybjsKCgkJLy8gUGVyZnMgY29tbWVudCBidWZmZXJzCgkJaW50IGxlbmd0aCA9IERJTV9OQU1FUy5sZW5ndGg7CgkJU3RyaW5nW10gY29tbWVudHMgPSBuZXcgU3RyaW5nW2xlbmd0aF07CgoJCS8vIExvZyBwZXJmIHJlc3VsdAoJCWJvb2xlYW4gaGF2ZVN0YXRzID0gSmR0Q29yZVBlcmZvcm1hbmNlTWV0ZXIuU1RBVElTVElDUyAhPSBudWxsOwoJCWlmIChoYXZlU3RhdHMpIHsKCQkJRGF0YVBvaW50W10gZGF0YVBvaW50cyA9IChEYXRhUG9pbnRbXSkgSmR0Q29yZVBlcmZvcm1hbmNlTWV0ZXIuU1RBVElTVElDUy5nZXQodGhpcy5zY2VuYXJpb1JlYWRhYmxlTmFtZSk7CgkJCWlmIChkYXRhUG9pbnRzICE9IG51bGwpIHsKCQkJCVN0YXRpc3RpY3Mgc3RhdGlzdGljcyA9IG5ldyBTdGF0aXN0aWNzKGRhdGFQb2ludHMpOwoJCQkJZm9yIChpbnQgaWR4PTA7IGlkeDxsZW5ndGg7IGlkeCsrKSB7CgkJCQkJc3RvcmVEaW1lbnNpb24obG9nU3RyZWFtcywgY29tbWVudHMsIHN0YXRpc3RpY3MsIGlkeCk7CgkJCQl9CgkJCX0gZWxzZSB7CgkJCQl0cnkgewoJCQkJCWhhdmVTdGF0cyA9IGZhbHNlOwoJCQkJCVRocmVhZC5zbGVlcCgxMDAwKTsKCQkJCQlTeXN0ZW0uZXJyLnByaW50bG4odGhpcy5zY2VuYXJpb1Nob3J0TmFtZSsiOiB3ZSBzaG91bGQgaGF2ZSBzdG9yZWQgc3RhdGlzdGljcyEiKTsKCQkJCQlUaHJlYWQuc2xlZXAoMTAwMCk7CgkJCQl9IGNhdGNoIChJbnRlcnJ1cHRlZEV4Y2VwdGlvbiBlKSB7CgkJCQkJLy8gZG8gbm90aGluZwoJCQkJfQoJCQl9CgkJfQoKCQkvLyBVcGRhdGUgY29tbWVudCBidWZmZXJzCgkJU3RyaW5nQnVmZmVyW10gc2NlbmFyaW9Db21tZW50cyA9IChTdHJpbmdCdWZmZXJbXSkgU0NFTkFSSUlfQ09NTUVOVC5nZXQoZ2V0Q2xhc3MoKSk7CgkJaWYgKHNjZW5hcmlvQ29tbWVudHMgPT0gbnVsbCkgewoJCQlzY2VuYXJpb0NvbW1lbnRzID0gbmV3IFN0cmluZ0J1ZmZlcltsZW5ndGhdOwoJCQlTQ0VOQVJJSV9DT01NRU5ULnB1dChnZXRDbGFzcygpLCBzY2VuYXJpb0NvbW1lbnRzKTsKCQl9CgkJZm9yIChpbnQgaT0wOyBpPGxlbmd0aDsgaSsrKSB7CgkJCWlmICh0aGlzLnNjZW5hcmlvQ29tbWVudCAhPSBudWxsIHx8IGNvbW1lbnRzW2ldICE9IG51bGwpIHsKCQkJCWlmIChzY2VuYXJpb0NvbW1lbnRzW2ldID09IG51bGwpIHsKCQkJCQlzY2VuYXJpb0NvbW1lbnRzW2ldID0gbmV3IFN0cmluZ0J1ZmZlcigpOwoJCQkJfSBlbHNlIHsKCQkJCQlzY2VuYXJpb0NvbW1lbnRzW2ldLmFwcGVuZCgnICcpOwoJCQkJfQoJCQkJaWYgKHRoaXMuc2NlbmFyaW9Db21tZW50ID09IG51bGwpIHsKCQkJCQlzY2VuYXJpb0NvbW1lbnRzW2ldLmFwcGVuZCgiWyIrVEVTVF9QT1NJVElPTisiXSIpOwoJCQkJfSBlbHNlIHsKCQkJCQlzY2VuYXJpb0NvbW1lbnRzW2ldLmFwcGVuZCh0aGlzLnNjZW5hcmlvQ29tbWVudCk7CgkJCQl9CgkJCQlpZiAoY29tbWVudHNbaV0gIT0gbnVsbCkgewoJCQkJCWlmICh0aGlzLnNjZW5hcmlvQ29tbWVudCAhPSBudWxsKSBzY2VuYXJpb0NvbW1lbnRzW2ldLmFwcGVuZCgnLCcpOwoJCQkJCXNjZW5hcmlvQ29tbWVudHNbaV0uYXBwZW5kKGNvbW1lbnRzW2ldKTsKCQkJCX0KCQkJfQoJCX0KCgkJLy8gQ2xvc2UgbG9nCgkJaWYgKGNvdW50ID09IDApIHsKCQkJZm9yIChpbnQgaT0wLCBsbj1sb2dTdHJlYW1zLmxlbmd0aDsgaTxsbjsgaSsrKSB7CgkJCQlpZiAobG9nU3RyZWFtc1tpXSAhPSBudWxsKSB7CgkJCQkJaWYgKGhhdmVTdGF0cykgewoJCQkJCQlpZiAoc2NlbmFyaW9Db21tZW50c1tpXSAhPSBudWxsKSB7CgkJCQkJCQlsb2dTdHJlYW1zW2ldLnByaW50KHNjZW5hcmlvQ29tbWVudHNbaV0udG9TdHJpbmcoKSk7CgkJCQkJCX0KCQkJCQkJbG9nU3RyZWFtc1tpXS5wcmludGxuKCk7CgkJCQkJfQoJCQkJCWxvZ1N0cmVhbXNbaV0uY2xvc2UoKTsKCQkJCX0KCQkJfQoJCQlURVNUX1BPU0lUSU9OID0gMDsKCQl9Cgl9CgoJcHJpdmF0ZSB2b2lkIHN0b3JlRGltZW5zaW9uKFByaW50U3RyZWFtW10gbG9nU3RyZWFtcywgU3RyaW5nW10gY29tbWVudHMsIFN0YXRpc3RpY3Mgc3RhdGlzdGljcywgaW50IGluZGV4KSB7CgkgICAgU3lzdGVtLm91dC5wcmludGxuKCIJLSAiK3N0YXRpc3RpY3MudG9TdHJpbmcoaW5kZXgpKTsKCSAgICBkb3VibGUgc3RkZGV2ID0gc3RhdGlzdGljcy5nZXRTdGRkZXYoaW5kZXgpOwoJICAgIGRvdWJsZSBhdmVyYWdlID0gc3RhdGlzdGljcy5nZXRBdmVyYWdlKGluZGV4KTsKCSAgICBsb25nIGNvdW50ID0gc3RhdGlzdGljcy5nZXRDb3VudChpbmRleCk7CgkgICAgZG91YmxlIGVycm9yID0gc3RkZGV2IC8gTWF0aC5zcXJ0KGNvdW50KTsKCSAgICBpZiAoKGVycm9yL2F2ZXJhZ2UpID4gRVJST1JfVEhSRVNIT0xEKSB7CgkgICAgCS8vaWYgKGxvZ1N0cmVhbXNbMF0gIT0gbnVsbCkgbG9nU3RyZWFtc1swXS5wcmludCgiJyIpOyAvLyBkaXNhYmxlIG92ZXIgdGhyZXNob2xkIHJlc3VsdCBmb3IgeGxzIHRhYmxlCgkgICAgCVN5c3RlbS5vdXQucHJpbnRsbigiCVdBUk5JTkc6ICIrRElNX05BTUVTW2luZGV4XSsiIGVycm9yIGlzIG92ZXIgIitFUlJPUl9TVFJJTkcrIiU6ICIrdGhpcy5kMkZvcm1hdC5mb3JtYXQoc3RkZGV2KSsiL3NxcnQoIitjb3VudCsiKT0iKyB0aGlzLnBlcmNlbnRGb3JtYXQuZm9ybWF0KGVycm9yL2F2ZXJhZ2UpKTsKCSAgICAJY29tbWVudHNbaW5kZXhdID0gImVycj0iICsgdGhpcy5wZXJjZW50Rm9ybWF0LmZvcm1hdChlcnJvci9hdmVyYWdlKTsKCSAgICB9CgkgICAgaWYgKGxvZ1N0cmVhbXNbaW5kZXhdICE9IG51bGwpIHsKCSAgICAJbG9nU3RyZWFtc1tpbmRleF0ucHJpbnQoIiIrc3RhdGlzdGljcy5nZXRTdW0oaW5kZXgpKyJcdCIpOwoJICAgIH0KICAgIH0KCgkvKioKCSAqIFBlcmZvcm0gZ2Mgc2V2ZXJhbCB0aW1lcyB0byBiZSBzdXJlIHRoYXQgaXQgd29uJ3QgdGFrZSB0aW1lIHdoaWxlIGV4ZWN1dGluZyBjdXJyZW50IHRlc3QuCgkgKi8KCXByb3RlY3RlZCB2b2lkIHJ1bkdjKCkgewoJCWludCBpdGVyYXRpb25zID0gMDsKCQlsb25nIGRlbHRhPTAsIGZyZWU9MDsKCQlmb3IgKGludCBpPTA7IGk8TUFYX0dDOyBpKyspIHsKCQkJZnJlZSA9IFJ1bnRpbWUuZ2V0UnVudGltZSgpLmZyZWVNZW1vcnkoKTsKCQkJU3lzdGVtLmdjKCk7CgkJCWRlbHRhID0gUnVudGltZS5nZXRSdW50aW1lKCkuZnJlZU1lbW9yeSgpIC0gZnJlZTsKLy8JCQlpZiAoREVCVUcpIFN5c3RlbS5vdXQucHJpbnRsbigiTG9vcCBnYyAiKyArK2l0ZXJhdGlvbnMgKyAiIChmcmVlPSIrZnJlZSsiLCBkZWx0YT0iK2RlbHRhKyIpIik7CgkJCXRyeSB7CgkJCQlUaHJlYWQuc2xlZXAoVElNRV9HQyk7CgkJCX0gY2F0Y2ggKEludGVycnVwdGVkRXhjZXB0aW9uIGUpIHsKCQkJCS8vIGRvIG5vdGhpbmcKCQkJfQoJCX0KCQlpZiAoaXRlcmF0aW9ucyA9PSBNQVhfR0MgJiYgZGVsdGEgPiBERUxUQV9HQykgewoJCQkvLyBwZXJoYXBzIGdjIHdhcyBub3Qgd2VsbCBleGVjdXRlZAoJCQlTeXN0ZW0ub3V0LnByaW50bG4oIldBUk5JTkc6ICIrdGhpcy5zY2VuYXJpb1Nob3J0TmFtZSsiIHN0aWxsIGdldCAiK2RlbHRhKyIgdW5mcmVlYWJsZSBtZW1vcnkgKGZyZWU9IitmcmVlKyIsdG90YWw9IitSdW50aW1lLmdldFJ1bnRpbWUoKS50b3RhbE1lbW9yeSgpKyIpIGFmdGVyICIrTUFYX0dDKyIgZ2MuLi4iKTsKCQkJdHJ5IHsKCQkJCVRocmVhZC5zbGVlcCgxMDAwKTsKCQkJfSBjYXRjaCAoSW50ZXJydXB0ZWRFeGNlcHRpb24gZSkgewoJCQkJLy8gZG8gbm90aGluZwoJCQl9CgkJfQoJfQoKCS8qKgoJICogT3ZlcnJpZGUgc3VwZXIgaW1wbGVtZW50YXRpb24gdG86CgkgKiA8dWw+CgkgKgkJPGxpPnN0b3JlIHNjZW5hcmlvIG5hbWVzIGFuZCBjb21tZW50IChvbmUgc2NlbmFyaW8gcGVyIHRlc3QpPC9saT4KCSAqCQk8bGk+aW5pdCB3b3Jrc3BhY2UgaWYgZmlyc3QgdGVzdCBydW48L2xpPgoJICoJCTxsaT5pbmNyZW1lbnQgdGVzdCBwb3NpdGlvbjwvbGk+CgkgKgk8L3VsPgoJICogQHNlZSBvcmcuZWNsaXBzZS50ZXN0LnBlcmZvcm1hbmNlLlBlcmZvcm1hbmNlVGVzdENhc2Ujc2V0VXAoKQoJICovCglwcm90ZWN0ZWQgdm9pZCBzZXRVcCgpIHRocm93cyBFeGNlcHRpb24gewoJCXN1cGVyLnNldFVwKCk7CgoJCS8vIFN0b3JlIHNjZW5hcmlvIHJlYWRhYmxlIG5hbWUKCQlTdHJpbmcgc2NlbmFyaW8gPSBQZXJmb3JtYW5jZS5nZXREZWZhdWx0KCkuZ2V0RGVmYXVsdFNjZW5hcmlvSWQodGhpcyk7CgkJdGhpcy5zY2VuYXJpb1JlYWRhYmxlTmFtZSA9IHNjZW5hcmlvLnN1YnN0cmluZyhzY2VuYXJpby5sYXN0SW5kZXhPZignLicpKzEsIHNjZW5hcmlvLmxlbmd0aCgpLTIpOwoJCXRoaXMuc2NlbmFyaW9TaG9ydE5hbWUgPSB0aGlzLnNjZW5hcmlvUmVhZGFibGVOYW1lLnN1YnN0cmluZyh0aGlzLnNjZW5hcmlvUmVhZGFibGVOYW1lLmxhc3RJbmRleE9mKCcjJykrNS8qMSsidGVzdCIubGVuZ3RoKCkqLywgdGhpcy5zY2VuYXJpb1JlYWRhYmxlTmFtZS5sZW5ndGgoKSk7CgkJdGhpcy5zY2VuYXJpb0NvbW1lbnQgPSBudWxsOwoKCQkvLyBTZXQgdGVzdGluZyBlbnZpcm9ubWVudCBpZiBudWxsCgkJaWYgKEVOViA9PSBudWxsKSB7CgkJCUVOViA9IG5ldyBUZXN0aW5nRW52aXJvbm1lbnQoKTsKCQkJRU5WLm9wZW5FbXB0eVdvcmtzcGFjZSgpOwoJCQlzZXRVcEZ1bGxTb3VyY2VXb3Jrc3BhY2UoKTsKLy8JCQlpZiAoSlVOSVRfUFJPSkVDVCA9PSBudWxsKSB7Ci8vCQkJCXNldFVwSnVuaXRQcm9qZWN0KCk7Ci8vCQkJfQoJCX0KCgkJLy8gVmVyaWZ5IHRoYXQgYWxsIHVzZWQgcHJvamVjdHMgd2VyZSBmb3VuZCBpbiB3a3NwCgkJYXNzZXJ0Tm90TnVsbCgiV2Ugc2hvdWxkIGhhdmUgZm91bmQgIitKYXZhQ29yZS5QTFVHSU5fSUQrIiBwcm9qZWN0IGluIHdvcmtzcGFjZSEhISIsIEpEVF9DT1JFX1BST0pFQ1QpOwoKCQkvLyBJbmNyZW1lbnQgdGVzdCBwb3NpdGlvbgoJCVRFU1RfUE9TSVRJT04rKzsKCgkJLy8gQWJvcnQgaWYgb25seSB0b3VjaAoJCWlmIChUT1VDSCkgewoJCQlTdHJpbmcgdGVzdFByaW50TmFtZSA9ICInIit0aGlzLnNjZW5hcmlvU2hvcnROYW1lKyInIHRlc3QiOwoJCQlTeXN0ZW0ub3V0LnByaW50bG4oIlRvdWNoICIrdGVzdFByaW50TmFtZSsiIHRvIHZlcmlmeSB0aGF0IGl0IHdpbGwgcnVuIGNvcnJlY3RseS4iKTsKCQkJdGhyb3cgbmV3IEVycm9yKHRlc3RQcmludE5hbWUrIiBleGVjdXRpb24gaGFzIGJlZW4gYWJvcnRlZCEiKTsKCQl9CgoJCS8vIFByaW50IHRlc3QgbmFtZQoJCVN5c3RlbS5vdXQucHJpbnRsbigiPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0iKTsKCQlTeXN0ZW0ub3V0LnByaW50bG4oIlJ1bm5pbmcgIit0aGlzLnNjZW5hcmlvUmVhZGFibGVOYW1lKyIuLi4iKTsKCgkJLy8gVGltZSBtZWFzdXJpbmcKCQl0aGlzLnRlc3REdXJhdGlvbiA9IDA7CgkJdGhpcy5uYk1lYXN1cmVzID0gMDsKCgkJLy8gV2FpdCAyIHNlY29uZHMKCQlUaHJlYWQuc2xlZXAoMjAwMCk7Cgl9CgoJLyoKCSAqIFNldCB1cCBmdWxsIHNvdXJjZSB3b3JrcHNhY2UgZnJvbSB6aXAgZmlsZS4KCSAqLwoJcHJpdmF0ZSB2b2lkIHNldFVwRnVsbFNvdXJjZVdvcmtzcGFjZSgpIHRocm93cyBJT0V4Y2VwdGlvbiwgQ29yZUV4Y2VwdGlvbiB7CgoJCS8vIEdldCB3a3NwIGluZm8KCQlJV29ya3NwYWNlIHdvcmtzcGFjZSA9IFJlc291cmNlc1BsdWdpbi5nZXRXb3Jrc3BhY2UoKTsKCQlmaW5hbCBJV29ya3NwYWNlUm9vdCB3b3Jrc3BhY2VSb290ID0gd29ya3NwYWNlLmdldFJvb3QoKTsKCQlTdHJpbmcgdGFyZ2V0V29ya3NwYWNlUGF0aCA9IHdvcmtzcGFjZVJvb3QuZ2V0TG9jYXRpb24oKS50b0ZpbGUoKS5nZXRDYW5vbmljYWxQYXRoKCk7CgoJCS8vIE1vZGlmeSByZXNvdXJjZXMgd29ya3NwYWNlIHByZWZlcmVuY2VzIHRvIGF2b2lkIGRpc3R1cmJpbmcgdGVzdHMgd2hpbGUgcnVubmluZyB0aGVtCgkJSUVjbGlwc2VQcmVmZXJlbmNlcyByZXNvdXJjZXNQcmVmZXJlbmNlcyA9IEluc3RhbmNlU2NvcGUuSU5TVEFOQ0UuZ2V0Tm9kZShSZXNvdXJjZXNQbHVnaW4uUElfUkVTT1VSQ0VTKTsKCQlyZXNvdXJjZXNQcmVmZXJlbmNlcy5wdXQoUmVzb3VyY2VzUGx1Z2luLlBSRUZfQVVUT19SRUZSRVNILCAiZmFsc2UiKTsKCQl3b3Jrc3BhY2UuZ2V0RGVzY3JpcHRpb24oKS5zZXRTbmFwc2hvdEludGVydmFsKExvbmcuTUFYX1ZBTFVFKTsKCQl3b3Jrc3BhY2UuZ2V0RGVzY3JpcHRpb24oKS5zZXRBdXRvQnVpbGRpbmcoZmFsc2UpOwoKCQkvLyBHZXQgcHJvamVjdHMgZGlyZWN0b3JpZXMKCQlGaWxlIHdrc3BEaXIgPSBuZXcgRmlsZSh0YXJnZXRXb3Jrc3BhY2VQYXRoKTsKCQlGdWxsU291cmNlUHJvamVjdHNGaWx0ZXIgZmlsdGVyID0gbmV3IEZ1bGxTb3VyY2VQcm9qZWN0c0ZpbHRlcigpOwoJCUZpbGVbXSBkaXJlY3RvcmllcyA9IHdrc3BEaXIubGlzdEZpbGVzKGZpbHRlcik7CgkJbG9uZyBzdGFydCA9IFN5c3RlbS5jdXJyZW50VGltZU1pbGxpcygpOwoJCWludCBkaXJMZW5ndGggPSBkaXJlY3Rvcmllcy5sZW5ndGg7CgkJaWYgKGRpckxlbmd0aCA8IDYyKSB7CgkJCVN0cmluZyBmdWxsU291cmNlWmlwUGF0aCA9IGdldFBsdWdpbkJpbmFyaWVzRGlyZWN0b3J5UGF0aCgpICsgRmlsZS5zZXBhcmF0b3IgKyAiZnVsbC1zb3VyY2UtUjNfMC56aXAiOwoJCQlTeXN0ZW0ub3V0LnByaW50bG4oIlVuemlwcGluZyAiK2Z1bGxTb3VyY2VaaXBQYXRoKTsKCQkJU3lzdGVtLm91dC5wcmludCgiCWluICIrdGFyZ2V0V29ya3NwYWNlUGF0aCsiLi4uIik7CgkJCVV0aWwudW56aXAoZnVsbFNvdXJjZVppcFBhdGgsIHRhcmdldFdvcmtzcGFjZVBhdGgpOwoJCQlTeXN0ZW0ub3V0LnByaW50bG4oIiBkb25lIGluICIrKFN5c3RlbS5jdXJyZW50VGltZU1pbGxpcygpLXN0YXJ0KSsibXMuIik7CgkJCWRpcmVjdG9yaWVzID0gd2tzcERpci5saXN0RmlsZXMoZmlsdGVyKTsKCQkJZGlyTGVuZ3RoID0gZGlyZWN0b3JpZXMubGVuZ3RoOwoJCX0KCgkJLy8gSW5pdCBlbnZpcm9ubWVudCB3aXRoIGV4aXN0aW5nIHBvcmplY3RzCgkJU3lzdGVtLm91dC5wcmludCgiQ3JlYXRlIGFuZCBvcGVuIHByb2plY3RzIGluIGVudmlyb25tZW50Li4uIik7CgkJc3RhcnQgPSBTeXN0ZW0uY3VycmVudFRpbWVNaWxsaXMoKTsKCQlmb3IgKGludCBpID0gMDsgaSA8IGRpckxlbmd0aDsgaSsrKSB7CgkJCVN0cmluZyBkaXJOYW1lID0gZGlyZWN0b3JpZXNbaV0uZ2V0TmFtZSgpOwoJCQlJUHJvamVjdCBwcm9qZWN0ID0gd29ya3NwYWNlUm9vdC5nZXRQcm9qZWN0KGRpck5hbWUpOwoJCQlpZiAocHJvamVjdC5leGlzdHMoKSkgewoJCQkJRU5WLmFkZFByb2plY3QocHJvamVjdCk7CgkJCX0gZWxzZSB7CgkJCQlFTlYuYWRkUHJvamVjdChkaXJOYW1lKTsKCQkJfQoJCX0KCQlTeXN0ZW0ub3V0LnByaW50bG4oIigiKyhTeXN0ZW0uY3VycmVudFRpbWVNaWxsaXMoKS1zdGFydCkrIm1zKSIpOwoKCQkvLyBDcmVhdGUgbGliIGVudHJpZXMgZm9yIHRoZSBKREtzCgkJU3RyaW5nIGpyZUxpYlBhdGggPSBKYXZhQ29yZS5nZXRDbGFzc3BhdGhWYXJpYWJsZSgiSlJFX0xJQiIpLnRvT1NTdHJpbmcoKTsKCQlTeXN0ZW0ub3V0LnByaW50KCJDcmVhdGUgbGliIGVudHJpZXMgZm9yIHRoZSBKREtzLi4uIik7CgkJc3RhcnQgPSBTeXN0ZW0uY3VycmVudFRpbWVNaWxsaXMoKTsKCQlTdHJpbmdbXSBqZGtMaWJzID0gVXRpbC5nZXRKYXZhQ2xhc3NMaWJzKCk7CgkJaW50IGpka0xpYnNMZW5ndGggPSBqZGtMaWJzLmxlbmd0aDsKCQlJQ2xhc3NwYXRoRW50cnlbXSBqZGtFbnRyaWVzID0gbmV3IElDbGFzc3BhdGhFbnRyeVtqZGtMaWJzTGVuZ3RoXTsKCQlpbnQgamRrRW50cmllc0NvdW50ID0gMDsKCQlmb3IgKGludCBpPTA7IGk8amRrTGlic0xlbmd0aDsgaSsrKSB7CgkJCWlmICghamRrTGlic1tpXS5lcXVhbHMoanJlTGliUGF0aCkpIHsgLy8gZG8gbm90IGluY2x1ZGUgSlJFX0xJQiBpbiBhZGRpdGlvbmFsIEpESyBlbnRyaWVzCgkJCQlqZGtFbnRyaWVzW2pka0VudHJpZXNDb3VudCsrXSA9IEphdmFDb3JlLm5ld0xpYnJhcnlFbnRyeShuZXcgUGF0aChqZGtMaWJzW2ldKSwgbnVsbCwgbnVsbCk7CgkJCX0KCQl9CgkJU3lzdGVtLm91dC5wcmludGxuKGpka0xpYnNMZW5ndGgrIiBmb3VuZCAoIisoU3lzdGVtLmN1cnJlbnRUaW1lTWlsbGlzKCktc3RhcnQpKyJtcykiKTsKCgkJLy8gU2V0IGNsYXNzcGF0aHMgKHdvcmthcm91bmQgYnVnIDczMjUzIFByb2plY3QgcmVmZXJlbmNlcyBub3Qgc2V0IG9uIHByb2plY3Qgb3BlbikKCQlTeXN0ZW0ub3V0LnByaW50KCJTZXQgcHJvamVjdHMgY2xhc3NwYXRocy4uLiIpOwoJCXN0YXJ0ID0gU3lzdGVtLmN1cnJlbnRUaW1lTWlsbGlzKCk7CgkJQUxMX1BST0pFQ1RTID0gSmF2YUNvcmUuY3JlYXRlKHdvcmtzcGFjZVJvb3QpLmdldEphdmFQcm9qZWN0cygpOwoJCWludCBwcm9qZWN0c0xlbmd0aCA9IEFMTF9QUk9KRUNUUy5sZW5ndGg7CgkJZm9yIChpbnQgaSA9IDA7IGkgPCBwcm9qZWN0c0xlbmd0aDsgaSsrKSB7CgkJCVN0cmluZyBwcm9qZWN0TmFtZSA9IEFMTF9QUk9KRUNUU1tpXS5nZXRFbGVtZW50TmFtZSgpOwoJCQlpZiAoQklHX1BST0pFQ1RfTkFNRS5lcXVhbHMocHJvamVjdE5hbWUpKSBjb250aW51ZTsgLy8gd2lsbCBiZSBzZXQgbGF0ZXIKCQkJaWYgKEphdmFDb3JlLlBMVUdJTl9JRC5lcXVhbHMocHJvamVjdE5hbWUpKSB7CgkJCQlKRFRfQ09SRV9QUk9KRUNUID0gQUxMX1BST0pFQ1RTW2ldOwovLwkJCX0gZWxzZSBpZiAoSlVOSVRfUFJPSkVDVF9OQU1FLmVxdWFscyhwcm9qZWN0TmFtZSkpIHsKLy8JCQkJSlVOSVRfUFJPSkVDVCA9IEFMTF9QUk9KRUNUU1tpXTsKCQkJfQoKCQkJLy8gU2V0IGpkayBqYXJzIG9udG8gdGhlIHByb2plY3QgY2xhc3NwYXRoCgkJCUlDbGFzc3BhdGhFbnRyeVtdIGVudHJpZXMgPSBBTExfUFJPSkVDVFNbaV0uZ2V0UmF3Q2xhc3NwYXRoKCk7CgkJCWludCBlbnRyaWVzTGVuZ3RoID0gZW50cmllcy5sZW5ndGg7CgkJCXRyeSB7CgkJCQlTeXN0ZW0uYXJyYXljb3B5KGVudHJpZXMsIDAsIGVudHJpZXMgPSBuZXcgSUNsYXNzcGF0aEVudHJ5W2pka0VudHJpZXNDb3VudCtlbnRyaWVzTGVuZ3RoXSwgMCwgZW50cmllc0xlbmd0aCk7CgkJCQlTeXN0ZW0uYXJyYXljb3B5KGpka0VudHJpZXMsIDAsIGVudHJpZXMsIGVudHJpZXNMZW5ndGgsIGpka0VudHJpZXNDb3VudCk7CgkJCQlBTExfUFJPSkVDVFNbaV0uc2V0UmF3Q2xhc3NwYXRoKGVudHJpZXMsIG51bGwpOwoJCQl9CgkJCWNhdGNoIChKYXZhTW9kZWxFeGNlcHRpb24gam1lKSB7CgkJCQkvLyBza2lwIG5hbWUgY29sbGlzaW9uIGFzIGl0IG1lYW5zIHRoYXQgSlJFIGxpYiB3ZXJlIGFscmVhZHkgc2V0IG9uIHRoZSBjbGFzc3BhdGgKCQkJCWlmIChqbWUuZ2V0U3RhdHVzKCkuZ2V0Q29kZSgpICE9IElKYXZhTW9kZWxTdGF0dXNDb25zdGFudHMuTkFNRV9DT0xMSVNJT04pIHsKCQkJCQl0aHJvdyBqbWU7CgkJCQl9CgkJCX0KCgkJCS8vIE1ha2UgQmlnIHByb2plY3QgZGVwZW5kZW50IGZyb20gamR0LmNvcmUgb25lCi8vCQkJSUNsYXNzcGF0aEVudHJ5W10gYmlnUHJvamVjdEVudHJpZXMgPSBCSUdfUFJPSkVDVC5nZXRSYXdDbGFzc3BhdGgoKTsKLy8JCQlpbnQgYnBlTGVuZ3RoID0gYmlnUHJvamVjdEVudHJpZXMubGVuZ3RoOwovLwkJCVN5c3RlbS5hcnJheWNvcHkoYmlnUHJvamVjdEVudHJpZXMsIDAsIGJpZ1Byb2plY3RFbnRyaWVzID0gbmV3IElDbGFzc3BhdGhFbnRyeVticGVMZW5ndGgrMV0sIDAsIGJwZUxlbmd0aCk7Ci8vCQkJYmlnUHJvamVjdEVudHJpZXNbYnBlTGVuZ3RoXSA9IEphdmFDb3JlLm5ld1Byb2plY3RFbnRyeShKRFRfQ09SRV9QUk9KRUNULmdldFBhdGgoKSk7CgkJfQoJCVN5c3RlbS5vdXQucHJpbnRsbigiKCIrKFN5c3RlbS5jdXJyZW50VGltZU1pbGxpcygpLXN0YXJ0KSsibXMpIik7CgoJCS8vIEluaXRpYWxpemUgUGFyc2VyIHdva3JpbmcgY29weQoJCUlKYXZhRWxlbWVudCBlbGVtZW50ID0gSkRUX0NPUkVfUFJPSkVDVC5maW5kVHlwZSgib3JnLmVjbGlwc2UuamR0LmludGVybmFsLmNvbXBpbGVyLnBhcnNlci5QYXJzZXIiKTsKCQlhc3NlcnRUcnVlKCJQYXJzZXIgc2hvdWxkIGV4aXN0IGluIG9yZy5lY2xpcHNlLmpkdC5jb3JlIHByb2plY3QhIiwgZWxlbWVudCAhPSBudWxsICYmIGVsZW1lbnQuZXhpc3RzKCkpOwoJCVBBUlNFUl9XT1JLSU5HX0NPUFkgPSAoSUNvbXBpbGF0aW9uVW5pdCkgZWxlbWVudC5nZXRQYXJlbnQoKTsKCX0KCgkvKgoJICogQ3JlYXRlIEpVbml0IHByb2plY3QgYW5kIGFkZCBpdCB0byB0aGUgd29ya3NwYWNlCgkgKgoJcHJpdmF0ZSB2b2lkIHNldFVwSnVuaXRQcm9qZWN0KCkgdGhyb3dzIENvcmVFeGNlcHRpb24sIElPRXhjZXB0aW9uIHsKCQlJV29ya3NwYWNlIHdvcmtzcGFjZSA9IFJlc291cmNlc1BsdWdpbi5nZXRXb3Jrc3BhY2UoKTsKCQlJV29ya3NwYWNlUm9vdCB3b3Jrc3BhY2VSb290ID0gd29ya3NwYWNlLmdldFJvb3QoKTsKCQlmaW5hbCBTdHJpbmcgdGFyZ2V0V29ya3NwYWNlUGF0aCA9IHdvcmtzcGFjZVJvb3QuZ2V0TG9jYXRpb24oKS50b0ZpbGUoKS5nZXRDYW5vbmljYWxQYXRoKCk7CgoJCS8vIFByaW50IGZvciBsb2cgaW4gY2FzZSBvZiBwcm9qZWN0IGNyZWF0aW9uIHRyb3VibGVzLi4uCgkJU3lzdGVtLm91dC5wcmludGxuKCJDcmVhdGUgJyIrSlVOSVRfUFJPSkVDVF9OQU1FKyInIHByb2plY3QgaW4gIit3b3Jrc3BhY2VSb290LmdldExvY2F0aW9uKCkrIjoiKTsKCQlsb25nIHN0YXJ0ID0gU3lzdGVtLmN1cnJlbnRUaW1lTWlsbGlzKCk7CgoJCS8vIFByaW50IGZvciBsb2cgaW4gY2FzZSBvZiBwcm9qZWN0IGNyZWF0aW9uIHRyb3VibGVzLi4uCgkJU3RyaW5nIGdlbmVyaWNzWmlwUGF0aCA9IGdldFBsdWdpbkRpcmVjdG9yeVBhdGgoKSArIEZpbGUuc2VwYXJhdG9yICsgSlVOSVRfUFJPSkVDVF9OQU1FICsgInNyYy56aXAiOwoJCXN0YXJ0ID0gU3lzdGVtLmN1cnJlbnRUaW1lTWlsbGlzKCk7CgkJU3lzdGVtLm91dC5wcmludGxuKCJVbnppcHBpbmcgIitnZW5lcmljc1ppcFBhdGgpOwoJCVN5c3RlbS5vdXQucHJpbnQoIglpbiAiK3RhcmdldFdvcmtzcGFjZVBhdGgrIi4uLiIpOwoKCQkvLyBVbnppcCBmaWxlCgkJVXRpbC51bnppcChnZW5lcmljc1ppcFBhdGgsIHRhcmdldFdvcmtzcGFjZVBhdGgpOwoJCVN5c3RlbS5vdXQucHJpbnRsbigiICIrKFN5c3RlbS5jdXJyZW50VGltZU1pbGxpcygpLXN0YXJ0KSsibXMuIik7CgoJCS8vIEFkZCBwcm9qZWN0IHRvIHdvcmtzcGFjZQoJCVN5c3RlbS5vdXQucHJpbnQoIgktIGFkZCBwcm9qZWN0IHRvIGZ1bGwgc291cmNlIHdvcmtzcGFjZS4uLiIpOwoJCXN0YXJ0ID0gU3lzdGVtLmN1cnJlbnRUaW1lTWlsbGlzKCk7CgkJRU5WLmFkZFByb2plY3QoSlVOSVRfUFJPSkVDVF9OQU1FKTsKCQlKVU5JVF9QUk9KRUNUID0gY3JlYXRlSmF2YVByb2plY3QoSlVOSVRfUFJPSkVDVF9OQU1FLCBuZXcgU3RyaW5nW117ICJzcmMiIH0sICJiaW4iLCAiMS41Iik7CgkJSlVOSVRfUFJPSkVDVC5zZXRSYXdDbGFzc3BhdGgoSlVOSVRfUFJPSkVDVC5nZXRSZXNvbHZlZENsYXNzcGF0aCh0cnVlKSwgbnVsbCk7CgoJCS8vIFByaW50IGZvciBsb2cgaW4gY2FzZSBvZiBwcm9qZWN0IGNyZWF0aW9uIHRyb3VibGVzLi4uCgkJU3lzdGVtLm91dC5wcmludGxuKCIgIisoU3lzdGVtLmN1cnJlbnRUaW1lTWlsbGlzKCktc3RhcnQpKyJtcy4iKTsKCX0KCSovCgoJLyoqCgkgKiBAZGVwcmVjYXRlZCBVc2Uge0BsaW5rICN0YWdBc0dsb2JhbFN1bW1hcnkoU3RyaW5nLERpbWVuc2lvbixib29sZWFuKX0gaW5zdGVhZAoJICovCglwdWJsaWMgdm9pZCB0YWdBc0dsb2JhbFN1bW1hcnkoU3RyaW5nIHNob3J0TmFtZSwgRGltZW5zaW9uIGRpbWVuc2lvbikgewoJCXRhZ0FzR2xvYmFsU3VtbWFyeShzaG9ydE5hbWUsIGRpbWVuc2lvbiwgZmFsc2UpOyAvLyBkbyBOT1QgcHV0IGluIGZpbmdlcnByaW50Cgl9Cglwcm90ZWN0ZWQgdm9pZCB0YWdBc0dsb2JhbFN1bW1hcnkoU3RyaW5nIHNob3J0TmFtZSwgYm9vbGVhbiBmaW5nZXJwcmludCkgewoJCXRhZ0FzR2xvYmFsU3VtbWFyeShzaG9ydE5hbWUsIERpbWVuc2lvbi5FTEFQU0VEX1BST0NFU1MsIGZpbmdlcnByaW50KTsKCX0KCXByb3RlY3RlZCB2b2lkIHRhZ0FzR2xvYmFsU3VtbWFyeShTdHJpbmcgc2hvcnROYW1lLCBEaW1lbnNpb24gZGltZW5zaW9uLCBib29sZWFuIGZpbmdlcnByaW50KSB7CgkJaWYgKERFQlVHKSBTeXN0ZW0ub3V0LnByaW50bG4oc2hvcnROYW1lKTsKCQlpZiAoZmluZ2VycHJpbnQpIHN1cGVyLnRhZ0FzR2xvYmFsU3VtbWFyeShzaG9ydE5hbWUsIGRpbWVuc2lvbik7Cgl9CgkvKioKCSAqIEBkZXByZWNhdGVkIFdlIGRvIG5vdCB1c2UgdGhpcyBtZXRob2QuLi4KCSAqLwoJcHVibGljIHZvaWQgdGFnQXNHbG9iYWxTdW1tYXJ5KFN0cmluZyBzaG9ydE5hbWUsIERpbWVuc2lvbltdIGRpbWVuc2lvbnMpIHsKCQlTeXN0ZW0ub3V0LnByaW50bG4oIkVSUk9SOiB0YWdBc0dsb2JhbFN1bW1hcnkoU3RyaW5nLCBEaW1lbnNpb25bXSkgaXMgbm90IGltcGxlbWVudGVkISEhIik7Cgl9CgkvKioKCSAqIEBkZXByZWNhdGVkIFVzZSB7QGxpbmsgI3RhZ0FzU3VtbWFyeShTdHJpbmcsRGltZW5zaW9uLGJvb2xlYW4pfSBpbnN0ZWFkCgkgKi8KCXB1YmxpYyB2b2lkIHRhZ0FzU3VtbWFyeShTdHJpbmcgc2hvcnROYW1lLCBEaW1lbnNpb24gZGltZW5zaW9uKSB7CgkJdGFnQXNTdW1tYXJ5KHNob3J0TmFtZSwgZGltZW5zaW9uLCBmYWxzZSk7IC8vIGRvIE5PVCBwdXQgaW4gZmluZ2VycHJpbnQKCX0KCXByb3RlY3RlZCB2b2lkIHRhZ0FzU3VtbWFyeShTdHJpbmcgc2hvcnROYW1lLCBib29sZWFuIGZpbmdlcnByaW50KSB7CgkJdGFnQXNTdW1tYXJ5KHNob3J0TmFtZSwgRGltZW5zaW9uLkVMQVBTRURfUFJPQ0VTUywgZmluZ2VycHJpbnQpOwoJfQoJcHVibGljIHZvaWQgdGFnQXNTdW1tYXJ5KFN0cmluZyBzaG9ydE5hbWUsIERpbWVuc2lvbiBkaW1lbnNpb24sIGJvb2xlYW4gZmluZ2VycHJpbnQpIHsKCQlpZiAoREVCVUcpIFN5c3RlbS5vdXQucHJpbnRsbihzaG9ydE5hbWUpOwoJCWlmIChmaW5nZXJwcmludCkgc3VwZXIudGFnQXNTdW1tYXJ5KHNob3J0TmFtZSwgZGltZW5zaW9uKTsKCX0KCS8qKgoJICogQGRlcHJlY2F0ZWQgV2UgZG8gbm90IHVzZSB0aGlzIG1ldGhvZC4uLgoJICovCglwdWJsaWMgdm9pZCB0YWdBc1N1bW1hcnkoU3RyaW5nIHNob3J0TmFtZSwgRGltZW5zaW9uW10gZGltZW5zaW9ucykgewoJCVN5c3RlbS5vdXQucHJpbnRsbigiRVJST1I6IHRhZ0FzR2xvYmFsU3VtbWFyeShTdHJpbmcsIERpbWVuc2lvbltdKSBpcyBub3QgaW1wbGVtZW50ZWQhISEiKTsKCX0KCXB1YmxpYyB2b2lkIHRhZ0FzU3VtbWFyeShTdHJpbmcgc2hvcnROYW1lLCBEaW1lbnNpb25bXSBkaW1lbnNpb25zLCBib29sZWFuIGZpbmdlcnByaW50KSB7CgkJaWYgKERFQlVHKSBTeXN0ZW0ub3V0LnByaW50bG4oc2hvcnROYW1lKTsKCQlpZiAoZmluZ2VycHJpbnQpIHN1cGVyLnRhZ0FzU3VtbWFyeShzaG9ydE5hbWUsIGRpbWVuc2lvbnMpOwoJfQoJcHVibGljIHZvaWQgc3RhcnRNZWFzdXJpbmcoKSB7CgkJaWYgKFBSSU5UICYmIHRoaXMubmJNZWFzdXJlcz09MCkgU3lzdGVtLm91dC5wcmludGxuKCIJTWVhc3VyZXMgKH5FbGFwc2VkIFByb2Nlc3MgdGltZSk6Iik7CgkJdGhpcy5zdGFydE1lYXN1cmluZyA9IFN5c3RlbS5jdXJyZW50VGltZU1pbGxpcygpOwoJCXN1cGVyLnN0YXJ0TWVhc3VyaW5nKCk7Cgl9CglwdWJsaWMgdm9pZCBzdG9wTWVhc3VyaW5nKCkgewoJCXN1cGVyLnN0b3BNZWFzdXJpbmcoKTsKCQl0aGlzLm5iTWVhc3VyZXMrKzsKCQlsb25nIGR1cmF0aW9uID0gU3lzdGVtLmN1cnJlbnRUaW1lTWlsbGlzKCkgLSB0aGlzLnN0YXJ0TWVhc3VyaW5nOwoJCWlmIChQUklOVCkgU3lzdGVtLm91dC5wcmludGxuKCIJCS0gbrAgIit0aGlzLm5iTWVhc3VyZXMrIjogIitkdXJhdGlvbisibXMiKTsKCQl0aGlzLnRlc3REdXJhdGlvbiArPSBkdXJhdGlvbjsKCX0KCXB1YmxpYyB2b2lkIGNvbW1pdE1lYXN1cmVtZW50cygpIHsKCQlpZiAoUFJJTlQpIHsKCQkJU3lzdGVtLm91dC5wcmludGxuKCIJVGVzdCBkdXJhdGlvbiA9ICIrdGhpcy50ZXN0RHVyYXRpb24rIm1zIik7CgkJCVN5c3RlbS5vdXQucHJpbnRsbigiCVRpbWUgYXZlcmFnZSA9ICIrKCgodGhpcy50ZXN0RHVyYXRpb24qMTAwMCkvdGhpcy5uYk1lYXN1cmVzKS8xMDAwKSk7CgkJfQoJCXN1cGVyLmNvbW1pdE1lYXN1cmVtZW50cygpOwoJfQoJLyoqCgkgKiBPdmVycmlkZSBzdXBlciBpbXBsZW1lbnRhdGlvbiB0bzoKCSAqCTx1bD4KCSAqCQk8bGk+ZGVjcmVtZW50IGFsbCB0ZXN0IGNvdW50PC9saT4KCSAqCQk8bGk+cmVzZXQgd29ya3NwYWNlIGFuZCBiYWNrIHRvIGluaXRpYWwgb3B0aW9ucyBpZiBsYXN0IHRlc3QgcnVuPC9saT4KCSAqPC91bD4KCSAqIEBzZWUgb3JnLmVjbGlwc2UudGVzdC5wZXJmb3JtYW5jZS5QZXJmb3JtYW5jZVRlc3RDYXNlI3RlYXJEb3duKCkKCSAqLwoJcHJvdGVjdGVkIHZvaWQgdGVhckRvd24oKSB0aHJvd3MgRXhjZXB0aW9uIHsKCQlBTExfVEVTVFNfQ09VTlQtLTsKCQlpZiAoQUxMX1RFU1RTX0NPVU5UID09IDApIHsKLy8JCQlFTlYucmVzZXRXb3Jrc3BhY2UoKTsKCQkJSmF2YUNvcmUuc2V0T3B0aW9ucyhJTklUSUFMX09QVElPTlMpOwoJCX0KCQlzdXBlci50ZWFyRG93bigpOwoJfQoKCS8qCgkgKiBEZWxldGUgYSBkaXJlY3RvcnkgZnJvbSBmaWxlIHN5c3RlbS4KCSAqIEBwYXJhbSBkaXJlY3RvcnkKCSAqCglwcm90ZWN0ZWQgdm9pZCBjbGVhbnVwRGlyZWN0b3J5KEZpbGUgZGlyZWN0b3J5KSB7CgkJaWYgKCFkaXJlY3RvcnkuaXNEaXJlY3RvcnkoKSB8fCAhZGlyZWN0b3J5LmV4aXN0cygpKSB7CgkJCXJldHVybjsKCQl9CgkJU3RyaW5nW10gZmlsZU5hbWVzID0gZGlyZWN0b3J5Lmxpc3QoKTsKCQlmb3IgKGludCBpID0gMDsgaSA8IGZpbGVOYW1lcy5sZW5ndGg7IGkrKykgewoJCQlGaWxlIGZpbGUgPSBuZXcgRmlsZShkaXJlY3RvcnksIGZpbGVOYW1lc1tpXSk7CgkJCWlmIChmaWxlLmlzRGlyZWN0b3J5KCkpIHsKCQkJCWNsZWFudXBEaXJlY3RvcnkoZmlsZSk7CgkJCX0gZWxzZSB7CgkJCQlpZiAoIWZpbGUuZGVsZXRlKCkpCgkJCQkJU3lzdGVtLm91dC5wcmludGxuKCJDb3VsZCBub3QgZGVsZXRlIGZpbGUgIiArIGZpbGUuZ2V0UGF0aCgpKTsgLy8kTk9OLU5MUy0xJAoJCQl9CgkJfQoJCWlmICghZGlyZWN0b3J5LmRlbGV0ZSgpKQoJCQlTeXN0ZW0ub3V0LnByaW50bG4oIkNvdWxkIG5vdCBkZWxldGUgZGlyZWN0b3J5ICIgKyBkaXJlY3RvcnkuZ2V0UGF0aCgpKTsgLy8kTk9OLU5MUy0xJAoJfQoJKi8KCgkvKgoJICogQ2xlYXIgZ2l2ZW4gb3B0aW9ucwoJICovCglNYXAgY2xlYXJPcHRpb25zKE1hcCBvcHRpb25zKSB7CgkJLy8gdHVybiBhbGwgZXJyb3JzIGFuZCB3YXJuaW5ncyBpbnRvIGlnbm9yZS4gVGhlIGN1c3RvbWl6YWJsZSBzZXQgb2YgY29tcGlsZXIKCQkvLyBvcHRpb25zIG9ubHkgY29udGFpbnMgYWRkaXRpb25hbCBFY2xpcHNlIG9wdGlvbnMuIFRoZSBzdGFuZGFyZCBKREsgY29tcGlsZXIKCQkvLyBvcHRpb25zIGNhbid0IGJlIGNoYW5nZWQgYW55d2F5LgoJCWZvciAoSXRlcmF0b3IgaXRlcj0gb3B0aW9ucy5rZXlTZXQoKS5pdGVyYXRvcigpOyBpdGVyLmhhc05leHQoKTspIHsKCQkJU3RyaW5nIGtleT0gKFN0cmluZylpdGVyLm5leHQoKTsKCQkJU3RyaW5nIHZhbHVlPSAoU3RyaW5nKW9wdGlvbnMuZ2V0KGtleSk7CgkJCWlmICgiZXJyb3IiLmVxdWFscyh2YWx1ZSkgfHwgIndhcm5pbmciLmVxdWFscyh2YWx1ZSkpIHsgIC8vJE5PTi1OTFMtMSQvLyROT04tTkxTLTIkCgkJCQkvLyBTeXN0ZW0ub3V0LnByaW50bG4oIklnbm9yaW5nIC0gIiArIGtleSk7CgkJCQlvcHRpb25zLnB1dChrZXksICJpZ25vcmUiKTsgLy8kTk9OLU5MUy0xJAoJCQl9IGVsc2UgaWYgKCJlbmFibGVkIi5lcXVhbHModmFsdWUpKSB7CgkJCQkvLyBTeXN0ZW0ub3V0LnByaW50bG4oIgktIGRpc2FibGluZyAiICsga2V5KTsKCQkJCW9wdGlvbnMucHV0KGtleSwgImRpc2FibGVkIik7CgkJCX0KCQl9CgkJb3B0aW9ucy5wdXQoSmF2YUNvcmUuQ09NUElMRVJfVEFTS19UQUdTLCAiIik7CgkJcmV0dXJuIG9wdGlvbnM7Cgl9CgoJLyoqCgkgKiBAc2VlIG9yZy5lY2xpcHNlLmpkdC5jb3JlLnRlc3RzLm1vZGVsLkFic3RyYWN0SmF2YU1vZGVsVGVzdHMjY3JlYXRlSmF2YVByb2plY3QoU3RyaW5nLCBTdHJpbmdbXSwgU3RyaW5nW10sIFN0cmluZ1tdW10sIFN0cmluZ1tdW10sIFN0cmluZ1tdLCBTdHJpbmdbXVtdLCBTdHJpbmdbXVtdLCBib29sZWFuW10sIFN0cmluZywgU3RyaW5nW10sIFN0cmluZ1tdW10sIFN0cmluZ1tdW10sIFN0cmluZykKCSAqLwoJcHJvdGVjdGVkIElKYXZhUHJvamVjdCBjcmVhdGVKYXZhUHJvamVjdChmaW5hbCBTdHJpbmcgcHJvamVjdE5hbWUsIGZpbmFsIFN0cmluZ1tdIHNvdXJjZUZvbGRlcnMsIGZpbmFsIFN0cmluZyBwcm9qZWN0T3V0cHV0LCBmaW5hbCBTdHJpbmcgY29tcGxpYW5jZSkgdGhyb3dzIENvcmVFeGNlcHRpb24gewoJCWZpbmFsIElKYXZhUHJvamVjdFtdIHJlc3VsdCA9IG5ldyBJSmF2YVByb2plY3RbMV07CgkJSVdvcmtzcGFjZVJ1bm5hYmxlIGNyZWF0ZSA9IG5ldyBJV29ya3NwYWNlUnVubmFibGUoKSB7CgkJCXB1YmxpYyB2b2lkIHJ1bihJUHJvZ3Jlc3NNb25pdG9yIG1vbml0b3IpIHRocm93cyBDb3JlRXhjZXB0aW9uIHsKCgkJCQkvLyBjcmVhdGUgY2xhc3NwYXRoIGVudHJpZXMKCQkJCUlQcm9qZWN0IHByb2plY3QgPSBFTlYuZ2V0UHJvamVjdChwcm9qZWN0TmFtZSk7CgkJCQlJUGF0aCBwcm9qZWN0UGF0aCA9IHByb2plY3QuZ2V0RnVsbFBhdGgoKTsKCQkJCWludCBzb3VyY2VMZW5ndGggPSBzb3VyY2VGb2xkZXJzID09IG51bGwgPyAwIDogc291cmNlRm9sZGVycy5sZW5ndGg7CgkJCQlJQ2xhc3NwYXRoRW50cnlbXSBlbnRyaWVzID0gbmV3IElDbGFzc3BhdGhFbnRyeVtzb3VyY2VMZW5ndGgrMV07CgkJCQlmb3IgKGludCBpPSAwOyBpIDwgc291cmNlTGVuZ3RoOyBpKyspIHsKCQkJCQlJUGF0aCBzb3VyY2VQYXRoID0gbmV3IFBhdGgoc291cmNlRm9sZGVyc1tpXSk7CgkJCQkJaW50IHNlZ21lbnRDb3VudCA9IHNvdXJjZVBhdGguc2VnbWVudENvdW50KCk7CgkJCQkJaWYgKHNlZ21lbnRDb3VudCA+IDApIHsKCQkJCQkJLy8gY3JlYXRlIGZvbGRlciBhbmQgaXRzIHBhcmVudHMKCQkJCQkJSUNvbnRhaW5lciBjb250YWluZXIgPSBwcm9qZWN0OwoJCQkJCQlmb3IgKGludCBqID0gMDsgaiA8IHNlZ21lbnRDb3VudDsgaisrKSB7CgkJCQkJCQlJRm9sZGVyIGZvbGRlciA9IGNvbnRhaW5lci5nZXRGb2xkZXIobmV3IFBhdGgoc291cmNlUGF0aC5zZWdtZW50KGopKSk7CgkJCQkJCQlpZiAoIWZvbGRlci5leGlzdHMoKSkgewoJCQkJCQkJCWZvbGRlci5jcmVhdGUodHJ1ZSwgdHJ1ZSwgbnVsbCk7CgkJCQkJCQl9CgkJCQkJCQljb250YWluZXIgPSBmb2xkZXI7CgkJCQkJCX0KCQkJCQl9CgkJCQkJLy8gY3JlYXRlIHNvdXJjZSBlbnRyeQoJCQkJCWVudHJpZXNbaV0gPQoJCQkJCQlKYXZhQ29yZS5uZXdTb3VyY2VFbnRyeSgKCQkJCQkJCXByb2plY3RQYXRoLmFwcGVuZChzb3VyY2VQYXRoKSwKCQkJCQkJCW5ldyBJUGF0aFswXSwKCQkJCQkJCW5ldyBJUGF0aFswXSwKCQkJCQkJCW51bGwKCQkJCQkJKTsKCQkJCX0KCgkJCQkvLyBBZGQgSlJFX0xJQiBlbnRyeQoJCQkJZW50cmllc1tzb3VyY2VMZW5ndGhdID0gSmF2YUNvcmUubmV3VmFyaWFibGVFbnRyeSgKCQkJCQkJCQluZXcgUGF0aCgiSlJFX0xJQiIpLAoJCQkJCQkJCW51bGwsCgkJCQkJCQkJbnVsbCk7CgoJCQkJLy8gY3JlYXRlIHByb2plY3QncyBvdXRwdXQgZm9sZGVyCgkJCQlJUGF0aCBvdXRwdXRQYXRoID0gbmV3IFBhdGgocHJvamVjdE91dHB1dCk7CgkJCQlpZiAob3V0cHV0UGF0aC5zZWdtZW50Q291bnQoKSA+IDApIHsKCQkJCQlJRm9sZGVyIG91dHB1dCA9IHByb2plY3QuZ2V0Rm9sZGVyKG91dHB1dFBhdGgpOwoJCQkJCWlmICghb3V0cHV0LmV4aXN0cygpKSB7CgkJCQkJCW91dHB1dC5jcmVhdGUodHJ1ZSwgdHJ1ZSwgbnVsbCk7CgkJCQkJfQoJCQkJfQoKCQkJCS8vIHNldCBjbGFzc3BhdGggYW5kIG91dHB1dCBsb2NhdGlvbgoJCQkJSUphdmFQcm9qZWN0IGphdmFQcm9qZWN0ID0gRU5WLmdldEphdmFQcm9qZWN0KHByb2plY3ROYW1lKTsKCQkJCWphdmFQcm9qZWN0LnNldFJhd0NsYXNzcGF0aChlbnRyaWVzLCBwcm9qZWN0UGF0aC5hcHBlbmQob3V0cHV0UGF0aCksIG51bGwpOwoKCQkJCS8vIHNldCBjb21wbGlhbmNlIGxldmVsIG9wdGlvbnMKCQkJCWlmICgiMS41Ii5lcXVhbHMoY29tcGxpYW5jZSkpIHsKCQkJCQlNYXAgb3B0aW9ucyA9IG5ldyBIYXNoTWFwKCk7CgkJCQkJb3B0aW9ucy5wdXQoQ29tcGlsZXJPcHRpb25zLk9QVElPTl9Db21wbGlhbmNlLCBDb21waWxlck9wdGlvbnMuVkVSU0lPTl8xXzUpOwoJCQkJCW9wdGlvbnMucHV0KENvbXBpbGVyT3B0aW9ucy5PUFRJT05fU291cmNlLCBDb21waWxlck9wdGlvbnMuVkVSU0lPTl8xXzUpOwoJCQkJCW9wdGlvbnMucHV0KENvbXBpbGVyT3B0aW9ucy5PUFRJT05fVGFyZ2V0UGxhdGZvcm0sIENvbXBpbGVyT3B0aW9ucy5WRVJTSU9OXzFfNSk7CgkJCQkJamF2YVByb2plY3Quc2V0T3B0aW9ucyhvcHRpb25zKTsKCQkJCX0KCgkJCQlyZXN1bHRbMF0gPSBqYXZhUHJvamVjdDsKCQkJfQoJCX07CgkJUmVzb3VyY2VzUGx1Z2luLmdldFdvcmtzcGFjZSgpLnJ1bihjcmVhdGUsIG51bGwpOwoJCXJldHVybiByZXN1bHRbMF07Cgl9CgoJcHJpdmF0ZSB2b2lkIGNvbGxlY3RBbGxGaWxlcyhGaWxlIHJvb3QsIEFycmF5TGlzdCBjb2xsZWN0b3IsIEZpbGVGaWx0ZXIgZmlsZUZpbHRlcikgewoJCUZpbGVbXSBmaWxlcyA9IHJvb3QubGlzdEZpbGVzKGZpbGVGaWx0ZXIpOwoJCWZvciAoaW50IGkgPSAwOyBpIDwgZmlsZXMubGVuZ3RoOyBpKyspIHsKCQkJZmluYWwgRmlsZSBjdXJyZW50RmlsZSA9IGZpbGVzW2ldOwoJCQlpZiAoY3VycmVudEZpbGUuaXNEaXJlY3RvcnkoKSkgewoJCQkJY29sbGVjdEFsbEZpbGVzKGN1cnJlbnRGaWxlLCBjb2xsZWN0b3IsIGZpbGVGaWx0ZXIpOwoJCQl9IGVsc2UgewoJCQkJY29sbGVjdG9yLmFkZChjdXJyZW50RmlsZSk7CgkJCX0KCQl9Cgl9CgoJcHJvdGVjdGVkIEZpbGVbXSBnZXRBbGxGaWxlcyhGaWxlIHJvb3QsIEZpbGVGaWx0ZXIgZmlsZUZpbHRlcikgewoJCUFycmF5TGlzdCBmaWxlcyA9IG5ldyBBcnJheUxpc3QoKTsKCQlpZiAocm9vdC5pc0RpcmVjdG9yeSgpKSB7CgkJCWNvbGxlY3RBbGxGaWxlcyhyb290LCBmaWxlcywgZmlsZUZpbHRlcik7CgkJCUZpbGVbXSByZXN1bHQgPSBuZXcgRmlsZVtmaWxlcy5zaXplKCldOwoJCQlmaWxlcy50b0FycmF5KHJlc3VsdCk7CgkJCXJldHVybiByZXN1bHQ7CgkJfSBlbHNlIHsKCQkJcmV0dXJuIG51bGw7CgkJfQoJfQoKCS8qKgoJICogUmV0dXJucyB0aGUgc3BlY2lmaWVkIGNvbXBpbGF0aW9uIHVuaXQgaW4gdGhlIGdpdmVuIHByb2plY3QsIHJvb3QsIGFuZAoJICogcGFja2FnZSBmcmFnbWVudCBvciA8Y29kZT5udWxsPC9jb2RlPiBpZiBpdCBkb2VzIG5vdCBleGlzdC4KCSAqLwoJcHJvdGVjdGVkIElDbGFzc0ZpbGUgZ2V0Q2xhc3NGaWxlKElKYXZhUHJvamVjdCBwcm9qZWN0LCBTdHJpbmcgcm9vdFBhdGgsIFN0cmluZyBwYWNrYWdlTmFtZSwgU3RyaW5nIGNsYXNzTmFtZSkgdGhyb3dzIEphdmFNb2RlbEV4Y2VwdGlvbiB7CgkJSVBhY2thZ2VGcmFnbWVudCBwa2c9IGdldFBhY2thZ2VGcmFnbWVudChwcm9qZWN0LCByb290UGF0aCwgcGFja2FnZU5hbWUpOwoJCWlmIChwa2cgPT0gbnVsbCkgewoJCQlyZXR1cm4gbnVsbDsKCQl9CgkJcmV0dXJuIHBrZy5nZXRDbGFzc0ZpbGUoY2xhc3NOYW1lKTsKCX0KCgkvKioKCSAqIFJldHVybnMgY29tcGlsYXRpb24gdW5pdCB3aXRoIGdpdmVuIG5hbWUgaW4gZ2l2ZW4gcHJvamVjdCBhbmQgcGFja2FnZS4KCSAqIEBwYXJhbSBwcm9qZWN0TmFtZQoJICogQHBhcmFtIHBhY2thZ2VOYW1lCgkgKiBAcGFyYW0gdW5pdE5hbWUKCSAqIEByZXR1cm4gb3JnLmVjbGlwc2UuamR0LmNvcmUuSUNvbXBpbGF0aW9uVW5pdAoJICovCglwcm90ZWN0ZWQgSUNvbXBpbGF0aW9uVW5pdCBnZXRDb21waWxhdGlvblVuaXQoU3RyaW5nIHByb2plY3ROYW1lLCBTdHJpbmcgcGFja2FnZU5hbWUsIFN0cmluZyB1bml0TmFtZSkgdGhyb3dzIEphdmFNb2RlbEV4Y2VwdGlvbiB7CgkJSUphdmFQcm9qZWN0IGphdmFQcm9qZWN0ID0gZ2V0UHJvamVjdChwcm9qZWN0TmFtZSk7CgkJaWYgKGphdmFQcm9qZWN0ID09IG51bGwpIHJldHVybiBudWxsOwoJCUlUeXBlIHR5cGUgPSBqYXZhUHJvamVjdC5maW5kVHlwZShwYWNrYWdlTmFtZSwgdW5pdE5hbWUpOwoJCWlmICh0eXBlICE9IG51bGwpIHsKCQkJcmV0dXJuIHR5cGUuZ2V0Q29tcGlsYXRpb25Vbml0KCk7CgkJfQoJCXJldHVybiBudWxsOwoJfQoKCS8qKgoJICogUmV0dXJucyB0aGUgc3BlY2lmaWVkIHBhY2thZ2UgZnJhZ21lbnQgaW4gdGhlIGdpdmVuIHByb2plY3QgYW5kIHJvb3QsIG9yCgkgKiA8Y29kZT5udWxsPC9jb2RlPiBpZiBpdCBkb2VzIG5vdCBleGlzdC4KCSAqIFRoZSByb290UGF0aCBtdXN0IGJlIHNwZWNpZmllZCBhcyBhIHByb2plY3QgcmVsYXRpdmUgcGF0aC4gVGhlIGVtcHR5CgkgKiBwYXRoIHJlZmVycyB0byB0aGUgZGVmYXVsdCBwYWNrYWdlIGZyYWdtZW50LgoJICovCglwcm90ZWN0ZWQgSVBhY2thZ2VGcmFnbWVudCBnZXRQYWNrYWdlRnJhZ21lbnQoSUphdmFQcm9qZWN0IHByb2plY3QsIFN0cmluZyByb290UGF0aCwgU3RyaW5nIHBhY2thZ2VOYW1lKSB0aHJvd3MgSmF2YU1vZGVsRXhjZXB0aW9uIHsKCQlJUGFja2FnZUZyYWdtZW50Um9vdCByb290PSBnZXRQYWNrYWdlRnJhZ21lbnRSb290KHByb2plY3QsIHJvb3RQYXRoKTsKCQlpZiAocm9vdCA9PSBudWxsKSB7CgkJCXJldHVybiBudWxsOwoJCX0KCQlyZXR1cm4gcm9vdC5nZXRQYWNrYWdlRnJhZ21lbnQocGFja2FnZU5hbWUpOwoJfQoKCS8qKgoJICogUmV0dXJucyB0aGUgc3BlY2lmaWVkIHBhY2thZ2UgZnJhZ21lbnQgcm9vdCBpbiB0aGUgZ2l2ZW4gcHJvamVjdCwgb3IKCSAqIDxjb2RlPm51bGw8L2NvZGU+IGlmIGl0IGRvZXMgbm90IGV4aXN0LgoJICogSWYgcmVsYXRpdmUsIHRoZSByb290UGF0aCBtdXN0IGJlIHNwZWNpZmllZCBhcyBhIHByb2plY3QgcmVsYXRpdmUgcGF0aC4KCSAqIFRoZSBlbXB0eSBwYXRoIHJlZmVycyB0byB0aGUgcGFja2FnZSBmcmFnbWVudCByb290IHRoYXQgaXMgdGhlIHByb2plY3QKCSAqIGZvbGRlciBpdGVzbGYuCgkgKiBJZiBhYnNvbHV0ZSwgdGhlIHJvb3RQYXRoIHJlZmVycyB0byBlaXRoZXIgYW4gZXh0ZXJuYWwgamFyLCBvciBhIHJlc291cmNlCgkgKiBpbnRlcm5hbCB0byB0aGUgd29ya3NwYWNlCgkgKi8KCXB1YmxpYyBJUGFja2FnZUZyYWdtZW50Um9vdCBnZXRQYWNrYWdlRnJhZ21lbnRSb290KAoJCUlKYXZhUHJvamVjdCBwcm9qZWN0LAoJCVN0cmluZyByb290UGF0aCkKCQl0aHJvd3MgSmF2YU1vZGVsRXhjZXB0aW9uIHsKCgkJaWYgKHByb2plY3QgPT0gbnVsbCkgewoJCQlyZXR1cm4gbnVsbDsKCQl9CgkJSVBhdGggcGF0aCA9IG5ldyBQYXRoKHJvb3RQYXRoKTsKCQlpZiAocGF0aC5pc0Fic29sdXRlKCkpIHsKCQkJSVdvcmtzcGFjZVJvb3Qgd29ya3NwYWNlUm9vdCA9IFJlc291cmNlc1BsdWdpbi5nZXRXb3Jrc3BhY2UoKS5nZXRSb290KCk7CgkJCUlSZXNvdXJjZSByZXNvdXJjZSA9IHdvcmtzcGFjZVJvb3QuZmluZE1lbWJlcihwYXRoKTsKCQkJSVBhY2thZ2VGcmFnbWVudFJvb3Qgcm9vdDsKCQkJaWYgKHJlc291cmNlID09IG51bGwpIHsKCQkJCS8vIGV4dGVybmFsIGphcgoJCQkJcm9vdCA9IHByb2plY3QuZ2V0UGFja2FnZUZyYWdtZW50Um9vdChyb290UGF0aCk7CgkJCX0gZWxzZSB7CgkJCQkvLyByZXNvdXJjZSBpbiB0aGUgd29ya3NwYWNlCgkJCQlyb290ID0gcHJvamVjdC5nZXRQYWNrYWdlRnJhZ21lbnRSb290KHJlc291cmNlKTsKCQkJfQoJCQlyZXR1cm4gcm9vdDsKCQl9IGVsc2UgewoJCQlJUGFja2FnZUZyYWdtZW50Um9vdFtdIHJvb3RzID0gcHJvamVjdC5nZXRQYWNrYWdlRnJhZ21lbnRSb290cygpOwoJCQlpZiAocm9vdHMgPT0gbnVsbCB8fCByb290cy5sZW5ndGggPT0gMCkgewoJCQkJcmV0dXJuIG51bGw7CgkJCX0KCQkJZm9yIChpbnQgaSA9IDA7IGkgPCByb290cy5sZW5ndGg7IGkrKykgewoJCQkJSVBhY2thZ2VGcmFnbWVudFJvb3Qgcm9vdCA9IHJvb3RzW2ldOwoJCQkJaWYgKCFyb290LmlzRXh0ZXJuYWwoKQoJCQkJCSYmIHJvb3QuZ2V0VW5kZXJseWluZ1Jlc291cmNlKCkuZ2V0UHJvamVjdFJlbGF0aXZlUGF0aCgpLmVxdWFscyhwYXRoKSkgewoJCQkJCXJldHVybiByb290OwoJCQkJfQoJCQl9CgkJfQoJCXJldHVybiBnZXRFeHRlcm5hbEphckZpbGUocHJvamVjdCwgcm9vdFBhdGgpOwoJfQoKCS8qKgoJICogUmV0dXJucyBwcm9qZWN0IGNvcnJlc3BvbmRpbmcgdG8gZ2l2ZW4gbmFtZSBvciBudWxsIGlmIG5vbmUgaXMgZm91bmQuCgkgKiBAcGFyYW0gcHJvamVjdE5hbWUKCSAqIEByZXR1cm4gSUphdmFQcm9qZWN0CgkgKi8KCXByb3RlY3RlZCBJSmF2YVByb2plY3QgZ2V0UHJvamVjdChTdHJpbmcgcHJvamVjdE5hbWUpIHsKCQlmb3IgKGludCBpPTAsIGxlbmd0aCA9IEFMTF9QUk9KRUNUUy5sZW5ndGg7IGk8bGVuZ3RoOyBpKyspIHsKCQkJaWYgKEFMTF9QUk9KRUNUU1tpXS5nZXRFbGVtZW50TmFtZSgpLmVxdWFscyhwcm9qZWN0TmFtZSkpCgkJCQlyZXR1cm4gQUxMX1BST0pFQ1RTW2ldOwoJCX0KCQlyZXR1cm4gbnVsbDsKCX0KCgkvKioKCSAqIFJldHVybnMgYWxsIGNvbXBpbGF0aW9uIHVuaXRzIG9mIGEgZ2l2ZW4gcHJvamVjdC4KCSAqIEBwYXJhbSBqYXZhUHJvamVjdCBQcm9qZWN0IHRvIGNvbGxlY3QgdW5pdHMKCSAqIEByZXR1cm4gTGlzdCBvZiBvcmcuZWNsaXBzZS5qZHQuY29yZS5JQ29tcGlsYXRpb25Vbml0CgkgKi8KCXByb3RlY3RlZCBMaXN0IGdldFByb2plY3RDb21waWxhdGlvblVuaXRzKElKYXZhUHJvamVjdCBqYXZhUHJvamVjdCkgdGhyb3dzIEphdmFNb2RlbEV4Y2VwdGlvbiB7CgkJSVBhY2thZ2VGcmFnbWVudFJvb3RbXSBmcmFnbWVudFJvb3RzID0gamF2YVByb2plY3QuZ2V0UGFja2FnZUZyYWdtZW50Um9vdHMoKTsKCQlpbnQgbGVuZ3RoID0gZnJhZ21lbnRSb290cy5sZW5ndGg7CgkJTGlzdCBhbGxVbml0cyA9IG5ldyBBcnJheUxpc3QoKTsKCQlmb3IgKGludCBpPTA7IGk8bGVuZ3RoOyBpKyspIHsKCQkJaWYgKGZyYWdtZW50Um9vdHNbaV0gaW5zdGFuY2VvZiBKYXJQYWNrYWdlRnJhZ21lbnRSb290KSBjb250aW51ZTsKCQkJSUphdmFFbGVtZW50W10gcGFja2FnZXM9IGZyYWdtZW50Um9vdHNbaV0uZ2V0Q2hpbGRyZW4oKTsKCQkJZm9yIChpbnQgaz0gMDsgayA8IHBhY2thZ2VzLmxlbmd0aDsgaysrKSB7CgkJCQlJUGFja2FnZUZyYWdtZW50IHBhY2sgPSAoSVBhY2thZ2VGcmFnbWVudCkgcGFja2FnZXNba107CgkJCQlJQ29tcGlsYXRpb25Vbml0W10gdW5pdHMgPSBwYWNrLmdldENvbXBpbGF0aW9uVW5pdHMoKTsKCQkJCWZvciAoaW50IHU9MDsgdTx1bml0cy5sZW5ndGg7IHUrKykgewoJCQkJCWFsbFVuaXRzLmFkZCh1bml0c1t1XSk7CgkJCQl9CgkJCX0KCQl9CgkJcmV0dXJuIGFsbFVuaXRzOwoJfQoKCXByb3RlY3RlZCBJUGFja2FnZUZyYWdtZW50Um9vdCBnZXRFeHRlcm5hbEphckZpbGUoSUphdmFQcm9qZWN0IHByb2plY3QsIFN0cmluZyBqYXJTaW1wbGVOYW1lKSB0aHJvd3MgSmF2YU1vZGVsRXhjZXB0aW9uIHsKCQlJUGFja2FnZUZyYWdtZW50Um9vdFtdIHJvb3RzID0gcHJvamVjdC5nZXRQYWNrYWdlRnJhZ21lbnRSb290cygpOwoJCWlmIChyb290cyA9PSBudWxsIHx8IHJvb3RzLmxlbmd0aCA9PSAwKSB7CgkJCXJldHVybiBudWxsOwoJCX0KCQlmb3IgKGludCBpID0gMDsgaSA8IHJvb3RzLmxlbmd0aDsgaSsrKSB7CgkJCUlQYWNrYWdlRnJhZ21lbnRSb290IHJvb3QgPSByb290c1tpXTsKCQkJaWYgKHJvb3QuaXNFeHRlcm5hbCgpICYmIHJvb3QuZ2V0RWxlbWVudE5hbWUoKS5lcXVhbHMoamFyU2ltcGxlTmFtZSkpIHsKCQkJCXJldHVybiByb290OwoJCQl9CgkJfQoJCXJldHVybiBudWxsOwoJfQoJLyoKCSAqIFNpbXVsYXRlIGEgc2F2ZS9leGl0IG9mIHRoZSB3b3Jrc3BhY2UKCSAqLwoJcHJvdGVjdGVkIHZvaWQgc2ltdWxhdGVFeGl0KCkgdGhyb3dzIENvcmVFeGNlcHRpb24gewoJCUFic3RyYWN0SmF2YU1vZGVsVGVzdHMud2FpdEZvckF1dG9CdWlsZCgpOwoJCVJlc291cmNlc1BsdWdpbi5nZXRXb3Jrc3BhY2UoKS5zYXZlKHRydWUvKmZ1bGwgc2F2ZSovLCBudWxsLypubyBwcm9ncmVzcyovKTsKCQlKYXZhTW9kZWxNYW5hZ2VyLmdldEphdmFNb2RlbE1hbmFnZXIoKS5zaHV0ZG93bigpOwoJfQoJLyoKCSAqIFNpbXVsYXRlIGEgc2F2ZS9leGl0L3Jlc3RhcnQgb2YgdGhlIHdvcmtzcGFjZQoJICovCglwcm90ZWN0ZWQgdm9pZCBzaW11bGF0ZUV4aXRSZXN0YXJ0KCkgdGhyb3dzIENvcmVFeGNlcHRpb24gewoJCXNpbXVsYXRlRXhpdCgpOwoJCXNpbXVsYXRlUmVzdGFydCgpOwoJfQoJLyoKCSAqIFNpbXVsYXRlIGEgcmVzdGFydCBvZiB0aGUgd29ya3NwYWNlCgkgKi8KCXByb3RlY3RlZCB2b2lkIHNpbXVsYXRlUmVzdGFydCgpIHRocm93cyBDb3JlRXhjZXB0aW9uIHsKCQlKYXZhTW9kZWxNYW5hZ2VyLmRvTm90VXNlKCk7IC8vIHJlc2V0IHRoZSBNQU5BR0VSIHNpbmdsZXRvbgoJCUphdmFNb2RlbE1hbmFnZXIuZ2V0SmF2YU1vZGVsTWFuYWdlcigpLnN0YXJ0dXAoKTsKCQluZXcgSmF2YUNvcmVQcmVmZXJlbmNlSW5pdGlhbGl6ZXIoKS5pbml0aWFsaXplRGVmYXVsdFByZWZlcmVuY2VzKCk7Cgl9CgoJLyoqCgkgKiBTcGxpdCBhIGxpc3Qgb2YgY29tcGlsYXRpb24gdW5pdHMgaW4gc2V2ZXJhbCBhcnJheXMuCgkgKiBAcGFyYW0gdW5pdHMgTGlzdCBvZiBvcmcuZWNsaXBzZS5qZHQuY29yZS5JQ29tcGlsYXRpb25Vbml0CgkgKiBAcGFyYW0gc3BsaXRTaXplIFNpemUgb2YgdGhlIGFycmF5cwoJICogQHJldHVybiBMaXN0IG9mIElDb21waWxhdGlvblVuaXRbXQoJICovCglwcm90ZWN0ZWQgTGlzdCBzcGxpdExpc3RJblNtYWxsQXJyYXlzKExpc3QgdW5pdHMsIGludCBzcGxpdFNpemUpIHRocm93cyBKYXZhTW9kZWxFeGNlcHRpb24gewoJCWludCBzaXplID0gdW5pdHMuc2l6ZSgpOwoJCWlmIChzaXplID09IDApIHJldHVybiBDb2xsZWN0aW9ucy5FTVBUWV9MSVNUOwoJCWludCBsZW5ndGggPSBzaXplIC8gc3BsaXRTaXplOwoJCWludCByZW1pbmQgPSBzaXplJXNwbGl0U2l6ZTsKCQlMaXN0IHNwbGl0dGVkID0gbmV3IEFycmF5TGlzdChyZW1pbmQ9PTA/bGVuZ3RoOmxlbmd0aCsxKTsKCQlpZiAobGVuZ3RoID09IDApIHsKCQkJSUNvbXBpbGF0aW9uVW5pdFtdIHN1Ymxpc3QgPSBuZXcgSUNvbXBpbGF0aW9uVW5pdFtzaXplXTsKCQkJdW5pdHMudG9BcnJheShzdWJsaXN0KTsKCQkJc3BsaXR0ZWQuYWRkKHN1Ymxpc3QpOwoJCQlyZXR1cm4gc3BsaXR0ZWQ7CgkJfQoJCWludCBwdHIgPSAwOwoJCWZvciAoaW50IGk9IDA7IGk8bGVuZ3RoOyBpKyspewoJCQlJQ29tcGlsYXRpb25Vbml0W10gc3VibGlzdCA9IG5ldyBJQ29tcGlsYXRpb25Vbml0W3NwbGl0U2l6ZV07CgkJCXVuaXRzLnN1Ykxpc3QocHRyLCBwdHIrc3BsaXRTaXplKS50b0FycmF5KHN1Ymxpc3QpOwoJCQlzcGxpdHRlZC5hZGQoc3VibGlzdCk7CgkJCXB0ciArPSBzcGxpdFNpemU7CgkJfQoJCWlmIChyZW1pbmQgPiAwKSB7CgkJCWlmIChyZW1pbmQ8IDEwKSB7CgkJCQlJQ29tcGlsYXRpb25Vbml0W10gbGFzdExpc3QgPSAoSUNvbXBpbGF0aW9uVW5pdFtdKSBzcGxpdHRlZC5yZW1vdmUobGVuZ3RoLTEpOwoJCQkJU3lzdGVtLmFycmF5Y29weShsYXN0TGlzdCwgMCwgbGFzdExpc3QgPSBuZXcgSUNvbXBpbGF0aW9uVW5pdFtzcGxpdFNpemUrcmVtaW5kXSwgMCwgc3BsaXRTaXplKTsKCQkJCWZvciAoaW50IGk9cHRyLCBqPXNwbGl0U2l6ZTsgaTxzaXplOyBpKyssIGorKykgewoJCQkJCWxhc3RMaXN0W2pdID0gKElDb21waWxhdGlvblVuaXQpIHVuaXRzLmdldChpKTsKCQkJCX0KCQkJCXNwbGl0dGVkLmFkZChsYXN0TGlzdCk7CgkJCX0gZWxzZSB7CgkJCQlJQ29tcGlsYXRpb25Vbml0W10gc3VibGlzdCA9IG5ldyBJQ29tcGlsYXRpb25Vbml0W3JlbWluZF07CgkJCQl1bml0cy5zdWJMaXN0KHB0ciwgc2l6ZSkudG9BcnJheShzdWJsaXN0KTsKCQkJCXNwbGl0dGVkLmFkZChzdWJsaXN0KTsKCQkJfQoJCX0KCQlyZXR1cm4gc3BsaXR0ZWQ7Cgl9CgoJLyoKCSAqIENyZWF0ZSBoYXNodGFibGUgb2Ygbm9uZSBvciBhbGwgd2FybmluZyBvcHRpb25zLgoJICogUG9zc2libGUga2luZDoKCSAqIAktMTogbm8gb3B0aW9ucwoJICogIDA6IGRlZmF1bHQgb3B0aW9ucwoJICogIDE6IGFsbCBvcHRpb25zCgkgKi8KCXByb3RlY3RlZCBIYXNodGFibGUgd2FybmluZ09wdGlvbnMoaW50IGtpbmQpIHsKCgkJLy8gVmFsdWVzCgkJSGFzaHRhYmxlIG9wdGlvbnNNYXAgPSBKYXZhQ29yZS5nZXREZWZhdWx0T3B0aW9ucygpOwoJCWlmIChraW5kID09IDApIHsKCQkJLy8gRGVmYXVsdCBzZXQgc2luY2UgMy4xCgkJCW9wdGlvbnNNYXAucHV0KENvbXBpbGVyT3B0aW9ucy5PUFRJT05fUmVwb3J0VW51c2VkSW1wb3J0LCBDb21waWxlck9wdGlvbnMuSUdOT1JFKTsKCQl9IGVsc2UgewoJCQljbGVhck9wdGlvbnMob3B0aW9uc01hcCk7CgkJCWJvb2xlYW4gYWxsID0ga2luZCA9PSAxOwoJCQlTdHJpbmcgZ2VuZXJhdGUgPSBhbGwgPyBDb21waWxlck9wdGlvbnMuR0VORVJBVEUgOiBDb21waWxlck9wdGlvbnMuRE9fTk9UX0dFTkVSQVRFOwoJCQlTdHJpbmcgd2FybmluZyA9IGFsbCA/IENvbXBpbGVyT3B0aW9ucy5XQVJOSU5HIDogQ29tcGlsZXJPcHRpb25zLklHTk9SRTsKCQkJU3RyaW5nIGVuYWJsZWQgPSBhbGwgPyBDb21waWxlck9wdGlvbnMuRU5BQkxFRCA6IENvbXBpbGVyT3B0aW9ucy5ESVNBQkxFRDsKCQkJU3RyaW5nIHByZXNlcnZlID0gYWxsID8gQ29tcGlsZXJPcHRpb25zLk9QVElNSVpFX09VVCA6IENvbXBpbGVyT3B0aW9ucy5QUkVTRVJWRTsKCgkJCS8vIFNldCBvcHRpb25zIHZhbHVlcwoJCQlvcHRpb25zTWFwLnB1dChDb21waWxlck9wdGlvbnMuT1BUSU9OX0xvY2FsVmFyaWFibGVBdHRyaWJ1dGUsIGdlbmVyYXRlKTsKCQkJb3B0aW9uc01hcC5wdXQoQ29tcGlsZXJPcHRpb25zLk9QVElPTl9MaW5lTnVtYmVyQXR0cmlidXRlLCBnZW5lcmF0ZSk7CgkJCW9wdGlvbnNNYXAucHV0KENvbXBpbGVyT3B0aW9ucy5PUFRJT05fU291cmNlRmlsZUF0dHJpYnV0ZSwgZ2VuZXJhdGUpOwoJCQlvcHRpb25zTWFwLnB1dChDb21waWxlck9wdGlvbnMuT1BUSU9OX1ByZXNlcnZlVW51c2VkTG9jYWwsIHByZXNlcnZlKTsKCQkJb3B0aW9uc01hcC5wdXQoQ29tcGlsZXJPcHRpb25zLk9QVElPTl9Eb2NDb21tZW50U3VwcG9ydCwgZW5hYmxlZCk7CgkJCW9wdGlvbnNNYXAucHV0KENvbXBpbGVyT3B0aW9ucy5PUFRJT05fUmVwb3J0TWV0aG9kV2l0aENvbnN0cnVjdG9yTmFtZSwgd2FybmluZyk7CgkJCW9wdGlvbnNNYXAucHV0KENvbXBpbGVyT3B0aW9ucy5PUFRJT05fUmVwb3J0T3ZlcnJpZGluZ1BhY2thZ2VEZWZhdWx0TWV0aG9kLCB3YXJuaW5nKTsKCQkJb3B0aW9uc01hcC5wdXQoQ29tcGlsZXJPcHRpb25zLk9QVElPTl9SZXBvcnREZXByZWNhdGlvbiwgd2FybmluZyk7CgkJCW9wdGlvbnNNYXAucHV0KENvbXBpbGVyT3B0aW9ucy5PUFRJT05fUmVwb3J0RGVwcmVjYXRpb25JbkRlcHJlY2F0ZWRDb2RlLCBlbmFibGVkKTsKCQkJb3B0aW9uc01hcC5wdXQoQ29tcGlsZXJPcHRpb25zLk9QVElPTl9SZXBvcnREZXByZWNhdGlvbldoZW5PdmVycmlkaW5nRGVwcmVjYXRlZE1ldGhvZCwgZW5hYmxlZCk7CgkJCW9wdGlvbnNNYXAucHV0KENvbXBpbGVyT3B0aW9ucy5PUFRJT05fUmVwb3J0SGlkZGVuQ2F0Y2hCbG9jaywgd2FybmluZyk7CgkJCW9wdGlvbnNNYXAucHV0KENvbXBpbGVyT3B0aW9ucy5PUFRJT05fUmVwb3J0VW51c2VkTG9jYWwsIHdhcm5pbmcpOwoJCQlvcHRpb25zTWFwLnB1dChDb21waWxlck9wdGlvbnMuT1BUSU9OX1JlcG9ydFVudXNlZFBhcmFtZXRlciwgd2FybmluZyk7CgkJCW9wdGlvbnNNYXAucHV0KENvbXBpbGVyT3B0aW9ucy5PUFRJT05fUmVwb3J0VW51c2VkSW1wb3J0LCB3YXJuaW5nKTsKCQkJb3B0aW9uc01hcC5wdXQoQ29tcGlsZXJPcHRpb25zLk9QVElPTl9SZXBvcnRTeW50aGV0aWNBY2Nlc3NFbXVsYXRpb24sIHdhcm5pbmcpOwoJCQlvcHRpb25zTWFwLnB1dChDb21waWxlck9wdGlvbnMuT1BUSU9OX1JlcG9ydE5vRWZmZWN0QXNzaWdubWVudCwgd2FybmluZyk7CgkJCW9wdGlvbnNNYXAucHV0KENvbXBpbGVyT3B0aW9ucy5PUFRJT05fUmVwb3J0Tm9uRXh0ZXJuYWxpemVkU3RyaW5nTGl0ZXJhbCwgd2FybmluZyk7CgkJCW9wdGlvbnNNYXAucHV0KENvbXBpbGVyT3B0aW9ucy5PUFRJT05fUmVwb3J0Tm9JbXBsaWNpdFN0cmluZ0NvbnZlcnNpb24sIHdhcm5pbmcpOwoJCQlvcHRpb25zTWFwLnB1dChDb21waWxlck9wdGlvbnMuT1BUSU9OX1JlcG9ydE5vblN0YXRpY0FjY2Vzc1RvU3RhdGljLCB3YXJuaW5nKTsKCQkJb3B0aW9uc01hcC5wdXQoQ29tcGlsZXJPcHRpb25zLk9QVElPTl9SZXBvcnRJbmRpcmVjdFN0YXRpY0FjY2Vzcywgd2FybmluZyk7CgkJCW9wdGlvbnNNYXAucHV0KENvbXBpbGVyT3B0aW9ucy5PUFRJT05fUmVwb3J0SW5jb21wYXRpYmxlTm9uSW5oZXJpdGVkSW50ZXJmYWNlTWV0aG9kLCB3YXJuaW5nKTsKCQkJb3B0aW9uc01hcC5wdXQoQ29tcGlsZXJPcHRpb25zLk9QVElPTl9SZXBvcnRVbnVzZWRQcml2YXRlTWVtYmVyLCB3YXJuaW5nKTsKCQkJb3B0aW9uc01hcC5wdXQoQ29tcGlsZXJPcHRpb25zLk9QVElPTl9SZXBvcnRMb2NhbFZhcmlhYmxlSGlkaW5nLCB3YXJuaW5nKTsKCQkJb3B0aW9uc01hcC5wdXQoQ29tcGlsZXJPcHRpb25zLk9QVElPTl9SZXBvcnRGaWVsZEhpZGluZywgd2FybmluZyk7CgkJCW9wdGlvbnNNYXAucHV0KENvbXBpbGVyT3B0aW9ucy5PUFRJT05fUmVwb3J0UG9zc2libGVBY2NpZGVudGFsQm9vbGVhbkFzc2lnbm1lbnQsIHdhcm5pbmcpOwoJCQlvcHRpb25zTWFwLnB1dChDb21waWxlck9wdGlvbnMuT1BUSU9OX1JlcG9ydEVtcHR5U3RhdGVtZW50LCB3YXJuaW5nKTsKCQkJb3B0aW9uc01hcC5wdXQoQ29tcGlsZXJPcHRpb25zLk9QVElPTl9SZXBvcnRBc3NlcnRJZGVudGlmaWVyLCB3YXJuaW5nKTsKCQkJb3B0aW9uc01hcC5wdXQoQ29tcGlsZXJPcHRpb25zLk9QVElPTl9SZXBvcnRVbmRvY3VtZW50ZWRFbXB0eUJsb2NrLCB3YXJuaW5nKTsKCQkJb3B0aW9uc01hcC5wdXQoQ29tcGlsZXJPcHRpb25zLk9QVElPTl9SZXBvcnRVbm5lY2Vzc2FyeVR5cGVDaGVjaywgd2FybmluZyk7CgkJCW9wdGlvbnNNYXAucHV0KENvbXBpbGVyT3B0aW9ucy5PUFRJT05fUmVwb3J0VW5uZWNlc3NhcnlFbHNlLCB3YXJuaW5nKTsKCQkJb3B0aW9uc01hcC5wdXQoQ29tcGlsZXJPcHRpb25zLk9QVElPTl9SZXBvcnRJbnZhbGlkSmF2YWRvYywgd2FybmluZyk7CgkJCW9wdGlvbnNNYXAucHV0KENvbXBpbGVyT3B0aW9ucy5PUFRJT05fUmVwb3J0SW52YWxpZEphdmFkb2NUYWdzLCBlbmFibGVkKTsKCQkJb3B0aW9uc01hcC5wdXQoQ29tcGlsZXJPcHRpb25zLk9QVElPTl9SZXBvcnRNaXNzaW5nSmF2YWRvY1RhZ3MsIHdhcm5pbmcpOwoJCQlvcHRpb25zTWFwLnB1dChDb21waWxlck9wdGlvbnMuT1BUSU9OX1JlcG9ydE1pc3NpbmdKYXZhZG9jQ29tbWVudHMsIHdhcm5pbmcpOwoJCQlvcHRpb25zTWFwLnB1dChDb21waWxlck9wdGlvbnMuT1BUSU9OX1JlcG9ydEZpbmFsbHlCbG9ja05vdENvbXBsZXRpbmdOb3JtYWxseSwgd2FybmluZyk7CgkJCW9wdGlvbnNNYXAucHV0KENvbXBpbGVyT3B0aW9ucy5PUFRJT05fUmVwb3J0VW51c2VkRGVjbGFyZWRUaHJvd25FeGNlcHRpb24sIHdhcm5pbmcpOwoJCQlvcHRpb25zTWFwLnB1dChDb21waWxlck9wdGlvbnMuT1BUSU9OX1JlcG9ydFVucXVhbGlmaWVkRmllbGRBY2Nlc3MsIHdhcm5pbmcpOwoJCQlvcHRpb25zTWFwLnB1dChDb21waWxlck9wdGlvbnMuT1BUSU9OX1Rhc2tUYWdzLCBhbGwgPyBKYXZhQ29yZS5ERUZBVUxUX1RBU0tfVEFHUyA6ICIiKTsKCQkJb3B0aW9uc01hcC5wdXQoQ29tcGlsZXJPcHRpb25zLk9QVElPTl9UYXNrUHJpb3JpdGllcywgYWxsID8gSmF2YUNvcmUuREVGQVVMVF9UQVNLX1BSSU9SSVRJRVMgOiAiIik7CgkJCW9wdGlvbnNNYXAucHV0KENvbXBpbGVyT3B0aW9ucy5PUFRJT05fVGFza0Nhc2VTZW5zaXRpdmUsIGVuYWJsZWQpOwoJCQlvcHRpb25zTWFwLnB1dChDb21waWxlck9wdGlvbnMuT1BUSU9OX1JlcG9ydFVudXNlZFBhcmFtZXRlcldoZW5JbXBsZW1lbnRpbmdBYnN0cmFjdCwgZW5hYmxlZCk7CgkJCW9wdGlvbnNNYXAucHV0KENvbXBpbGVyT3B0aW9ucy5PUFRJT05fUmVwb3J0VW51c2VkUGFyYW1ldGVyV2hlbk92ZXJyaWRpbmdDb25jcmV0ZSwgZW5hYmxlZCk7CgkJCW9wdGlvbnNNYXAucHV0KENvbXBpbGVyT3B0aW9ucy5PUFRJT05fUmVwb3J0U3BlY2lhbFBhcmFtZXRlckhpZGluZ0ZpZWxkLCBlbmFibGVkKTsKCQkJb3B0aW9uc01hcC5wdXQoQ29tcGlsZXJPcHRpb25zLk9QVElPTl9JbmxpbmVKc3IsIGVuYWJsZWQpOwoJCX0KCgkJLy8gSWdub3JlIDMuMSBvcHRpb25zCgkJb3B0aW9uc01hcC5wdXQoQ29tcGlsZXJPcHRpb25zLk9QVElPTl9SZXBvcnRNaXNzaW5nU2VyaWFsVmVyc2lvbiwgQ29tcGlsZXJPcHRpb25zLklHTk9SRSk7CgkJb3B0aW9uc01hcC5wdXQoQ29tcGlsZXJPcHRpb25zLk9QVElPTl9SZXBvcnRFbnVtSWRlbnRpZmllciwgQ29tcGlsZXJPcHRpb25zLklHTk9SRSk7CgoJCS8vIElnbm9yZSAzLjIgb3B0aW9ucwoJCW9wdGlvbnNNYXAucHV0KENvbXBpbGVyT3B0aW9ucy5PUFRJT05fUmVwb3J0VW51c2VkTGFiZWwsIENvbXBpbGVyT3B0aW9ucy5JR05PUkUpOwoKCQkvLyBTZXQgY29tcGxpYW5jZQoJCVN0cmluZyBjb21wbGlhbmNlPSBjb21wbGlhbmNlKCk7CgkJaWYgKGNvbXBsaWFuY2UgIT0gbnVsbCkgewoJCQlvcHRpb25zTWFwLnB1dChDb21waWxlck9wdGlvbnMuT1BUSU9OX0NvbXBsaWFuY2UsIGNvbXBsaWFuY2UpOwoJCQlvcHRpb25zTWFwLnB1dChDb21waWxlck9wdGlvbnMuT1BUSU9OX1NvdXJjZSwgY29tcGxpYW5jZSk7CgkJCW9wdGlvbnNNYXAucHV0KENvbXBpbGVyT3B0aW9ucy5PUFRJT05fVGFyZ2V0UGxhdGZvcm0sIGNvbXBsaWFuY2UpOwoJCX0KCgkJLy8gUmV0dXJuIGNyZWF0ZWQgb3B0aW9ucyBtYXAKCQlyZXR1cm4gb3B0aW9uc01hcDsKCX0KCglwcm90ZWN0ZWQgU3RyaW5nIGdldEV4dGVybmFsUGF0aCgpIHsKCQlTdHJpbmcgcGF0aCA9ICIiOwoJCXRyeSB7CgkJCXBhdGggPSBSZXNvdXJjZXNQbHVnaW4uZ2V0V29ya3NwYWNlKCkuZ2V0Um9vdCgpLmdldExvY2F0aW9uKCkudG9GaWxlKCkuZ2V0UGFyZW50RmlsZSgpLmdldENhbm9uaWNhbFBhdGgoKTsKCQkJaWYgKHBhdGguY2hhckF0KHBhdGgubGVuZ3RoKCktMSkgIT0gRmlsZS5zZXBhcmF0b3JDaGFyKQoJCQkJcGF0aCArPSBGaWxlLnNlcGFyYXRvckNoYXI7CgkJfSBjYXRjaCAoSU9FeGNlcHRpb24gZSkgewoJCQllLnByaW50U3RhY2tUcmFjZSgpOwoJCX0KCQlyZXR1cm4gcGF0aDsKCX0KCglwcm90ZWN0ZWQgU3RyaW5nIGdldEV4dGVybmFsUmVzb3VyY2VQYXRoKFN0cmluZyByZWxhdGl2ZVBhdGgpIHsKCQlyZXR1cm4gZ2V0RXh0ZXJuYWxQYXRoKCkgKyByZWxhdGl2ZVBhdGg7Cgl9Cn0K