LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogQ29weXJpZ2h0IChjKSAyMDA0LCAyMDE4IElCTSBDb3Jwb3JhdGlvbiBhbmQgb3RoZXJzLgogKgogKiBUaGlzIHByb2dyYW0gYW5kIHRoZSBhY2NvbXBhbnlpbmcgbWF0ZXJpYWxzCiAqIGFyZSBtYWRlIGF2YWlsYWJsZSB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEVjbGlwc2UgUHVibGljIExpY2Vuc2UgMi4wCiAqIHdoaWNoIGFjY29tcGFuaWVzIHRoaXMgZGlzdHJpYnV0aW9uLCBhbmQgaXMgYXZhaWxhYmxlIGF0CiAqIGh0dHBzOi8vd3d3LmVjbGlwc2Uub3JnL2xlZ2FsL2VwbC0yLjAvCiAqCiAqIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBFUEwtMi4wCiAqCiAqIENvbnRyaWJ1dG9yczoKICogICAgIElCTSBDb3Jwb3JhdGlvbiAtIGluaXRpYWwgQVBJIGFuZCBpbXBsZW1lbnRhdGlvbgogKiAgICAgTWlja2FlbCBJc3RyaWEgKFJlZCBIYXQgSW5jLikgLSBbMjYzMzE2XSByZWdleHAgZm9yIGZpbGUgYXNzb2NpYXRpb24KICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovCnBhY2thZ2Ugb3JnLmVjbGlwc2UuY29yZS50ZXN0cy5yZXNvdXJjZXMuY29udGVudDsKCmltcG9ydCBzdGF0aWMgb3JnLmVjbGlwc2UuY29yZS50ZXN0cy5yZXNvdXJjZXMuQXV0b21hdGVkVGVzdHMuUElfUkVTT1VSQ0VTX1RFU1RTOwppbXBvcnQgc3RhdGljIG9yZy5qdW5pdC5Bc3NlcnQuYXNzZXJ0RXF1YWxzOwppbXBvcnQgc3RhdGljIG9yZy5qdW5pdC5Bc3NlcnQuYXNzZXJ0RmFsc2U7CmltcG9ydCBzdGF0aWMgb3JnLmp1bml0LkFzc2VydC5hc3NlcnROb3ROdWxsOwppbXBvcnQgc3RhdGljIG9yZy5qdW5pdC5Bc3NlcnQuYXNzZXJ0Tm90U2FtZTsKaW1wb3J0IHN0YXRpYyBvcmcuanVuaXQuQXNzZXJ0LmFzc2VydE51bGw7CmltcG9ydCBzdGF0aWMgb3JnLmp1bml0LkFzc2VydC5hc3NlcnRTYW1lOwppbXBvcnQgc3RhdGljIG9yZy5qdW5pdC5Bc3NlcnQuYXNzZXJ0VGhyb3dzOwppbXBvcnQgc3RhdGljIG9yZy5qdW5pdC5Bc3NlcnQuYXNzZXJ0VHJ1ZTsKCmltcG9ydCBqYXZhLmlvLio7CmltcG9ydCBqYXZhLm5pby5jaGFyc2V0LkNoYXJzZXQ7CmltcG9ydCBqYXZhLm5pby5jaGFyc2V0LlN0YW5kYXJkQ2hhcnNldHM7CmltcG9ydCBqYXZhLnV0aWwuSGFzaFNldDsKaW1wb3J0IGphdmEudXRpbC5TZXQ7CmltcG9ydCBvcmcuZWNsaXBzZS5jb3JlLmludGVybmFsLmNvbnRlbnQuKjsKaW1wb3J0IG9yZy5lY2xpcHNlLmNvcmUucnVudGltZS4qOwppbXBvcnQgb3JnLmVjbGlwc2UuY29yZS5ydW50aW1lLmNvbnRlbnQuKjsKaW1wb3J0IG9yZy5lY2xpcHNlLmNvcmUucnVudGltZS5jb250ZW50LklDb250ZW50VHlwZU1hbmFnZXIuQ29udGVudFR5cGVDaGFuZ2VFdmVudDsKaW1wb3J0IG9yZy5lY2xpcHNlLmNvcmUucnVudGltZS5jb250ZW50LlhNTENvbnRlbnREZXNjcmliZXI7CmltcG9ydCBvcmcuZWNsaXBzZS5jb3JlLnJ1bnRpbWUuam9icy5Kb2I7CmltcG9ydCBvcmcuZWNsaXBzZS5jb3JlLnJ1bnRpbWUucHJlZmVyZW5jZXMuKjsKaW1wb3J0IG9yZy5lY2xpcHNlLmNvcmUudGVzdHMuaGFybmVzcy4qOwppbXBvcnQgb3JnLmp1bml0LkFmdGVyOwppbXBvcnQgb3JnLmp1bml0LlRlc3Q7CmltcG9ydCBvcmcub3NnaS5zZXJ2aWNlLnByZWZzLkJhY2tpbmdTdG9yZUV4Y2VwdGlvbjsKaW1wb3J0IG9yZy5vc2dpLnNlcnZpY2UucHJlZnMuUHJlZmVyZW5jZXM7CgpwdWJsaWMgY2xhc3MgSUNvbnRlbnRUeXBlTWFuYWdlclRlc3QgZXh0ZW5kcyBDb250ZW50VHlwZVRlc3QgewoKCXByaXZhdGUgc3RhdGljIGNsYXNzIENvbnRlbnRUeXBlQ2hhbmdlVHJhY2VyIGltcGxlbWVudHMgSUNvbnRlbnRUeXBlTWFuYWdlci5JQ29udGVudFR5cGVDaGFuZ2VMaXN0ZW5lciB7CgkJcHJpdmF0ZSBmaW5hbCBTZXQ8SUNvbnRlbnRUeXBlPiBjaGFuZ2VkID0gbmV3IEhhc2hTZXQ8PigpOwoKCQlwdWJsaWMgQ29udGVudFR5cGVDaGFuZ2VUcmFjZXIoKSB7CgkJfQoKCQlAT3ZlcnJpZGUKCQlwdWJsaWMgdm9pZCBjb250ZW50VHlwZUNoYW5nZWQoQ29udGVudFR5cGVDaGFuZ2VFdmVudCBldmVudCkgewoJCQljaGFuZ2VkLmFkZChldmVudC5nZXRDb250ZW50VHlwZSgpKTsKCQl9CgoJCXB1YmxpYyBib29sZWFuIGlzT25seUNoYW5nZShJQ29udGVudFR5cGUgbXlUeXBlKSB7CgkJCXJldHVybiBjaGFuZ2VkLnNpemUoKSA9PSAxICYmIGNoYW5nZWQuY29udGFpbnMobXlUeXBlKTsKCQl9CgoJCXB1YmxpYyB2b2lkIHJlc2V0KCkgewoJCQljaGFuZ2VkLmNsZWFyKCk7CgkJfQoJfQoKCS8vIFhYWCB0aGlzIGlzIGNvcGllZCBmcm9tIENoYXJzZXREZWx0YUpvYiBpbiB0aGUgcmVzb3VyY2VzIHBsdWctaW4KCXByaXZhdGUgc3RhdGljIGZpbmFsIFN0cmluZyBGQU1JTFlfQ0hBUlNFVF9ERUxUQSA9ICJvcmcuZWNsaXBzZS5jb3JlLnJlc291cmNlcy5jaGFyc2V0Sm9iRmFtaWx5IjsKCglwcml2YXRlIGZpbmFsIHN0YXRpYyBTdHJpbmcgTUlOSU1BTF9YTUwgPSAiPD94bWwgdmVyc2lvbj1cIjEuMFwiPz48b3JnLmVjbGlwc2UuY29yZS5yZXNvdXJjZXMudGVzdHMucm9vdC8+IjsKCXByaXZhdGUgZmluYWwgc3RhdGljIFN0cmluZyBTQU1QTEVfQklOMV9PRkZTRVQgPSAiMTIzNDUiOwoJcHJpdmF0ZSBmaW5hbCBzdGF0aWMgYnl0ZVtdIFNBTVBMRV9CSU4xX1NJR05BVFVSRSA9IHsgMHgxMCwgKGJ5dGUpIDB4QUIsIChieXRlKSAweENELCAoYnl0ZSkgMHhGRiB9OwoJcHJpdmF0ZSBmaW5hbCBzdGF0aWMgU3RyaW5nIFNBTVBMRV9CSU4yX09GRlNFVCA9ICIiOwoJcHJpdmF0ZSBmaW5hbCBzdGF0aWMgYnl0ZVtdIFNBTVBMRV9CSU4yX1NJR05BVFVSRSA9IHsgMHgxMCwgKGJ5dGUpIDB4QUIsIChieXRlKSAweENELCAoYnl0ZSkgMHhFRiB9OwoJcHJpdmF0ZSBmaW5hbCBzdGF0aWMgU3RyaW5nIFhNTF9EVERfRVhURVJOQUxfRU5USVRZID0gIjw/eG1sIHZlcnNpb249XCIxLjBcIj8+PCFET0NUWVBFIHByb2plY3QgIFNZU1RFTSBcIm9yZy5lY2xpcHNlLmNvcmUucmVzb3VyY2VzLnRlc3RzLnNvbWUuZHRkXCIgIFs8IUVOVElUWSBzb21lZW50aXR5IFNZU1RFTSBcInNvbWVlbnRpdHkueG1sXCI+XT48b3JnLmVjbGlwc2UuY29yZS5yZXNvdXJjZXMudGVzdHMucm9vdC8+IjsKCXByaXZhdGUgZmluYWwgc3RhdGljIFN0cmluZyBYTUxfRFREX1VTX0FTQ0lJID0gIjw/eG1sIHZlcnNpb249XCIxLjBcIiBlbmNvZGluZz1cIlVTLUFTQ0lJXCI/PjwhRE9DVFlQRSBzb21ldHlwZSBTWVNURU0gXCJvcmcuZWNsaXBzZS5jb3JlLnJlc291cmNlcy50ZXN0cy5zb21lLmR0ZFwiPjxvcmcuZWNsaXBzZS5jb3JlLnJlc291cmNlcy50ZXN0cy5yb290Lz4iOwoJcHJpdmF0ZSBmaW5hbCBzdGF0aWMgU3RyaW5nIFhNTF9JU09fODg1OV8xID0gIjw/eG1sIHZlcnNpb249XCIxLjBcIiBlbmNvZGluZz1cIklTTy04ODU5LTFcIj8+PG9yZy5lY2xpcHNlLmNvcmUucmVzb3VyY2VzLnRlc3RzLnJvb3QvPiI7Cglwcml2YXRlIGZpbmFsIHN0YXRpYyBTdHJpbmcgWE1MX0lTT184ODU5XzFfU0lOR0xFX1FVT1RFUyA9ICI8P3htbCB2ZXJzaW9uPScxLjAnIGVuY29kaW5nPSdJU08tODg1OS0xJz8+PG9yZy5lY2xpcHNlLmNvcmUucmVzb3VyY2VzLnRlc3RzLnJvb3QvPiI7Cglwcml2YXRlIGZpbmFsIHN0YXRpYyBTdHJpbmcgWE1MX1JPT1RfRUxFTUVOVF9FWFRFUk5BTF9FTlRJVFkgPSAiPD94bWwgdmVyc2lvbj1cIjEuMFwiPz48IURPQ1RZUEUgcHJvamVjdCAgIFs8IUVOVElUWSBzb21lZW50aXR5IFNZU1RFTSBcInNvbWVlbnRpdHkueG1sXCI+XT48b3JnLmVjbGlwc2UuY29yZS5yZXNvdXJjZXMudGVzdHMucm9vdC1lbGVtZW50Lz4iOwoJcHJpdmF0ZSBmaW5hbCBzdGF0aWMgU3RyaW5nIFhNTF9ST09UX0VMRU1FTlRfRVhURVJOQUxfRU5USVRZMiA9ICI8P3htbCB2ZXJzaW9uPVwiMS4wXCI/PjwhRE9DVFlQRSBvcmcuZWNsaXBzZS5jb3JlLnJlc291cmNlcy50ZXN0cy5yb290LWVsZW1lbnQgUFVCTElDIFwib3JnLmVjbGlwc2UuY29yZS5yZXNvdXJjZXMudGVzdHMucm9vdC1lbGVtZW50SWRcIiBcIm9yZy5lY2xpcHNlLmNvcmUucmVzb3VyY2VzLnRlc3RzLnJvb3QtZWxlbWVudC5kdGRcIiA+PG9yZy5lY2xpcHNlLmNvcmUucmVzb3VyY2VzLnRlc3RzLnJvb3QtZWxlbWVudC8+IjsKCXByaXZhdGUgZmluYWwgc3RhdGljIFN0cmluZyBYTUxfUk9PVF9FTEVNRU5UX0lTT184ODU5XzEgPSAiPD94bWwgdmVyc2lvbj1cIjEuMFwiIGVuY29kaW5nPVwiSVNPLTg4NTktMVwiPz48b3JnLmVjbGlwc2UuY29yZS5yZXNvdXJjZXMudGVzdHMucm9vdC1lbGVtZW50Lz4iOwoJcHJpdmF0ZSBmaW5hbCBzdGF0aWMgU3RyaW5nIFhNTF9ST09UX0VMRU1FTlRfTk9fREVDTCA9ICI8b3JnLmVjbGlwc2UuY29yZS5yZXNvdXJjZXMudGVzdHMucm9vdC1lbGVtZW50Lz4iOwoJcHJpdmF0ZSBmaW5hbCBzdGF0aWMgU3RyaW5nIFhNTF9VU19BU0NJSV9JTlZBTElEID0gIjw/eG1sIHZlcnNpb249JzEuMCcgZW5jb2Rpbmc9J3VzLWFzY2lpJz8+PCEtLSBOb24tQVNDSUkgY2hhcnM6IOHp7fP6IC0tPjxvcmcuZWNsaXBzZS5jb3JlLnJlc291cmNlcy50ZXN0cy5yb290Lz4iOwoJcHJpdmF0ZSBmaW5hbCBzdGF0aWMgU3RyaW5nIFhNTF9VVEZfMTYgPSAiPD94bWwgdmVyc2lvbj1cIjEuMFwiIGVuY29kaW5nPVwiVVRGLTE2XCI/PjxvcmcuZWNsaXBzZS5jb3JlLnJlc291cmNlcy50ZXN0cy5yb290Lz4iOwoJcHJpdmF0ZSBmaW5hbCBzdGF0aWMgU3RyaW5nIFhNTF9VVEZfMTZCRSA9ICI8P3htbCB2ZXJzaW9uPVwiMS4wXCIgZW5jb2Rpbmc9XCJVVEYtMTZCRVwiPz48b3JnLmVjbGlwc2UuY29yZS5yZXNvdXJjZXMudGVzdHMucm9vdC8+IjsKCXByaXZhdGUgZmluYWwgc3RhdGljIFN0cmluZyBYTUxfVVRGXzE2TEUgPSAiPD94bWwgdmVyc2lvbj1cIjEuMFwiIGVuY29kaW5nPVwiVVRGLTE2TEVcIj8+PG9yZy5lY2xpcHNlLmNvcmUucmVzb3VyY2VzLnRlc3RzLnJvb3QvPiI7Cglwcml2YXRlIGZpbmFsIHN0YXRpYyBTdHJpbmcgWE1MX1VURl84ID0gIjw/eG1sIHZlcnNpb249XCIxLjBcIiBlbmNvZGluZz1cIlVURi04XCI/PjxvcmcuZWNsaXBzZS5jb3JlLnJlc291cmNlcy50ZXN0cy5yb290Lz4iOwoKCS8vIHVzZWQgYWxzbyBieSBGaWxlUHJvcGVydHlUZXN0ZXJUZXN0CglwdWJsaWMgc3RhdGljIGZpbmFsIFN0cmluZyBYTUxfUk9PVF9FTEVNRU5UX05TX01BVENIMSA9ICI8P3htbCB2ZXJzaW9uPVwiMS4wXCIgZW5jb2Rpbmc9XCJJU08tODg1OS0xXCI/PjxwcmVmaXg6cm9vdEVsZW1lbnQxIHhtbG5zOnByZWZpeD0ndXJuOmVjbGlwc2UuY29yZS5ydW50aW1lLm5zMScvPiI7CgoJcHJpdmF0ZSBzdGF0aWMgZmluYWwgU3RyaW5nIFhNTF9ST09UX0VMRU1FTlRfTlNfTUFUQ0gyID0gIjw/eG1sIHZlcnNpb249XCIxLjBcIiBlbmNvZGluZz1cIklTTy04ODU5LTFcIj8+PCFET0NUWVBFIHJvb3RFbGVtZW50MiBTWVNURU0gXCJvcmcuZWNsaXBzZS5jb3JlLnJlc291cmNlcy50ZXN0cy5ub3RoaW5nXCI+PHJvb3RFbGVtZW50MiB4bWxucz0ndXJuOmVjbGlwc2UuY29yZS5ydW50aW1lLm5zMicvPiI7Cglwcml2YXRlIHN0YXRpYyBmaW5hbCBTdHJpbmcgWE1MX1JPT1RfRUxFTUVOVF9OU19XUk9OR19FTEVNID0gIjw/eG1sIHZlcnNpb249XCIxLjBcIiBlbmNvZGluZz1cIklTTy04ODU5LTFcIj8+PHJvb3RFbGVtZW50MyB4bWxucz0ndXJuOmVjbGlwc2UuY29yZS5ydW50aW1lLm5zMicvPiI7Cglwcml2YXRlIHN0YXRpYyBmaW5hbCBTdHJpbmcgWE1MX1JPT1RfRUxFTUVOVF9OU19XUk9OR19OUyA9ICI8P3htbCB2ZXJzaW9uPVwiMS4wXCIgZW5jb2Rpbmc9XCJJU08tODg1OS0xXCI/PjxwcmVmaXg6cm9vdEVsZW1lbnQxIHhtbG5zPSdodHRwOi8vZXhhbXBsZS5jb20vJy8+IjsKCXByaXZhdGUgc3RhdGljIGZpbmFsIFN0cmluZyBYTUxfUk9PVF9FTEVNRU5UX05TX01JWFVQID0gIjw/eG1sIHZlcnNpb249XCIxLjBcIiBlbmNvZGluZz1cIklTTy04ODU5LTFcIj8+PHJvb3RFbGVtZW50MiB4bWxucz0ndXJuOmVjbGlwc2UuY29yZS5ydW50aW1lLm5zMScvPiI7Cglwcml2YXRlIHN0YXRpYyBmaW5hbCBTdHJpbmcgWE1MX1JPT1RfRUxFTUVOVF9OU19XSUxEQ0FSRCA9ICI8P3htbCB2ZXJzaW9uPVwiMS4wXCIgZW5jb2Rpbmc9XCJJU08tODg1OS0xXCI/Pjx3ZUNvdWxkUHV0QW55dGhpbmdIZXJlIHhtbG5zPSd1cm46ZWNsaXBzZS5jb3JlLnJ1bnRpbWUubnNXaWxkJy8+IjsKCXByaXZhdGUgZmluYWwgc3RhdGljIFN0cmluZyBYTUxfUk9PVF9FTEVNRU5UX05TX1dJTERDQVJEMiA9ICI8P3htbCB2ZXJzaW9uPVwiMS4wXCIgZW5jb2Rpbmc9XCJVUy1BU0NJSVwiPz48IURPQ1RZUEUgSm9rZXIgU1lTVEVNIFwib3JnLmVjbGlwc2UuY29yZS5yZXNvdXJjZXMudGVzdHMuc29tZS5kdGQzXCI+PEpva2VyLz4iOwoJcHJpdmF0ZSBmaW5hbCBzdGF0aWMgU3RyaW5nIFhNTF9ST09UX0VMRU1FTlRfRU1QVFlfTlMgPSAiPD94bWwgdmVyc2lvbj1cIjEuMFwiIGVuY29kaW5nPVwiVVMtQVNDSUlcIj8+PCFET0NUWVBFIEpva2VyIFNZU1RFTSBcIm9yZy5lY2xpcHNlLmNvcmUucmVzb3VyY2VzLnRlc3RzLnNvbWUuZHRkM1wiPjxyb290RWxlbWVudD4iOwoKCS8qKgoJICogSGVscHMgdG8gZW5zdXJlIHdlIGRvbid0IGdldCBmb29sZWQgYnkgY2FzZSBzZW5zaXRpdml0eSBpbiBmaWxlIG5hbWVzL3NwZWNzLgoJICovCglwcml2YXRlIFN0cmluZyBjaGFuZ2VDYXNlKFN0cmluZyBvcmlnaW5hbCkgewoJCVN0cmluZ0J1aWxkZXIgcmVzdWx0ID0gbmV3IFN0cmluZ0J1aWxkZXIob3JpZ2luYWwpOwoJCWZvciAoaW50IGkgPSByZXN1bHQubGVuZ3RoKCkgLSAxOyBpID49IDA7IGktLSkgewoJCQljaGFyIG9yaWdpbmFsQ2hhciA9IG9yaWdpbmFsLmNoYXJBdChpKTsKCQkJcmVzdWx0LnNldENoYXJBdChpLCBpICUgMiA9PSAwID8gQ2hhcmFjdGVyLnRvTG93ZXJDYXNlKG9yaWdpbmFsQ2hhcikgOiBDaGFyYWN0ZXIudG9VcHBlckNhc2Uob3JpZ2luYWxDaGFyKSk7CgkJfQoJCXJldHVybiByZXN1bHQudG9TdHJpbmcoKTsKCX0KCglib29sZWFuIGNvbnRhaW5zKE9iamVjdFtdIGFycmF5LCBPYmplY3QgZWxlbWVudCkgewoJCWZvciAoT2JqZWN0IGVsZW1lbnQyIDogYXJyYXkpIHsKCQkJaWYgKGVsZW1lbnQyLmVxdWFscyhlbGVtZW50KSkgewoJCQkJcmV0dXJuIHRydWU7CgkJCX0KCQl9CgkJcmV0dXJuIGZhbHNlOwoJfQoKCXByaXZhdGUgSUNvbnRlbnREZXNjcmlwdGlvbiBnZXREZXNjcmlwdGlvbkZvcihJQ29udGVudFR5cGVNYXRjaGVyIGZpbmRlciwgU3RyaW5nIGNvbnRlbnRzLCBDaGFyc2V0IGVuY29kaW5nLAoJCQlTdHJpbmcgZmlsZU5hbWUsIFF1YWxpZmllZE5hbWVbXSBvcHRpb25zLCBib29sZWFuIHRleHQpIHRocm93cyBJT0V4Y2VwdGlvbiB7CgkJcmV0dXJuIHRleHQgPyBmaW5kZXIuZ2V0RGVzY3JpcHRpb25Gb3IoZ2V0UmVhZGVyKGNvbnRlbnRzKSwgZmlsZU5hbWUsIG9wdGlvbnMpCgkJCQk6IGZpbmRlci5nZXREZXNjcmlwdGlvbkZvcihnZXRJbnB1dFN0cmVhbShjb250ZW50cywgZW5jb2RpbmcpLCBmaWxlTmFtZSwgb3B0aW9ucyk7Cgl9CgoJcHVibGljIElucHV0U3RyZWFtIGdldElucHV0U3RyZWFtKGJ5dGVbXVtdIGNvbnRlbnRzKSB7CgkJaW50IHNpemUgPSAwOwoJCS8vIGNvbXB1dGVzIGZpbmFsIGFycmF5IHNpemUKCQlmb3IgKGJ5dGVbXSBjb250ZW50IDogY29udGVudHMpIHsKCQkJc2l6ZSArPSBjb250ZW50Lmxlbmd0aDsKCQl9CgkJYnl0ZVtdIGZ1bGwgPSBuZXcgYnl0ZVtzaXplXTsKCQlpbnQgZnVsbEluZGV4ID0gMDsKCQkvLyBjb25jYXRlbmF0ZXMgYWxsIGJ5dGUgYXJyYXlzCgkJZm9yIChieXRlW10gY29udGVudCA6IGNvbnRlbnRzKSB7CgkJCWZvciAoYnl0ZSBlbGVtZW50IDogY29udGVudCkgewoJCQkJZnVsbFtmdWxsSW5kZXgrK10gPSBlbGVtZW50OwoJCQl9CgkJfQoJCXJldHVybiBuZXcgQnl0ZUFycmF5SW5wdXRTdHJlYW0oZnVsbCk7Cgl9CgoJcHVibGljIElucHV0U3RyZWFtIGdldElucHV0U3RyZWFtKFN0cmluZyBjb250ZW50cykgewoJCXJldHVybiBuZXcgQnl0ZUFycmF5SW5wdXRTdHJlYW0oY29udGVudHMuZ2V0Qnl0ZXMoKSk7Cgl9CgoJcHVibGljIElucHV0U3RyZWFtIGdldElucHV0U3RyZWFtKFN0cmluZyBjb250ZW50cywgQ2hhcnNldCBlbmNvZGluZykgewoJCXJldHVybiBuZXcgQnl0ZUFycmF5SW5wdXRTdHJlYW0oZW5jb2RpbmcgPT0gbnVsbCA/IGNvbnRlbnRzLmdldEJ5dGVzKCkgOiBjb250ZW50cy5nZXRCeXRlcyhlbmNvZGluZykpOwoJfQoKCXB1YmxpYyBSZWFkZXIgZ2V0UmVhZGVyKFN0cmluZyBjb250ZW50cykgewoJCXJldHVybiBuZXcgQ2hhckFycmF5UmVhZGVyKGNvbnRlbnRzLnRvQ2hhckFycmF5KCkpOwoJfQoKCXByaXZhdGUgYm9vbGVhbiBpc1RleHQoSUNvbnRlbnRUeXBlTWFuYWdlciBtYW5hZ2VyLCBJQ29udGVudFR5cGUgY2FuZGlkYXRlKSB7CgkJSUNvbnRlbnRUeXBlIHRleHQgPSBtYW5hZ2VyLmdldENvbnRlbnRUeXBlKElDb250ZW50VHlwZU1hbmFnZXIuQ1RfVEVYVCk7CgkJcmV0dXJuIGNhbmRpZGF0ZS5pc0tpbmRPZih0ZXh0KTsKCX0KCglAQWZ0ZXIKCXB1YmxpYyB2b2lkIHRlYXJEb3duKCkgdGhyb3dzIEV4Y2VwdGlvbiB7CgkJLy8gc29tZSB0ZXN0cyBoZXJlIHdpbGwgdHJpZ2dlciBhIGNoYXJzZXQgZGVsdGEgam9iIChhbnkgY2F1c2luZwoJCS8vIENvbnRlbnRUeXBlQ2hhbmdlRXZlbnRzIHRvIGJlIGJyb2FkY2FzdCkKCQkvLyBlbnN1cmUgbm9uZSBpcyBsZWZ0IHJ1bm5pbmcgYWZ0ZXIgd2UgZmluaXNoCgkJSm9iLmdldEpvYk1hbmFnZXIoKS5qb2luKEZBTUlMWV9DSEFSU0VUX0RFTFRBLCBuZXcgRnVzc3lQcm9ncmVzc01vbml0b3IoKSk7Cgl9CgoJLyoqCgkgKiBUaGlzIHRlc3Qgc2hvd3MgaG93IHdlIGRlYWwgd2l0aCBhbGlhc2VzLgoJICovCglAVGVzdAoJcHVibGljIHZvaWQgdGVzdEFsaWFzKCkgdGhyb3dzIElPRXhjZXB0aW9uIHsKCQlmaW5hbCBJQ29udGVudFR5cGVNYW5hZ2VyIGNvbnRlbnRUeXBlTWFuYWdlciA9IFBsYXRmb3JtLmdldENvbnRlbnRUeXBlTWFuYWdlcigpOwoJCUlDb250ZW50VHlwZSBhbGlhcyA9IGNvbnRlbnRUeXBlTWFuYWdlci5nZXRDb250ZW50VHlwZShQSV9SRVNPVVJDRVNfVEVTVFMgKyAiLmFsaWFzIik7CgkJYXNzZXJ0Tm90TnVsbCgiMC43IiwgYWxpYXMpOwoJCUlDb250ZW50VHlwZSBkZXJpdmVkID0gY29udGVudFR5cGVNYW5hZ2VyLmdldENvbnRlbnRUeXBlKFBJX1JFU09VUkNFU19URVNUUyArICIuZGVyaXZlZC1mcm9tLWFsaWFzIik7CgkJYXNzZXJ0Tm90TnVsbCgiMC44IiwgZGVyaXZlZCk7CgkJSUNvbnRlbnRUeXBlIHRhcmdldCA9IGNvbnRlbnRUeXBlTWFuYWdlci5nZXRDb250ZW50VHlwZSgib3JnLmVjbGlwc2UuYnVuZGxlMDIubWlzc2luZy10YXJnZXQiKTsKCQlhc3NlcnROdWxsKCIwLjkiLCB0YXJnZXQpOwoJCUlDb250ZW50VHlwZVtdIHNlbGVjdGVkOwoJCXNlbGVjdGVkID0gY29udGVudFR5cGVNYW5hZ2VyLmZpbmRDb250ZW50VHlwZXNGb3IoImZvby5taXNzaW5nLXRhcmdldCIpOwoJCWFzc2VydEVxdWFscygiMS4xIiwgMiwgc2VsZWN0ZWQubGVuZ3RoKTsKCQlhc3NlcnRFcXVhbHMoIjEuMiIsIGFsaWFzLCBzZWxlY3RlZFswXSk7CgkJYXNzZXJ0RXF1YWxzKCIxLjMiLCBkZXJpdmVkLCBzZWxlY3RlZFsxXSk7CgkJc2VsZWN0ZWQgPSBjb250ZW50VHlwZU1hbmFnZXIuZmluZENvbnRlbnRUeXBlc0ZvcihnZXRSYW5kb21Db250ZW50cygpLCAiZm9vLm1pc3NpbmctdGFyZ2V0Iik7CgkJYXNzZXJ0RXF1YWxzKCIxLjQiLCAyLCBzZWxlY3RlZC5sZW5ndGgpOwoJCWFzc2VydEVxdWFscygiMS41IiwgYWxpYXMsIHNlbGVjdGVkWzBdKTsKCQlhc3NlcnRFcXVhbHMoIjEuNiIsIGRlcml2ZWQsIHNlbGVjdGVkWzFdKTsKCgkJLy8gdGVzdCBsYXRlIGFkZGl0aW9uIG9mIGNvbnRlbnQgdHlwZQoJCVRlc3RSZWdpc3RyeUNoYW5nZUxpc3RlbmVyIGxpc3RlbmVyID0gbmV3IFRlc3RSZWdpc3RyeUNoYW5nZUxpc3RlbmVyKFBsYXRmb3JtLlBJX1JVTlRJTUUsCgkJCQlDb250ZW50VHlwZUJ1aWxkZXIuUFRfQ09OVEVOVFRZUEVTLCBudWxsLCBudWxsKTsKCQlCdW5kbGVUZXN0aW5nSGVscGVyLnJ1bldpdGhCdW5kbGVzKCIyIiwgKCkgLT4gewoJCQlJQ29udGVudFR5cGUgYWxpYXMxID0gY29udGVudFR5cGVNYW5hZ2VyLmdldENvbnRlbnRUeXBlKFBJX1JFU09VUkNFU19URVNUUyArICIuYWxpYXMiKTsKCQkJYXNzZXJ0TnVsbCgiMi4xLjEiLCBhbGlhczEpOwoJCQlJQ29udGVudFR5cGUgZGVyaXZlZDEgPSBjb250ZW50VHlwZU1hbmFnZXIuZ2V0Q29udGVudFR5cGUoUElfUkVTT1VSQ0VTX1RFU1RTICsgIi5kZXJpdmVkLWZyb20tYWxpYXMiKTsKCQkJYXNzZXJ0Tm90TnVsbCgiMi4xLjIiLCBkZXJpdmVkMSk7CgkJCUlDb250ZW50VHlwZSB0YXJnZXQxID0gY29udGVudFR5cGVNYW5hZ2VyLmdldENvbnRlbnRUeXBlKCJvcmcuZWNsaXBzZS5idW5kbGUwMi5taXNzaW5nLXRhcmdldCIpOwoJCQlhc3NlcnROb3ROdWxsKCIyLjEuMyIsIHRhcmdldDEpOwoJCQkvLyBjaGVja3MgYXNzb2NpYXRpb25zCgkJCUlDb250ZW50VHlwZVtdIHNlbGVjdGVkMSA9IGNvbnRlbnRUeXBlTWFuYWdlci5maW5kQ29udGVudFR5cGVzRm9yKCJmb28ubWlzc2luZy10YXJnZXQiKTsKCQkJYXNzZXJ0RXF1YWxzKCIyLjIuMSIsIDIsIHNlbGVjdGVkMS5sZW5ndGgpOwoJCQlhc3NlcnRFcXVhbHMoIjIuMi4yIiwgdGFyZ2V0MSwgc2VsZWN0ZWQxWzBdKTsKCQkJYXNzZXJ0RXF1YWxzKCIyLjIuMyIsIGRlcml2ZWQxLCBzZWxlY3RlZDFbMV0pOwoJCQlJQ29udGVudFR5cGVbXSBzZWxlY3RlZDI7CgkJCXRyeSB7CgkJCQlzZWxlY3RlZDIgPSBjb250ZW50VHlwZU1hbmFnZXIuZmluZENvbnRlbnRUeXBlc0ZvcihnZXRSYW5kb21Db250ZW50cygpLCAiZm9vLm1pc3NpbmctdGFyZ2V0Iik7CgkJCX0gY2F0Y2ggKElPRXhjZXB0aW9uIGUpIHsKCQkJCXRocm93IG5ldyBBc3NlcnRpb25FcnJvcihlKTsKCQkJfQoJCQlhc3NlcnRFcXVhbHMoIjIuMi41IiwgMiwgc2VsZWN0ZWQyLmxlbmd0aCk7CgkJCWFzc2VydEVxdWFscygiMi4yLjYiLCB0YXJnZXQxLCBzZWxlY3RlZDJbMF0pOwoJCQlhc3NlcnRFcXVhbHMoIjIuMi43IiwgZGVyaXZlZDEsIHNlbGVjdGVkMlsxXSk7CgkJfSwgZ2V0Q29udGV4dCgpLCBuZXcgU3RyaW5nW10geyBDb250ZW50VHlwZVRlc3QuVEVTVF9GSUxFU19ST09UICsgImNvbnRlbnQvYnVuZGxlMDIiIH0sIGxpc3RlbmVyKTsKCX0KCglAVGVzdAoJcHVibGljIHZvaWQgdGVzdEFzc29jaWF0aW9uSW5oZXJpdGFuY2UoKSB0aHJvd3MgQ29yZUV4Y2VwdGlvbiB7CgkJSUNvbnRlbnRUeXBlTWFuYWdlciBtYW5hZ2VyID0gUGxhdGZvcm0uZ2V0Q29udGVudFR5cGVNYW5hZ2VyKCk7CgkJSUNvbnRlbnRUeXBlTWF0Y2hlciBmaW5kZXIgPSBtYW5hZ2VyLmdldE1hdGNoZXIobmV3IExvY2FsU2VsZWN0aW9uUG9saWN5KCksIG51bGwpOwoJCUlDb250ZW50VHlwZSB0ZXh0ID0gbWFuYWdlci5nZXRDb250ZW50VHlwZShQbGF0Zm9ybS5QSV9SVU5USU1FICsgIi50ZXh0Iik7CgkJSUNvbnRlbnRUeXBlIGFzc29jMSA9IG1hbmFnZXIuZ2V0Q29udGVudFR5cGUoUElfUkVTT1VSQ0VTX1RFU1RTICsgIi5hc3NvYzEiKTsKCQlJQ29udGVudFR5cGUgYXNzb2MyID0gbWFuYWdlci5nZXRDb250ZW50VHlwZShQSV9SRVNPVVJDRVNfVEVTVFMgKyAiLmFzc29jMiIpOwoKCQkvLyBhc3NvY2lhdGUgYSB1c2VyLWRlZmluZWQgZmlsZSBzcGVjCgkJdGV4dC5hZGRGaWxlU3BlYygidHh0X3VzZXJhZGRlZCIsIElDb250ZW50VHlwZS5GSUxFX0VYVEVOU0lPTl9TUEVDKTsKCQlhc3NvYzEuYWRkRmlsZVNwZWMoInR4dF9hc3NvYzF1c2VyYWRkZWQiLCBJQ29udGVudFR5cGUuRklMRV9FWFRFTlNJT05fU1BFQyk7CgkJYXNzb2MyLmFkZEZpbGVTcGVjKCJ0eHRfYXNzb2MydXNlcmFkZGVkIiwgSUNvbnRlbnRUeXBlLkZJTEVfRVhURU5TSU9OX1NQRUMpOwoKCQkvLyB0ZXN0IGFzc29jaWF0aW9ucwoJCWFzc2VydFRydWUoIjEuMSIsIGFzc29jMS5pc0Fzc29jaWF0ZWRXaXRoKGNoYW5nZUNhc2UoInRleHQudHh0IikpKTsKCQlhc3NlcnRUcnVlKCIxLjIiLCBhc3NvYzEuaXNBc3NvY2lhdGVkV2l0aChjaGFuZ2VDYXNlKCJ0ZXh0LnR4dF91c2VyYWRkZWQiKSkpOwoJCWFzc2VydFRydWUoIjEuMyIsIGFzc29jMS5pc0Fzc29jaWF0ZWRXaXRoKGNoYW5nZUNhc2UoInRleHQudHh0X3BsdWdpbmFkZGVkIikpKTsKCQlhc3NlcnRUcnVlKCIxLjQiLCBhc3NvYzEuaXNBc3NvY2lhdGVkV2l0aChjaGFuZ2VDYXNlKCJ0ZXh0LnR4dF9hc3NvYzFwbHVnaW5hZGRlZCIpKSk7CgkJYXNzZXJ0VHJ1ZSgiMS41IiwgYXNzb2MxLmlzQXNzb2NpYXRlZFdpdGgoY2hhbmdlQ2FzZSgidGV4dC50eHRfYXNzb2MxdXNlcmFkZGVkIikpKTsKCgkJYXNzZXJ0RmFsc2UoIjIuMSIsIGFzc29jMi5pc0Fzc29jaWF0ZWRXaXRoKGNoYW5nZUNhc2UoInRleHQudHh0IikpKTsKCQlhc3NlcnRGYWxzZSgiMi4yIiwgYXNzb2MyLmlzQXNzb2NpYXRlZFdpdGgoY2hhbmdlQ2FzZSgidGV4dC50eHRfdXNlcmFkZGVkIikpKTsKCQlhc3NlcnRGYWxzZSgiMi4zIiwgYXNzb2MyLmlzQXNzb2NpYXRlZFdpdGgoY2hhbmdlQ2FzZSgidGV4dC50eHRfcGx1Z2luYWRkZWQiKSkpOwoJCWFzc2VydFRydWUoIjIuNCIsIGFzc29jMi5pc0Fzc29jaWF0ZWRXaXRoKGNoYW5nZUNhc2UoInRleHQudHh0X2Fzc29jMnBsdWdpbmFkZGVkIikpKTsKCQlhc3NlcnRUcnVlKCIyLjUiLCBhc3NvYzIuaXNBc3NvY2lhdGVkV2l0aChjaGFuZ2VDYXNlKCJ0ZXh0LnR4dF9hc3NvYzJidWlsdGluIikpKTsKCQlhc3NlcnRUcnVlKCIyLjYiLCBhc3NvYzIuaXNBc3NvY2lhdGVkV2l0aChjaGFuZ2VDYXNlKCJ0ZXh0LnR4dF9hc3NvYzJ1c2VyYWRkZWQiKSkpOwoKCQlJQ29udGVudFR5cGVbXSBzZWxlY3RlZDsKCQkvLyB0ZXh0IGJ1aWx0LWluIGFzc29jaWF0aW9ucwoJCXNlbGVjdGVkID0gZmluZGVyLmZpbmRDb250ZW50VHlwZXNGb3IoY2hhbmdlQ2FzZSgidGV4dC50eHQiKSk7CgkJYXNzZXJ0RXF1YWxzKCIzLjAiLCAyLCBzZWxlY3RlZC5sZW5ndGgpOwoJCWFzc2VydEVxdWFscygiMy4xIiwgYXNzb2MxLCBzZWxlY3RlZFsxXSk7CgkJYXNzZXJ0RXF1YWxzKCIzLjIiLCB0ZXh0LCBzZWxlY3RlZFswXSk7CgoJCS8vIHRleHQgdXNlci1hZGRlZCBhc3NvY2lhdGlvbnMKCQlzZWxlY3RlZCA9IGZpbmRlci5maW5kQ29udGVudFR5cGVzRm9yKGNoYW5nZUNhc2UoInRleHQudHh0X3VzZXJhZGRlZCIpKTsKCQlhc3NlcnRFcXVhbHMoIjQuMCIsIDIsIHNlbGVjdGVkLmxlbmd0aCk7CgkJYXNzZXJ0RXF1YWxzKCI0LjEiLCBhc3NvYzEsIHNlbGVjdGVkWzFdKTsKCQlhc3NlcnRFcXVhbHMoIjQuMiIsIHRleHQsIHNlbGVjdGVkWzBdKTsKCgkJLy8gdGV4dCBwcm92aWRlci1hZGRlZCBhc3NvY2lhdGlvbnMKCQlzZWxlY3RlZCA9IGZpbmRlci5maW5kQ29udGVudFR5cGVzRm9yKGNoYW5nZUNhc2UoInRleHQudHh0X3BsdWdpbmFkZGVkIikpOwoJCWFzc2VydEVxdWFscygiNS4wIiwgMiwgc2VsZWN0ZWQubGVuZ3RoKTsKCQlhc3NlcnRFcXVhbHMoIjUuMSIsIGFzc29jMSwgc2VsZWN0ZWRbMV0pOwoJCWFzc2VydEVxdWFscygiNS4yIiwgdGV4dCwgc2VsZWN0ZWRbMF0pOwoKCQlzZWxlY3RlZCA9IGZpbmRlci5maW5kQ29udGVudFR5cGVzRm9yKGNoYW5nZUNhc2UoInRleHQudHh0X2Fzc29jMXBsdWdpbmFkZGVkIikpOwoJCWFzc2VydEVxdWFscygiNi4wIiwgMSwgc2VsZWN0ZWQubGVuZ3RoKTsKCQlhc3NlcnRFcXVhbHMoIjYuMSIsIGFzc29jMSwgc2VsZWN0ZWRbMF0pOwoKCQlzZWxlY3RlZCA9IGZpbmRlci5maW5kQ29udGVudFR5cGVzRm9yKGNoYW5nZUNhc2UoInRleHQudHh0X2Fzc29jMXVzZXJhZGRlZCIpKTsKCQlhc3NlcnRFcXVhbHMoIjcuMCIsIDEsIHNlbGVjdGVkLmxlbmd0aCk7CgkJYXNzZXJ0RXF1YWxzKCI3LjEiLCBhc3NvYzEsIHNlbGVjdGVkWzBdKTsKCgkJc2VsZWN0ZWQgPSBmaW5kZXIuZmluZENvbnRlbnRUeXBlc0ZvcihjaGFuZ2VDYXNlKCJ0ZXh0LnR4dF9hc3NvYzJwbHVnaW5hZGRlZCIpKTsKCQlhc3NlcnRFcXVhbHMoIjguMCIsIDEsIHNlbGVjdGVkLmxlbmd0aCk7CgkJYXNzZXJ0RXF1YWxzKCI4LjEiLCBhc3NvYzIsIHNlbGVjdGVkWzBdKTsKCgkJc2VsZWN0ZWQgPSBmaW5kZXIuZmluZENvbnRlbnRUeXBlc0ZvcihjaGFuZ2VDYXNlKCJ0ZXh0LnR4dF9hc3NvYzJ1c2VyYWRkZWQiKSk7CgkJYXNzZXJ0RXF1YWxzKCI5LjAiLCAxLCBzZWxlY3RlZC5sZW5ndGgpOwoJCWFzc2VydEVxdWFscygiOS4xIiwgYXNzb2MyLCBzZWxlY3RlZFswXSk7CgoJCXNlbGVjdGVkID0gZmluZGVyLmZpbmRDb250ZW50VHlwZXNGb3IoY2hhbmdlQ2FzZSgidGV4dC50eHRfYXNzb2MyYnVpbHRpbiIpKTsKCQlhc3NlcnRFcXVhbHMoIjEwLjAiLCAxLCBzZWxlY3RlZC5sZW5ndGgpOwoJCWFzc2VydEVxdWFscygiMTAuMSIsIGFzc29jMiwgc2VsZWN0ZWRbMF0pOwoJfQoKCUBUZXN0CglwdWJsaWMgdm9pZCB0ZXN0QXNzb2NpYXRpb25zKCkgdGhyb3dzIENvcmVFeGNlcHRpb24gewoJCUlDb250ZW50VHlwZSB0ZXh0ID0gUGxhdGZvcm0uZ2V0Q29udGVudFR5cGVNYW5hZ2VyKCkuZ2V0Q29udGVudFR5cGUoUGxhdGZvcm0uUElfUlVOVElNRSArICIudGV4dCIpOwoKCQkvLyBhc3NvY2lhdGUgYSB1c2VyLWRlZmluZWQgZmlsZSBzcGVjCgkJdGV4dC5hZGRGaWxlU3BlYygidHh0X3VzZXJhZGRlZCIsIElDb250ZW50VHlwZS5GSUxFX0VYVEVOU0lPTl9TUEVDKTsKCgkJLy8gdGVzdCBhc3NvY2lhdGlvbnMKCQlhc3NlcnRUcnVlKCIwLjEiLCB0ZXh0LmlzQXNzb2NpYXRlZFdpdGgoY2hhbmdlQ2FzZSgidGV4dC50eHQiKSkpOwoJCWFzc2VydFRydWUoIjAuMiIsIHRleHQuaXNBc3NvY2lhdGVkV2l0aChjaGFuZ2VDYXNlKCJ0ZXh0LnR4dF91c2VyYWRkZWQiKSkpOwoJCWFzc2VydFRydWUoIjAuMyIsIHRleHQuaXNBc3NvY2lhdGVkV2l0aChjaGFuZ2VDYXNlKCJ0ZXh0LnR4dF9wbHVnaW5hZGRlZCIpKSk7CgoJCS8vIGNoZWNrIHByb3ZpZGVyIGRlZmluZWQgc2V0dGluZ3MKCQlTdHJpbmdbXSBwcm92aWRlckRlZmluZWRFeHRlbnNpb25zID0gdGV4dAoJCQkJLmdldEZpbGVTcGVjcyhJQ29udGVudFR5cGUuRklMRV9FWFRFTlNJT05fU1BFQyB8IElDb250ZW50VHlwZS5JR05PUkVfVVNFUl9ERUZJTkVEKTsKCQlhc3NlcnRUcnVlKCIxLjAiLCBjb250YWlucyhwcm92aWRlckRlZmluZWRFeHRlbnNpb25zLCAidHh0IikpOwoJCWFzc2VydEZhbHNlKCIxLjEiLCBjb250YWlucyhwcm92aWRlckRlZmluZWRFeHRlbnNpb25zLCAidHh0X3VzZXJhZGRlZCIpKTsKCQlhc3NlcnRUcnVlKCIxLjIiLCBjb250YWlucyhwcm92aWRlckRlZmluZWRFeHRlbnNpb25zLCAidHh0X3BsdWdpbmFkZGVkIikpOwoKCQkvLyBjaGVjayB1c2VyIGRlZmluZWQgc2V0dGluZ3MKCQlTdHJpbmdbXSB0ZXh0VXNlckRlZmluZWRFeHRlbnNpb25zID0gdGV4dAoJCQkJLmdldEZpbGVTcGVjcyhJQ29udGVudFR5cGUuRklMRV9FWFRFTlNJT05fU1BFQyB8IElDb250ZW50VHlwZS5JR05PUkVfUFJFX0RFRklORUQpOwoJCWFzc2VydEZhbHNlKCIyLjAiLCBjb250YWlucyh0ZXh0VXNlckRlZmluZWRFeHRlbnNpb25zLCAidHh0IikpOwoJCWFzc2VydFRydWUoIjIuMSIsIGNvbnRhaW5zKHRleHRVc2VyRGVmaW5lZEV4dGVuc2lvbnMsICJ0eHRfdXNlcmFkZGVkIikpOwoJCWFzc2VydEZhbHNlKCIyLjIiLCBjb250YWlucyh0ZXh0VXNlckRlZmluZWRFeHRlbnNpb25zLCAidHh0X3BsdWdpbmFkZGVkIikpOwoKCQkvLyByZW1vdmluZyBwcmUtZGVmaW5lZCBmaWxlIHNwZWNzIHNob3VsZCBub3QgZG8gYW55dGhpbmcKCQl0ZXh0LnJlbW92ZUZpbGVTcGVjKCJ0eHQiLCBJQ29udGVudFR5cGUuRklMRV9FWFRFTlNJT05fU1BFQyk7CgkJYXNzZXJ0VHJ1ZSgiMy4wIiwgY29udGFpbnMoCgkJCQl0ZXh0LmdldEZpbGVTcGVjcyhJQ29udGVudFR5cGUuRklMRV9FWFRFTlNJT05fU1BFQyB8IElDb250ZW50VHlwZS5JR05PUkVfVVNFUl9ERUZJTkVEKSwgInR4dCIpKTsKCQlhc3NlcnRUcnVlKCIzLjEiLCB0ZXh0LmlzQXNzb2NpYXRlZFdpdGgoY2hhbmdlQ2FzZSgidGV4dC50eHQiKSkpOwoJCWFzc2VydFRydWUoIjMuMiIsIHRleHQuaXNBc3NvY2lhdGVkV2l0aChjaGFuZ2VDYXNlKCJ0ZXh0LnR4dF91c2VyYWRkZWQiKSkpOwoJCWFzc2VydFRydWUoIjMuMyIsIHRleHQuaXNBc3NvY2lhdGVkV2l0aChjaGFuZ2VDYXNlKCJ0ZXh0LnR4dF9wbHVnaW5hZGRlZCIpKSk7CgoJCS8vIHJlbW92aW5nIHVzZXIgZmlsZSBzcGVjcyBpcyB0aGUgbm9ybWFsIGNhc2UgYW5kIGhhcyB0byB3b3JrIGFzIGV4cGVjdGVkCgkJdGV4dC5yZW1vdmVGaWxlU3BlYygidHh0X3VzZXJhZGRlZCIsIElDb250ZW50VHlwZS5GSUxFX0VYVEVOU0lPTl9TUEVDKTsKCQlhc3NlcnRGYWxzZSgiNC4wIiwKCQkJCWNvbnRhaW5zKHRleHQuZ2V0RmlsZVNwZWNzKElDb250ZW50VHlwZS5GSUxFX0VYVEVOU0lPTl9TUEVDIHwgSUNvbnRlbnRUeXBlLklHTk9SRV9QUkVfREVGSU5FRCksICJpbmkiKSk7CgkJYXNzZXJ0VHJ1ZSgiNC4xIiwgdGV4dC5pc0Fzc29jaWF0ZWRXaXRoKGNoYW5nZUNhc2UoInRleHQudHh0IikpKTsKCQlhc3NlcnRGYWxzZSgiNC4yIiwgdGV4dC5pc0Fzc29jaWF0ZWRXaXRoKGNoYW5nZUNhc2UoInRleHQudHh0X3VzZXJhZGRlZCIpKSk7CgkJYXNzZXJ0VHJ1ZSgiNC4zIiwgdGV4dC5pc0Fzc29jaWF0ZWRXaXRoKGNoYW5nZUNhc2UoInRleHQudHh0X3BsdWdpbmFkZGVkIikpKTsKCX0KCglAVGVzdAoJcHVibGljIHZvaWQgdGVzdEJpbmFyeVR5cGVzKCkgdGhyb3dzIElPRXhjZXB0aW9uIHsKCQlJQ29udGVudFR5cGVNYW5hZ2VyIGNvbnRlbnRUeXBlTWFuYWdlciA9IFBsYXRmb3JtLmdldENvbnRlbnRUeXBlTWFuYWdlcigpOwoJCUlDb250ZW50VHlwZSBzYW1wbGVCaW5hcnkxID0gY29udGVudFR5cGVNYW5hZ2VyLmdldENvbnRlbnRUeXBlKFBJX1JFU09VUkNFU19URVNUUyArICIuc2FtcGxlLWJpbmFyeTEiKTsKCQlJQ29udGVudFR5cGUgc2FtcGxlQmluYXJ5MiA9IGNvbnRlbnRUeXBlTWFuYWdlci5nZXRDb250ZW50VHlwZShQSV9SRVNPVVJDRVNfVEVTVFMgKyAiLnNhbXBsZS1iaW5hcnkyIik7CgkJSW5wdXRTdHJlYW0gY29udGVudHM7CgoJCWNvbnRlbnRzID0gZ2V0SW5wdXRTdHJlYW0oCgkJCQluZXcgYnl0ZVtdW10geyBTQU1QTEVfQklOMV9PRkZTRVQuZ2V0Qnl0ZXMoKSwgU0FNUExFX0JJTjFfU0lHTkFUVVJFLCAiIGV4dHJhIGNvbnRlbnRzIi5nZXRCeXRlcygpIH0pOwoJCUlDb250ZW50RGVzY3JpcHRpb24gZGVzY3JpcHRpb24gPSBjb250ZW50VHlwZU1hbmFnZXIuZ2V0RGVzY3JpcHRpb25Gb3IoY29udGVudHMsIG51bGwsIElDb250ZW50RGVzY3JpcHRpb24uQUxMKTsKCQlhc3NlcnROb3ROdWxsKCI2LjAiLCBkZXNjcmlwdGlvbik7CgkJYXNzZXJ0RXF1YWxzKCI2LjEiLCBzYW1wbGVCaW5hcnkxLCBkZXNjcmlwdGlvbi5nZXRDb250ZW50VHlwZSgpKTsKCgkJY29udGVudHMgPSBnZXRJbnB1dFN0cmVhbSgKCQkJCW5ldyBieXRlW11bXSB7IFNBTVBMRV9CSU4yX09GRlNFVC5nZXRCeXRlcygpLCBTQU1QTEVfQklOMl9TSUdOQVRVUkUsICIgZXh0cmEgY29udGVudHMiLmdldEJ5dGVzKCkgfSk7CgkJZGVzY3JpcHRpb24gPSBjb250ZW50VHlwZU1hbmFnZXIuZ2V0RGVzY3JpcHRpb25Gb3IoY29udGVudHMsIG51bGwsIElDb250ZW50RGVzY3JpcHRpb24uQUxMKTsKCQlhc3NlcnROb3ROdWxsKCI3LjAiLCBkZXNjcmlwdGlvbik7CgkJYXNzZXJ0RXF1YWxzKCI3LjEiLCBzYW1wbGVCaW5hcnkyLCBkZXNjcmlwdGlvbi5nZXRDb250ZW50VHlwZSgpKTsKCgkJLy8gbWFrZSBzdXJlIHdlIGlnbm9yZSB0aGF0IGNvbnRlbnQgdHlwZSB3aGVuIGNvbnRlbnRzIGFyZSB0ZXh0CgkJLy8gKHNlZSBidWcgMTAwMDMyKQoJCS8vIGZpcnN0IGNoZWNrIGlmIG91ciB0ZXN0IGVudmlyb25tZW50IGlzIHNhbmUKCQlJQ29udGVudFR5cGVbXSBzZWxlY3RlZCA9IGNvbnRlbnRUeXBlTWFuYWdlci5maW5kQ29udGVudFR5cGVzRm9yKCJ0ZXN0LnNhbXBsZWJpbjIiKTsKCQlhc3NlcnRFcXVhbHMoIjguMSIsIDEsIHNlbGVjdGVkLmxlbmd0aCk7CgkJYXNzZXJ0RXF1YWxzKCI4LjIiLCBzYW1wbGVCaW5hcnkyLmdldElkKCksIHNlbGVjdGVkWzBdLmdldElkKCkpOwoJCS8vICh3ZSB1c2VkIHRvIGJsb3cgdXAgaGVyZSkKCQlkZXNjcmlwdGlvbiA9IGNvbnRlbnRUeXBlTWFuYWdlci5nZXREZXNjcmlwdGlvbkZvcihnZXRSZWFkZXIoZ2V0UmFuZG9tU3RyaW5nKCkpLCAidGVzdC5zYW1wbGViaW4yIiwKCQkJCUlDb250ZW50RGVzY3JpcHRpb24uQUxMKTsKCQlhc3NlcnROdWxsKCI4LjMiLCBkZXNjcmlwdGlvbik7Cgl9CgoJQFRlc3QKCXB1YmxpYyB2b2lkIHRlc3RCeXRlT3JkZXJNYXJrKCkgdGhyb3dzIElPRXhjZXB0aW9uIHsKCQlJQ29udGVudFR5cGUgdGV4dCA9IFBsYXRmb3JtLmdldENvbnRlbnRUeXBlTWFuYWdlcigpLmdldENvbnRlbnRUeXBlKElDb250ZW50VHlwZU1hbmFnZXIuQ1RfVEVYVCk7CgkJUXVhbGlmaWVkTmFtZVtdIG9wdGlvbnMgPSBuZXcgUXVhbGlmaWVkTmFtZVtdIHsgSUNvbnRlbnREZXNjcmlwdGlvbi5CWVRFX09SREVSX01BUksgfTsKCQlJQ29udGVudERlc2NyaXB0aW9uIGRlc2NyaXB0aW9uOwoJCS8vIHRlc3RzIHdpdGggVVRGLTggQk9NCgkJU3RyaW5nIFVURjhfQk9NID0gbmV3IFN0cmluZyhJQ29udGVudERlc2NyaXB0aW9uLkJPTV9VVEZfOCwgU3RhbmRhcmRDaGFyc2V0cy5JU09fODg1OV8xKTsKCQlkZXNjcmlwdGlvbiA9IHRleHQuZ2V0RGVzY3JpcHRpb25Gb3IoCgkJCQluZXcgQnl0ZUFycmF5SW5wdXRTdHJlYW0oKFVURjhfQk9NICsgTUlOSU1BTF9YTUwpLmdldEJ5dGVzKFN0YW5kYXJkQ2hhcnNldHMuSVNPXzg4NTlfMSkpLCBvcHRpb25zKTsKCQlhc3NlcnROb3ROdWxsKCIxLjAiLCBkZXNjcmlwdGlvbi5nZXRQcm9wZXJ0eShJQ29udGVudERlc2NyaXB0aW9uLkJZVEVfT1JERVJfTUFSSykpOwoJCWFzc2VydEVxdWFscygiMS4xIiwgSUNvbnRlbnREZXNjcmlwdGlvbi5CT01fVVRGXzgsCgkJCQlkZXNjcmlwdGlvbi5nZXRQcm9wZXJ0eShJQ29udGVudERlc2NyaXB0aW9uLkJZVEVfT1JERVJfTUFSSykpOwoJCS8vIHRlc3RzIHdpdGggVVRGLTE2IExpdHRsZSBFbmRpYW4gQk9NCgkJU3RyaW5nIFVURjE2X0xFX0JPTSA9IG5ldyBTdHJpbmcoSUNvbnRlbnREZXNjcmlwdGlvbi5CT01fVVRGXzE2TEUsIFN0YW5kYXJkQ2hhcnNldHMuSVNPXzg4NTlfMSk7CgkJZGVzY3JpcHRpb24gPSB0ZXh0LmdldERlc2NyaXB0aW9uRm9yKAoJCQkJbmV3IEJ5dGVBcnJheUlucHV0U3RyZWFtKChVVEYxNl9MRV9CT00gKyBNSU5JTUFMX1hNTCkuZ2V0Qnl0ZXMoU3RhbmRhcmRDaGFyc2V0cy5JU09fODg1OV8xKSksIG9wdGlvbnMpOwoJCWFzc2VydE5vdE51bGwoIjIuMCIsIGRlc2NyaXB0aW9uLmdldFByb3BlcnR5KElDb250ZW50RGVzY3JpcHRpb24uQllURV9PUkRFUl9NQVJLKSk7CgkJYXNzZXJ0RXF1YWxzKCIyLjEiLCBJQ29udGVudERlc2NyaXB0aW9uLkJPTV9VVEZfMTZMRSwKCQkJCWRlc2NyaXB0aW9uLmdldFByb3BlcnR5KElDb250ZW50RGVzY3JpcHRpb24uQllURV9PUkRFUl9NQVJLKSk7CgkJLy8gdGVzdHMgd2l0aCBVVEYtMTYgQmlnIEVuZGlhbiBCT00KCQlTdHJpbmcgVVRGMTZfQkVfQk9NID0gbmV3IFN0cmluZyhJQ29udGVudERlc2NyaXB0aW9uLkJPTV9VVEZfMTZCRSwgU3RhbmRhcmRDaGFyc2V0cy5JU09fODg1OV8xKTsKCQlkZXNjcmlwdGlvbiA9IHRleHQuZ2V0RGVzY3JpcHRpb25Gb3IoCgkJCQluZXcgQnl0ZUFycmF5SW5wdXRTdHJlYW0oKFVURjE2X0JFX0JPTSArIE1JTklNQUxfWE1MKS5nZXRCeXRlcyhTdGFuZGFyZENoYXJzZXRzLklTT184ODU5XzEpKSwgb3B0aW9ucyk7CgkJYXNzZXJ0Tm90TnVsbCgiMy4wIiwgZGVzY3JpcHRpb24uZ2V0UHJvcGVydHkoSUNvbnRlbnREZXNjcmlwdGlvbi5CWVRFX09SREVSX01BUkspKTsKCQlhc3NlcnRFcXVhbHMoIjMuMSIsIElDb250ZW50RGVzY3JpcHRpb24uQk9NX1VURl8xNkJFLAoJCQkJZGVzY3JpcHRpb24uZ2V0UHJvcGVydHkoSUNvbnRlbnREZXNjcmlwdGlvbi5CWVRFX09SREVSX01BUkspKTsKCQkvLyB0ZXN0IHdpdGggbm8gQk9NCgkJZGVzY3JpcHRpb24gPSB0ZXh0LmdldERlc2NyaXB0aW9uRm9yKAoJCQkJbmV3IEJ5dGVBcnJheUlucHV0U3RyZWFtKE1JTklNQUxfWE1MLmdldEJ5dGVzKFN0YW5kYXJkQ2hhcnNldHMuSVNPXzg4NTlfMSkpLCBvcHRpb25zKTsKCQlhc3NlcnROdWxsKCI0LjAiLCBkZXNjcmlwdGlvbi5nZXRQcm9wZXJ0eShJQ29udGVudERlc2NyaXB0aW9uLkJZVEVfT1JERVJfTUFSSykpOwoKCQkvLyB0ZXN0cyBmb3IgcGFydGlhbCBCT00KCQkvLyBmaXJzdCBieXRlIG9mIFVURi0xNiBCaWcgRW5kaWFuICsgbWluaW1hbCB4bWwKCQlTdHJpbmcgVVRGMTZfQkVfQk9NXzFieXRlID0gbmV3IFN0cmluZyhuZXcgYnl0ZVtdIHsgKGJ5dGUpIDB4RkUgfSwgIklTTy04ODU5LTEiKTsKCQlkZXNjcmlwdGlvbiA9IHRleHQuZ2V0RGVzY3JpcHRpb25Gb3IoCgkJCQluZXcgQnl0ZUFycmF5SW5wdXRTdHJlYW0oKFVURjE2X0JFX0JPTV8xYnl0ZSArIE1JTklNQUxfWE1MKS5nZXRCeXRlcyhTdGFuZGFyZENoYXJzZXRzLklTT184ODU5XzEpKSwKCQkJCW9wdGlvbnMpOwoJCWFzc2VydE51bGwoIjUuMCIsIGRlc2NyaXB0aW9uLmdldFByb3BlcnR5KElDb250ZW50RGVzY3JpcHRpb24uQllURV9PUkRFUl9NQVJLKSk7CgkJLy8gZmlyc3QgYnl0ZSBvZiBVVEYtMTYgQmlnIEVuZGlhbiBvbmx5IChzZWUKCQkvLyBodHRwczovL2J1Z3MuZWNsaXBzZS5vcmcvYnVncy9zaG93X2J1Zy5jZ2k/aWQ9MTk5MjUyKQoJCWRlc2NyaXB0aW9uID0gdGV4dC5nZXREZXNjcmlwdGlvbkZvcigKCQkJCW5ldyBCeXRlQXJyYXlJbnB1dFN0cmVhbSgoVVRGMTZfQkVfQk9NXzFieXRlKS5nZXRCeXRlcyhTdGFuZGFyZENoYXJzZXRzLklTT184ODU5XzEpKSwgb3B0aW9ucyk7CgkJYXNzZXJ0TnVsbCgiNS4xIiwgZGVzY3JpcHRpb24uZ2V0UHJvcGVydHkoSUNvbnRlbnREZXNjcmlwdGlvbi5CWVRFX09SREVSX01BUkspKTsKCgkJLy8gZmlyc3QgYnl0ZSBvZiBVVEYtMTYgTGl0dGxlIEVuZGlhbiArIG1pbmltYWwgeG1sCgkJU3RyaW5nIFVURjE2X0xFX0JPTV8xYnl0ZSA9IG5ldyBTdHJpbmcobmV3IGJ5dGVbXSB7IChieXRlKSAweEZGIH0sIFN0YW5kYXJkQ2hhcnNldHMuSVNPXzg4NTlfMSk7CgkJZGVzY3JpcHRpb24gPSB0ZXh0LmdldERlc2NyaXB0aW9uRm9yKAoJCQkJbmV3IEJ5dGVBcnJheUlucHV0U3RyZWFtKChVVEYxNl9MRV9CT01fMWJ5dGUgKyBNSU5JTUFMX1hNTCkuZ2V0Qnl0ZXMoU3RhbmRhcmRDaGFyc2V0cy5JU09fODg1OV8xKSksCgkJCQlvcHRpb25zKTsKCQlhc3NlcnROdWxsKCI2LjAiLCBkZXNjcmlwdGlvbi5nZXRQcm9wZXJ0eShJQ29udGVudERlc2NyaXB0aW9uLkJZVEVfT1JERVJfTUFSSykpOwoJCS8vIGZpcnN0IGJ5dGUgb2YgVVRGLTE2IExpdHRsZSBFbmRpYW4gb25seQoJCWRlc2NyaXB0aW9uID0gdGV4dC5nZXREZXNjcmlwdGlvbkZvcigKCQkJCW5ldyBCeXRlQXJyYXlJbnB1dFN0cmVhbSgoVVRGMTZfTEVfQk9NXzFieXRlKS5nZXRCeXRlcyhTdGFuZGFyZENoYXJzZXRzLklTT184ODU5XzEpKSwgb3B0aW9ucyk7CgkJYXNzZXJ0TnVsbCgiNi4xIiwgZGVzY3JpcHRpb24uZ2V0UHJvcGVydHkoSUNvbnRlbnREZXNjcmlwdGlvbi5CWVRFX09SREVSX01BUkspKTsKCgkJLy8gZmlyc3QgYnl0ZSBvZiBVVEYtOCArIG1pbmltYWwgeG1sCgkJU3RyaW5nIFVURjhfQk9NXzFieXRlID0gbmV3IFN0cmluZyhuZXcgYnl0ZVtdIHsgKGJ5dGUpIDB4RUYgfSwgU3RhbmRhcmRDaGFyc2V0cy5JU09fODg1OV8xKTsKCQlkZXNjcmlwdGlvbiA9IHRleHQuZ2V0RGVzY3JpcHRpb25Gb3IoCgkJCQluZXcgQnl0ZUFycmF5SW5wdXRTdHJlYW0oKFVURjhfQk9NXzFieXRlICsgTUlOSU1BTF9YTUwpLmdldEJ5dGVzKFN0YW5kYXJkQ2hhcnNldHMuSVNPXzg4NTlfMSkpLAoJCQkJb3B0aW9ucyk7CgkJYXNzZXJ0TnVsbCgiNy4wIiwgZGVzY3JpcHRpb24uZ2V0UHJvcGVydHkoSUNvbnRlbnREZXNjcmlwdGlvbi5CWVRFX09SREVSX01BUkspKTsKCQkvLyBmaXJzdCBieXRlIG9mIFVURi04IG9ubHkKCQlkZXNjcmlwdGlvbiA9IHRleHQuZ2V0RGVzY3JpcHRpb25Gb3IoCgkJCQluZXcgQnl0ZUFycmF5SW5wdXRTdHJlYW0oKFVURjhfQk9NXzFieXRlKS5nZXRCeXRlcyhTdGFuZGFyZENoYXJzZXRzLklTT184ODU5XzEpKSwgb3B0aW9ucyk7CgkJYXNzZXJ0TnVsbCgiNy4xIiwgZGVzY3JpcHRpb24uZ2V0UHJvcGVydHkoSUNvbnRlbnREZXNjcmlwdGlvbi5CWVRFX09SREVSX01BUkspKTsKCgkJLy8gdHdvIGZpcnN0IGJ5dGVzIG9mIFVURi04ICsgbWluaW1hbCB4bWwKCQlTdHJpbmcgVVRGOF9CT01fMmJ5dGVzID0gbmV3IFN0cmluZyhuZXcgYnl0ZVtdIHsgKGJ5dGUpIDB4RUYsIChieXRlKSAweEJCIH0sIFN0YW5kYXJkQ2hhcnNldHMuSVNPXzg4NTlfMSk7CgkJZGVzY3JpcHRpb24gPSB0ZXh0LmdldERlc2NyaXB0aW9uRm9yKAoJCQkJbmV3IEJ5dGVBcnJheUlucHV0U3RyZWFtKChVVEY4X0JPTV8yYnl0ZXMgKyBNSU5JTUFMX1hNTCkuZ2V0Qnl0ZXMoU3RhbmRhcmRDaGFyc2V0cy5JU09fODg1OV8xKSksCgkJCQlvcHRpb25zKTsKCQlhc3NlcnROdWxsKCI4LjAiLCBkZXNjcmlwdGlvbi5nZXRQcm9wZXJ0eShJQ29udGVudERlc2NyaXB0aW9uLkJZVEVfT1JERVJfTUFSSykpOwoJCS8vIHR3byBmaXJzdCBieXRlcyBvZiBVVEYtOCBvbmx5CgkJZGVzY3JpcHRpb24gPSB0ZXh0LmdldERlc2NyaXB0aW9uRm9yKAoJCQkJbmV3IEJ5dGVBcnJheUlucHV0U3RyZWFtKChVVEY4X0JPTV8yYnl0ZXMpLmdldEJ5dGVzKFN0YW5kYXJkQ2hhcnNldHMuSVNPXzg4NTlfMSkpLCBvcHRpb25zKTsKCQlhc3NlcnROdWxsKCI4LjEiLCBkZXNjcmlwdGlvbi5nZXRQcm9wZXJ0eShJQ29udGVudERlc2NyaXB0aW9uLkJZVEVfT1JERVJfTUFSSykpOwoJfQoKCS8qKgoJICogU2VlIGJ1ZyA5MDIxOC4KCSAqLwoJQFRlc3QKCXB1YmxpYyB2b2lkIHRlc3RDb250ZW50QW5kTmFtZU1hdGNoaW5nKCkgdGhyb3dzIElPRXhjZXB0aW9uIC8qIG5vdCByZWFsbHkgKi8gewoJCUlDb250ZW50VHlwZU1hbmFnZXIgbWFuYWdlciA9IFBsYXRmb3JtLmdldENvbnRlbnRUeXBlTWFuYWdlcigpOwoKCQlieXRlW11bXSBjb250ZW50czAgPSB7IHsgMHgwQSwgMHgwQiwgMHgwRSwgMHgxMCB9IH07CgkJYnl0ZVtdW10gY29udGVudHMxID0geyB7IDB4MEEsIDB4MEIsIDB4MEMsIDB4MTAgfSB9OwoJCWJ5dGVbXVtdIGNvbnRlbnRzMiA9IHsgeyAweDBBLCAweDBCLCAweDBELCAweDEwIH0gfTsKCQlieXRlW11bXSBpbnZhbGlkQ29udGVudHMgPSB7IHsgMCwgMCwgMCwgMCB9IH07CgoJCS8vIGJhc2UgbWF0Y2hlcyAqLm15YmluYXJ5IGZpbGVzIHN0YXJ0aW5nIHdpdGggMHgwYSAweDBiCgkJSUNvbnRlbnRUeXBlIGJhc2UgPSBtYW5hZ2VyLmdldENvbnRlbnRUeXBlKFBJX1JFU09VUkNFU19URVNUUyArICIuYmluYXJ5X2Jhc2UiKTsKCQkvLyBkZXJpdmVkMSBtYXRjaGVzICoubXliaW5hcnkgYW5kIHNwZWNpZmljYWxseSBmb28ubXliaW5hcnkgZmlsZXMgc3RhcnRpbmcgd2l0aAoJCS8vIDB4MGEgMHgwYiAweGMKCQlJQ29udGVudFR5cGUgZGVyaXZlZDEgPSBtYW5hZ2VyLmdldENvbnRlbnRUeXBlKFBJX1JFU09VUkNFU19URVNUUyArICIuYmluYXJ5X2Rlcml2ZWQxIik7CgkJLy8gZGVyaXZlZDIgbWF0Y2hlcyAqLm15YmluYXJ5IChpbmhlcml0cyBmaWxlc3BlYyBmcm9tIGJhc2UpIGZpbGVzIHN0YXJ0aW5nIHdpdGgKCQkvLyAweDBhIDB4MGIgMHhkCgkJSUNvbnRlbnRUeXBlIGRlcml2ZWQyID0gbWFuYWdlci5nZXRDb250ZW50VHlwZShQSV9SRVNPVVJDRVNfVEVTVFMgKyAiLmJpbmFyeV9kZXJpdmVkMiIpOwoKCQlJQ29udGVudFR5cGVbXSBzZWxlY3RlZDsKCgkJc2VsZWN0ZWQgPSBtYW5hZ2VyLmZpbmRDb250ZW50VHlwZXNGb3IoZ2V0SW5wdXRTdHJlYW0oY29udGVudHMwKSwgImFueXRoaW5nLm15YmluYXJ5Iik7CgkJYXNzZXJ0RXF1YWxzKCIxLjAiLCAzLCBzZWxlY3RlZC5sZW5ndGgpOwoJCS8vIGFsbCB3ZSBrbm93IGlzIHRoZSBmaXJzdCBvbmUgaXMgdGhlIGJhc2UgdHlwZSAob25seSBvbmUgd2l0aCBhIFZBTElEIG1hdGNoKQoJCWFzc2VydEVxdWFscygiMS4xIiwgYmFzZSwgc2VsZWN0ZWRbMF0pOwoKCQlzZWxlY3RlZCA9IG1hbmFnZXIuZmluZENvbnRlbnRUeXBlc0ZvcihnZXRJbnB1dFN0cmVhbShjb250ZW50czApLCAiZm9vLm15YmluYXJ5Iik7CgkJLy8gd2Uga25vdyBhbHNvIHRoYXQgdGhlIHNlY29uZCBvbmUgd2lsbCBiZSBkZXJpdmVkMSwgYmVjYXVzZSBpdCBoYXMgYSBmdWxsIG5hbWUKCQkvLyBtYXRjaGluZwoJCWFzc2VydEVxdWFscygiMi4wIiwgMywgc2VsZWN0ZWQubGVuZ3RoKTsKCQlhc3NlcnRFcXVhbHMoIjIuMSIsIGJhc2UsIHNlbGVjdGVkWzBdKTsKCQlhc3NlcnRFcXVhbHMoIjIuMiIsIGRlcml2ZWQxLCBzZWxlY3RlZFsxXSk7CgoJCXNlbGVjdGVkID0gbWFuYWdlci5maW5kQ29udGVudFR5cGVzRm9yKGdldElucHV0U3RyZWFtKGNvbnRlbnRzMSksICJmb28ubXliaW5hcnkiKTsKCQkvLyBkZXJpdmVkMSB3aWxsIGJlIGZpcnN0IGJlY2F1c2UgYm90aCBiYXNlIGFuZCBkZXJpdmVkMSBoYXZlIGEgc3Ryb25nIGNvbnRlbnQKCQkvLyBtYXRjaGluZywgc28gbW9yZSBzcGVjaWZpYyB3aW5zCgkJYXNzZXJ0RXF1YWxzKCIzLjAiLCAzLCBzZWxlY3RlZC5sZW5ndGgpOwoJCWFzc2VydEVxdWFscygiMy4xIiwgZGVyaXZlZDEsIHNlbGVjdGVkWzBdKTsKCQlhc3NlcnRFcXVhbHMoIjMuMiIsIGJhc2UsIHNlbGVjdGVkWzFdKTsKCgkJc2VsZWN0ZWQgPSBtYW5hZ2VyLmZpbmRDb250ZW50VHlwZXNGb3IoZ2V0SW5wdXRTdHJlYW0oY29udGVudHMyKSwgImZvby5teWJpbmFyeSIpOwoJCS8vIHNhbWUgYXMgMy4qIC0gZGVyaXZlZDEgaXMgbGFzdCBiZWNhdXNlIGNvbnRlbnQgbWF0Y2hpbmcgaXMgd2VhaywgYWx0aG91ZyBuYW1lCgkJLy8gbWF0Y2hpbmcgaXMgc3Ryb25nCgkJYXNzZXJ0RXF1YWxzKCI0LjAiLCAzLCBzZWxlY3RlZC5sZW5ndGgpOwoJCWFzc2VydEVxdWFscygiNC4xIiwgZGVyaXZlZDIsIHNlbGVjdGVkWzBdKTsKCQlhc3NlcnRFcXVhbHMoIjQuMiIsIGJhc2UsIHNlbGVjdGVkWzFdKTsKCgkJc2VsZWN0ZWQgPSBtYW5hZ2VyLmZpbmRDb250ZW50VHlwZXNGb3IoZ2V0SW5wdXRTdHJlYW0oaW52YWxpZENvbnRlbnRzKSwgImZvby5teWJpbmFyeSIpOwoJCS8vIGFsbCB0eXBlcyBoYXZlIHdlYWsgY29udGVudCBtYXRjaGluZyBvbmx5IC0gZGVyaXZlZDEgaGFzIHN0cm9uZyBuYW1lIG1hdGNoaW5nCgkJYXNzZXJ0RXF1YWxzKCI1LjAiLCAzLCBzZWxlY3RlZC5sZW5ndGgpOwoJCWFzc2VydEVxdWFscygiNS4xIiwgZGVyaXZlZDEsIHNlbGVjdGVkWzBdKTsKCQlhc3NlcnRFcXVhbHMoIjUuMiIsIGJhc2UsIHNlbGVjdGVkWzFdKTsKCgkJc2VsZWN0ZWQgPSBtYW5hZ2VyLmZpbmRDb250ZW50VHlwZXNGb3IoZ2V0SW5wdXRTdHJlYW0oaW52YWxpZENvbnRlbnRzKSwgImFueXRoaW5nLm15YmluYXJ5Iik7CgkJLy8gYWxsIHR5cGVzIGhhdmUgd2VhayBjb250ZW50L25hbWUgbWF0Y2hpbmcgb25seSAtIG1vc3QgZ2VuZXJhbCB3aW5zCgkJYXNzZXJ0RXF1YWxzKCI2LjAiLCAzLCBzZWxlY3RlZC5sZW5ndGgpOwoJCWFzc2VydEVxdWFscygiNi4xIiwgYmFzZSwgc2VsZWN0ZWRbMF0pOwoJfQoKCS8qCgkgKiBUZXN0cyBib3RoIHRleHQgYW5kIGJ5dGUgc3RyZWFtLWJhc2VkIGdldERlc2NyaXB0aW9uRm9yIG1ldGhvZHMuCgkgKi9AVGVzdAoJcHVibGljIHZvaWQgdGVzdENvbnRlbnREZXNjcmlwdGlvbigpIHRocm93cyBJT0V4Y2VwdGlvbiwgQ29yZUV4Y2VwdGlvbiB7CgkJSUNvbnRlbnRUeXBlTWFuYWdlciBjb250ZW50VHlwZU1hbmFnZXIgPSBQbGF0Zm9ybS5nZXRDb250ZW50VHlwZU1hbmFnZXIoKTsKCQlJQ29udGVudFR5cGVNYXRjaGVyIGZpbmRlciA9IGNvbnRlbnRUeXBlTWFuYWdlci5nZXRNYXRjaGVyKG5ldyBMb2NhbFNlbGVjdGlvblBvbGljeSgpLCBudWxsKTsKCgkJSUNvbnRlbnRUeXBlIHhtbFR5cGUgPSBjb250ZW50VHlwZU1hbmFnZXIuZ2V0Q29udGVudFR5cGUoUGxhdGZvcm0uUElfUlVOVElNRSArICIueG1sIik7CgkJSUNvbnRlbnRUeXBlIG15dGV4dCA9IGNvbnRlbnRUeXBlTWFuYWdlci5nZXRDb250ZW50VHlwZShQSV9SRVNPVVJDRVNfVEVTVFMgKyAnLicgKyAibXl0ZXh0Iik7CgkJSUNvbnRlbnRUeXBlIG15dGV4dDEgPSBjb250ZW50VHlwZU1hbmFnZXIuZ2V0Q29udGVudFR5cGUoUElfUkVTT1VSQ0VTX1RFU1RTICsgJy4nICsgIm15dGV4dDEiKTsKCQlJQ29udGVudFR5cGUgbXl0ZXh0MiA9IGNvbnRlbnRUeXBlTWFuYWdlci5nZXRDb250ZW50VHlwZShQSV9SRVNPVVJDRVNfVEVTVFMgKyAnLicgKyAibXl0ZXh0MiIpOwoKCQlib29sZWFuIHRleHQgPSBmYWxzZTsKCgkJZm9yIChpbnQgaSA9IDA7IGkgPCAyOyBpKyssIHRleHQgPSAhdGV4dCkgewoJCQlTdHJpbmcgc3VmaXggPSB0ZXh0ID8gIi10ZXh0IiA6ICItYmluYXJ5IjsKCQkJSUNvbnRlbnREZXNjcmlwdGlvbiBkZXNjcmlwdGlvbjsKCgkJCWRlc2NyaXB0aW9uID0gZ2V0RGVzY3JpcHRpb25Gb3IoZmluZGVyLCBNSU5JTUFMX1hNTCwgU3RhbmRhcmRDaGFyc2V0cy5VVEZfOCwgImZvby54bWwiLAoJCQkJCUlDb250ZW50RGVzY3JpcHRpb24uQUxMLCB0ZXh0KTsKCQkJYXNzZXJ0Tm90TnVsbCgiMS4wIiArIHN1Zml4LCBkZXNjcmlwdGlvbik7CgkJCWFzc2VydEVxdWFscygiMS4xIiArIHN1Zml4LCB4bWxUeXBlLCBkZXNjcmlwdGlvbi5nZXRDb250ZW50VHlwZSgpKTsKCQkJYXNzZXJ0U2FtZSgiMS4yIiwgeG1sVHlwZS5nZXREZWZhdWx0RGVzY3JpcHRpb24oKSwgZGVzY3JpcHRpb24pOwoKCQkJZGVzY3JpcHRpb24gPSBnZXREZXNjcmlwdGlvbkZvcihmaW5kZXIsIE1JTklNQUxfWE1MLCBTdGFuZGFyZENoYXJzZXRzLlVURl84LCAiZm9vLnhtbCIsCgkJCQkJbmV3IFF1YWxpZmllZE5hbWVbXSB7IElDb250ZW50RGVzY3JpcHRpb24uQ0hBUlNFVCB9LCB0ZXh0KTsKCQkJYXNzZXJ0Tm90TnVsbCgiMi4wIiArIHN1Zml4LCBkZXNjcmlwdGlvbik7CgkJCWFzc2VydEVxdWFscygiMi4xIiArIHN1Zml4LCB4bWxUeXBlLCBkZXNjcmlwdGlvbi5nZXRDb250ZW50VHlwZSgpKTsKCQkJLy8gdGhlIGRlZmF1bHQgY2hhcnNldCBzaG91bGQgaGF2ZSBiZWVuIGZpbGxlZCBieSB0aGUgY29udGVudCB0eXBlIG1hbmFnZXIKCQkJYXNzZXJ0RXF1YWxzKCIyLjIiICsgc3VmaXgsICJVVEYtOCIsIGRlc2NyaXB0aW9uLmdldFByb3BlcnR5KElDb250ZW50RGVzY3JpcHRpb24uQ0hBUlNFVCkpOwoJCQlhc3NlcnRTYW1lKCIyLjMiLCB4bWxUeXBlLmdldERlZmF1bHREZXNjcmlwdGlvbigpLCBkZXNjcmlwdGlvbik7CgoJCQlkZXNjcmlwdGlvbiA9IGdldERlc2NyaXB0aW9uRm9yKGZpbmRlciwgWE1MX0lTT184ODU5XzEsIFN0YW5kYXJkQ2hhcnNldHMuSVNPXzg4NTlfMSwgImZvby54bWwiLAoJCQkJCW5ldyBRdWFsaWZpZWROYW1lW10geyBJQ29udGVudERlc2NyaXB0aW9uLkNIQVJTRVQgfSwgdGV4dCk7CgkJCWFzc2VydE5vdE51bGwoIjIuM2EiICsgc3VmaXgsIGRlc2NyaXB0aW9uKTsKCQkJYXNzZXJ0RXF1YWxzKCIyLjNiIiArIHN1Zml4LCB4bWxUeXBlLCBkZXNjcmlwdGlvbi5nZXRDb250ZW50VHlwZSgpKTsKCQkJYXNzZXJ0RXF1YWxzKCIyLjNjIiArIHN1Zml4LCAiSVNPLTg4NTktMSIsIGRlc2NyaXB0aW9uLmdldFByb3BlcnR5KElDb250ZW50RGVzY3JpcHRpb24uQ0hBUlNFVCkpOwoJCQlhc3NlcnROb3RTYW1lKCIyLjNkIiwgeG1sVHlwZS5nZXREZWZhdWx0RGVzY3JpcHRpb24oKSwgZGVzY3JpcHRpb24pOwoKCQkJLy8gZW5zdXJlIHdlIGhhbmRsZSBzaW5nbGUgcXVvdGVzIHByb3Blcmx5IChidWcgNjU0NDMpCgkJCWRlc2NyaXB0aW9uID0gZ2V0RGVzY3JpcHRpb25Gb3IoZmluZGVyLCBYTUxfSVNPXzg4NTlfMV9TSU5HTEVfUVVPVEVTLCBTdGFuZGFyZENoYXJzZXRzLklTT184ODU5XzEsCgkJCQkJImZvby54bWwiLCBuZXcgUXVhbGlmaWVkTmFtZVtdIHsgSUNvbnRlbnREZXNjcmlwdGlvbi5DSEFSU0VUIH0sIHRleHQpOwoJCQlhc3NlcnROb3ROdWxsKCIyLjNlIiArIHN1Zml4LCBkZXNjcmlwdGlvbik7CgkJCWFzc2VydEVxdWFscygiMi4zZiIgKyBzdWZpeCwgeG1sVHlwZSwgZGVzY3JpcHRpb24uZ2V0Q29udGVudFR5cGUoKSk7CgkJCWFzc2VydEVxdWFscygiMi4zZyIgKyBzdWZpeCwgIklTTy04ODU5LTEiLCBkZXNjcmlwdGlvbi5nZXRQcm9wZXJ0eShJQ29udGVudERlc2NyaXB0aW9uLkNIQVJTRVQpKTsKCQkJYXNzZXJ0Tm90U2FtZSgiMi4zaCIsIHhtbFR5cGUuZ2V0RGVmYXVsdERlc2NyaXB0aW9uKCksIGRlc2NyaXB0aW9uKTsKCgkJCWRlc2NyaXB0aW9uID0gZ2V0RGVzY3JpcHRpb25Gb3IoZmluZGVyLCBYTUxfVVRGXzE2LCBTdGFuZGFyZENoYXJzZXRzLlVURl8xNiwgImZvby54bWwiLAoJCQkJCW5ldyBRdWFsaWZpZWROYW1lW10geyBJQ29udGVudERlc2NyaXB0aW9uLkNIQVJTRVQsIElDb250ZW50RGVzY3JpcHRpb24uQllURV9PUkRFUl9NQVJLIH0sIHRleHQpOwoJCQlhc3NlcnROb3ROdWxsKCIyLjRhIiArIHN1Zml4LCBkZXNjcmlwdGlvbik7CgkJCWFzc2VydEVxdWFscygiMi40YiIgKyBzdWZpeCwgeG1sVHlwZSwgZGVzY3JpcHRpb24uZ2V0Q29udGVudFR5cGUoKSk7CgkJCWFzc2VydEVxdWFscygiMi40YyIgKyBzdWZpeCwgIlVURi0xNiIsIGRlc2NyaXB0aW9uLmdldFByb3BlcnR5KElDb250ZW50RGVzY3JpcHRpb24uQ0hBUlNFVCkpOwoJCQlhc3NlcnRUcnVlKCIyLjRkIiArIHN1Zml4LCB0ZXh0IHx8IElDb250ZW50RGVzY3JpcHRpb24uQk9NX1VURl8xNkJFID09IGRlc2NyaXB0aW9uCgkJCQkJLmdldFByb3BlcnR5KElDb250ZW50RGVzY3JpcHRpb24uQllURV9PUkRFUl9NQVJLKSk7CgkJCWFzc2VydE5vdFNhbWUoIjIuNGUiLCB4bWxUeXBlLmdldERlZmF1bHREZXNjcmlwdGlvbigpLCBkZXNjcmlwdGlvbik7CgoJCQlkZXNjcmlwdGlvbiA9IGdldERlc2NyaXB0aW9uRm9yKGZpbmRlciwgWE1MX1VURl8xNkJFLCBTdGFuZGFyZENoYXJzZXRzLlVURl84LCAiZm9vLnhtbCIsCgkJCQkJbmV3IFF1YWxpZmllZE5hbWVbXSB7IElDb250ZW50RGVzY3JpcHRpb24uQ0hBUlNFVCB9LCB0ZXh0KTsKCQkJYXNzZXJ0Tm90TnVsbCgiMi41YSIgKyBzdWZpeCwgZGVzY3JpcHRpb24pOwoJCQlhc3NlcnRFcXVhbHMoIjIuNWIiICsgc3VmaXgsIHhtbFR5cGUsIGRlc2NyaXB0aW9uLmdldENvbnRlbnRUeXBlKCkpOwoJCQlhc3NlcnRFcXVhbHMoIjIuNWMiICsgc3VmaXgsICJVVEYtMTZCRSIsIGRlc2NyaXB0aW9uLmdldFByb3BlcnR5KElDb250ZW50RGVzY3JpcHRpb24uQ0hBUlNFVCkpOwoJCQlhc3NlcnROb3RTYW1lKCIyLjVkIiwgeG1sVHlwZS5nZXREZWZhdWx0RGVzY3JpcHRpb24oKSwgZGVzY3JpcHRpb24pOwoKCQkJZGVzY3JpcHRpb24gPSBnZXREZXNjcmlwdGlvbkZvcihmaW5kZXIsIFhNTF9VVEZfMTZMRSwgU3RhbmRhcmRDaGFyc2V0cy5VVEZfOCwgImZvby54bWwiLAoJCQkJCW5ldyBRdWFsaWZpZWROYW1lW10geyBJQ29udGVudERlc2NyaXB0aW9uLkNIQVJTRVQgfSwgdGV4dCk7CgkJCWFzc2VydE5vdE51bGwoIjIuNmEiICsgc3VmaXgsIGRlc2NyaXB0aW9uKTsKCQkJYXNzZXJ0RXF1YWxzKCIyLjZiIiArIHN1Zml4LCB4bWxUeXBlLCBkZXNjcmlwdGlvbi5nZXRDb250ZW50VHlwZSgpKTsKCQkJLy8gdGhlIGRlZmF1bHQgY2hhcnNldCBzaG91bGQgaGF2ZSBiZWVuIGZpbGxlZCBieSB0aGUgY29udGVudCB0eXBlIG1hbmFnZXIKCQkJYXNzZXJ0RXF1YWxzKCIyLjZjIiArIHN1Zml4LCAiVVRGLTE2TEUiLCBkZXNjcmlwdGlvbi5nZXRQcm9wZXJ0eShJQ29udGVudERlc2NyaXB0aW9uLkNIQVJTRVQpKTsKCQkJYXNzZXJ0Tm90U2FtZSgiMi42ZCIsIHhtbFR5cGUuZ2V0RGVmYXVsdERlc2NyaXB0aW9uKCksIGRlc2NyaXB0aW9uKTsKCgkJCWRlc2NyaXB0aW9uID0gZ2V0RGVzY3JpcHRpb25Gb3IoZmluZGVyLCBNSU5JTUFMX1hNTCwgU3RhbmRhcmRDaGFyc2V0cy5VVEZfOCwgImZvby54bWwiLAoJCQkJCUlDb250ZW50RGVzY3JpcHRpb24uQUxMLCB0ZXh0KTsKCQkJYXNzZXJ0Tm90TnVsbCgiNC4wIiArIHN1Zml4LCBkZXNjcmlwdGlvbik7CgkJCWFzc2VydEVxdWFscygiNC4xIiArIHN1Zml4LCB4bWxUeXBlLCBkZXNjcmlwdGlvbi5nZXRDb250ZW50VHlwZSgpKTsKCQkJYXNzZXJ0RXF1YWxzKCI0LjIiICsgc3VmaXgsICJVVEYtOCIsIGRlc2NyaXB0aW9uLmdldFByb3BlcnR5KElDb250ZW50RGVzY3JpcHRpb24uQ0hBUlNFVCkpOwoJCQlhc3NlcnROb3ROdWxsKCI1LjAiICsgc3VmaXgsIG15dGV4dCk7CgkJCWFzc2VydEVxdWFscygiNS4wYiIgKyBzdWZpeCwgIkJBUiIsIG15dGV4dC5nZXREZWZhdWx0Q2hhcnNldCgpKTsKCQkJYXNzZXJ0U2FtZSgiNS4wYyIsIHhtbFR5cGUuZ2V0RGVmYXVsdERlc2NyaXB0aW9uKCksIGRlc2NyaXB0aW9uKTsKCgkJCWRlc2NyaXB0aW9uID0gZ2V0RGVzY3JpcHRpb25Gb3IoZmluZGVyLCAic29tZSBjb250ZW50cyIsIG51bGwsICJhYmMudHp0IiwgSUNvbnRlbnREZXNjcmlwdGlvbi5BTEwsIHRleHQpOwoJCQlhc3NlcnROb3ROdWxsKCI1LjEiICsgc3VmaXgsIGRlc2NyaXB0aW9uKTsKCQkJYXNzZXJ0RXF1YWxzKCI1LjIiICsgc3VmaXgsIG15dGV4dCwgZGVzY3JpcHRpb24uZ2V0Q29udGVudFR5cGUoKSk7CgkJCWFzc2VydEVxdWFscygiNS4zIiArIHN1Zml4LCAiQkFSIiwgZGVzY3JpcHRpb24uZ2V0UHJvcGVydHkoSUNvbnRlbnREZXNjcmlwdGlvbi5DSEFSU0VUKSk7CgkJCWFzc2VydFNhbWUoIjUuNCIsIG15dGV4dC5nZXREZWZhdWx0RGVzY3JpcHRpb24oKSwgZGVzY3JpcHRpb24pOwoJCQkvLyBub3cgcGxheXMgd2l0aCBzZXR0aW5nIGEgbm9uLWRlZmF1bHQgZGVmYXVsdCBjaGFyc2V0CgkJCW15dGV4dC5zZXREZWZhdWx0Q2hhcnNldCgiRk9PIik7CgoJCQlkZXNjcmlwdGlvbiA9IGdldERlc2NyaXB0aW9uRm9yKGZpbmRlciwgInNvbWUgY29udGVudHMiLCBudWxsLCAiYWJjLnR6dCIsIElDb250ZW50RGVzY3JpcHRpb24uQUxMLCB0ZXh0KTsKCQkJYXNzZXJ0Tm90TnVsbCgiNS41IiArIHN1Zml4LCBkZXNjcmlwdGlvbik7CgkJCWFzc2VydEVxdWFscygiNS42IiArIHN1Zml4LCBteXRleHQsIGRlc2NyaXB0aW9uLmdldENvbnRlbnRUeXBlKCkpOwoJCQlhc3NlcnRFcXVhbHMoIjUuNyIgKyBzdWZpeCwgIkZPTyIsIGRlc2NyaXB0aW9uLmdldFByb3BlcnR5KElDb250ZW50RGVzY3JpcHRpb24uQ0hBUlNFVCkpOwoJCQlhc3NlcnRTYW1lKCI1LjgiLCBteXRleHQuZ2V0RGVmYXVsdERlc2NyaXB0aW9uKCksIGRlc2NyaXB0aW9uKTsKCQkJbXl0ZXh0LnNldERlZmF1bHRDaGFyc2V0KG51bGwpOwoKCQkJZGVzY3JpcHRpb24gPSBnZXREZXNjcmlwdGlvbkZvcihmaW5kZXIsICJzb21lIGNvbnRlbnRzIiwgbnVsbCwgImFiYy50enQiLCBJQ29udGVudERlc2NyaXB0aW9uLkFMTCwgdGV4dCk7CgkJCWFzc2VydE5vdE51bGwoIjUuMTAiICsgc3VmaXgsIGRlc2NyaXB0aW9uKTsKCQkJYXNzZXJ0RXF1YWxzKCI1LjExIiArIHN1Zml4LCBteXRleHQsIGRlc2NyaXB0aW9uLmdldENvbnRlbnRUeXBlKCkpOwoJCQlhc3NlcnRFcXVhbHMoIjUuMTIiICsgc3VmaXgsICJCQVIiLCBkZXNjcmlwdGlvbi5nZXRQcm9wZXJ0eShJQ29udGVudERlc2NyaXB0aW9uLkNIQVJTRVQpKTsKCQkJYXNzZXJ0U2FtZSgiNS4xMyIsIG15dGV4dC5nZXREZWZhdWx0RGVzY3JpcHRpb24oKSwgZGVzY3JpcHRpb24pOwoKCQkJLy8gc2VlIGh0dHBzOi8vYnVncy5lY2xpcHNlLm9yZy9idWdzL3Nob3dfYnVnLmNnaT9pZD0xNzYzNTQKCQkJZGVzY3JpcHRpb24gPSBnZXREZXNjcmlwdGlvbkZvcihmaW5kZXIsCgkJCQkJIjw/eG1sIHZlcnNpb249XCcxLjBcJyBlbmNvZGluZz1cJ1VURi04XCc/Pjxzb2FwZW52OkVudmVsb3BlIHhtbG5zOnNvYXBlbnY9XCJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy9zb2FwL2VudmVsb3BlL1wiIHhtbG5zOnRucz1cImh0dHA6Ly93d3cuZXhhbXBsZS5vcmcvXCIgeG1sbnM6bnMwPVwiaHR0cDovL2Fub3RoZXIuZXhhbXBsZS5vcmcvXCI+PHNvYXBlbnY6SGVhZGVyIC8+PHNvYXBlbnY6Qm9keT48bnMwOnggLz48L3NvYXBlbnY6Qm9keT48L3NvYXBlbnY6RW52ZWxvcGU+IiwKCQkJCQlTdGFuZGFyZENoYXJzZXRzLlVURl84LCAiZm9vLnhtbCIsIG5ldyBRdWFsaWZpZWROYW1lW10geyBJQ29udGVudERlc2NyaXB0aW9uLkNIQVJTRVQgfSwgdGV4dCk7CgkJCWFzc2VydE5vdE51bGwoIjUuMTQiICsgc3VmaXgsIGRlc2NyaXB0aW9uKTsKCQkJYXNzZXJ0RXF1YWxzKCI1LjE1IiArIHN1Zml4LCB4bWxUeXBlLCBkZXNjcmlwdGlvbi5nZXRDb250ZW50VHlwZSgpKTsKCQkJYXNzZXJ0RXF1YWxzKCI1LjE2IiArIHN1Zml4LCAiVVRGLTgiLCBkZXNjcmlwdGlvbi5nZXRQcm9wZXJ0eShJQ29udGVudERlc2NyaXB0aW9uLkNIQVJTRVQpKTsKCQkJYXNzZXJ0RXF1YWxzKCI1LjE3IiwgeG1sVHlwZS5nZXREZWZhdWx0RGVzY3JpcHRpb24oKS5nZXRDaGFyc2V0KCksIGRlc2NyaXB0aW9uLmdldENoYXJzZXQoKSk7CgkJfQoJCWFzc2VydE5vdE51bGwoIjYuMCIsIG15dGV4dDEpOwoJCWFzc2VydEVxdWFscygiNi4xIiwgIkJBUiIsIG15dGV4dDEuZ2V0RGVmYXVsdENoYXJzZXQoKSk7CgkJYXNzZXJ0Tm90TnVsbCgiNi4yIiwgbXl0ZXh0Mik7CgkJYXNzZXJ0RXF1YWxzKCI2LjMiLCBudWxsLCBteXRleHQyLmdldERlZmF1bHRDaGFyc2V0KCkpOwoKCX0KCglAVGVzdAoJcHVibGljIHZvaWQgdGVzdENvbnRlbnREZXRlY3Rpb24oKSB0aHJvd3MgSU9FeGNlcHRpb24gewoJCUlDb250ZW50VHlwZU1hbmFnZXIgY29udGVudFR5cGVNYW5hZ2VyID0gUGxhdGZvcm0uZ2V0Q29udGVudFR5cGVNYW5hZ2VyKCk7CgkJSUNvbnRlbnRUeXBlTWF0Y2hlciBmaW5kZXI7CgoJCUlDb250ZW50VHlwZSBpbmFwcHJvcHJpYXRlID0gY29udGVudFR5cGVNYW5hZ2VyLmdldENvbnRlbnRUeXBlKFBJX1JFU09VUkNFU19URVNUUyArICIuc2FtcGxlLWJpbmFyeTEiKTsKCQlJQ29udGVudFR5cGUgYXBwcm9wcmlhdGUgPSBjb250ZW50VHlwZU1hbmFnZXIuZ2V0Q29udGVudFR5cGUoUGxhdGZvcm0uUElfUlVOVElNRSArICIueG1sIik7CgkJSUNvbnRlbnRUeXBlIGFwcHJvcHJpYXRlU3BlY2lmaWMxID0gY29udGVudFR5cGVNYW5hZ2VyCgkJCQkuZ2V0Q29udGVudFR5cGUoUElfUkVTT1VSQ0VTX1RFU1RTICsgIi54bWwtYmFzZWQtZGlmZmVyZW50LWV4dGVuc2lvbiIpOwoJCUlDb250ZW50VHlwZSBhcHByb3ByaWF0ZVNwZWNpZmljMUxvd1ByaW9yaXR5ID0gY29udGVudFR5cGVNYW5hZ2VyCgkJCQkuZ2V0Q29udGVudFR5cGUoUElfUkVTT1VSQ0VTX1RFU1RTICsgIi54bWwtYmFzZWQtZGlmZmVyZW50LWV4dGVuc2lvbi1sb3ctcHJpb3JpdHkiKTsKCQlJQ29udGVudFR5cGUgYXBwcm9wcmlhdGVTcGVjaWZpYzIgPSBjb250ZW50VHlwZU1hbmFnZXIKCQkJCS5nZXRDb250ZW50VHlwZShQSV9SRVNPVVJDRVNfVEVTVFMgKyAiLnhtbC1iYXNlZC1zcGVjaWZpYy1uYW1lIik7CgoJCS8vIGlmIG9ubHkgaW5hcHByb3ByaWF0ZSBpcyBwcm92aWRlZCwgbm9uZSB3aWxsIGJlIHNlbGVjdGVkCgkJZmluZGVyID0gY29udGVudFR5cGVNYW5hZ2VyLmdldE1hdGNoZXIobmV3IFN1YnNldFNlbGVjdGlvblBvbGljeShuZXcgSUNvbnRlbnRUeXBlW10geyBpbmFwcHJvcHJpYXRlIH0pLCBudWxsKTsKCQlhc3NlcnROdWxsKCIxLjAiLCBmaW5kZXIuZmluZENvbnRlbnRUeXBlRm9yKGdldElucHV0U3RyZWFtKE1JTklNQUxfWE1MKSwgbnVsbCkpOwoKCQkvLyBpZiBpbmFwcHJvcHJpYXRlIGFuZCBhcHByb3ByaWF0ZSBhcmUgcHJvdmlkZWQsIGFwcHJvcHJpYXRlIHdpbGwgYmUgc2VsZWN0ZWQKCQlmaW5kZXIgPSBjb250ZW50VHlwZU1hbmFnZXIKCQkJCS5nZXRNYXRjaGVyKG5ldyBTdWJzZXRTZWxlY3Rpb25Qb2xpY3kobmV3IElDb250ZW50VHlwZVtdIHsgaW5hcHByb3ByaWF0ZSwgYXBwcm9wcmlhdGUgfSksIG51bGwpOwoJCWFzc2VydEVxdWFscygiMi4wIiwgYXBwcm9wcmlhdGUsIGZpbmRlci5maW5kQ29udGVudFR5cGVGb3IoZ2V0SW5wdXRTdHJlYW0oTUlOSU1BTF9YTUwpLCBudWxsKSk7CgoJCS8vIGlmIGluYXBwcm9wcmlhdGUsIGFwcHJvcHJpYXRlIGFuZCBhIG1vcmUgc3BlY2lmaWMgYXBwcm9wcmlhdGUgdHlwZSBhcmUKCQkvLyBwcm92aWRlZCwgdGhlIHNwZWNpZmljIHR5cGUgd2lsbCBiZSBzZWxlY3RlZAoJCWZpbmRlciA9IGNvbnRlbnRUeXBlTWFuYWdlci5nZXRNYXRjaGVyKAoJCQkJbmV3IFN1YnNldFNlbGVjdGlvblBvbGljeShuZXcgSUNvbnRlbnRUeXBlW10geyBpbmFwcHJvcHJpYXRlLCBhcHByb3ByaWF0ZSwgYXBwcm9wcmlhdGVTcGVjaWZpYzEgfSksCgkJCQludWxsKTsKCQlhc3NlcnRFcXVhbHMoIjMuMCIsIGFwcHJvcHJpYXRlU3BlY2lmaWMxLCBmaW5kZXIuZmluZENvbnRlbnRUeXBlRm9yKGdldElucHV0U3RyZWFtKE1JTklNQUxfWE1MKSwgbnVsbCkpOwoJCWZpbmRlciA9IGNvbnRlbnRUeXBlTWFuYWdlci5nZXRNYXRjaGVyKAoJCQkJbmV3IFN1YnNldFNlbGVjdGlvblBvbGljeShuZXcgSUNvbnRlbnRUeXBlW10geyBpbmFwcHJvcHJpYXRlLCBhcHByb3ByaWF0ZSwgYXBwcm9wcmlhdGVTcGVjaWZpYzIgfSksCgkJCQludWxsKTsKCQlhc3NlcnRFcXVhbHMoIjMuMSIsIGFwcHJvcHJpYXRlU3BlY2lmaWMyLCBmaW5kZXIuZmluZENvbnRlbnRUeXBlRm9yKGdldElucHV0U3RyZWFtKE1JTklNQUxfWE1MKSwgbnVsbCkpOwoKCQkvLyBpZiBhbGwgYXJlIHByb3ZpZGVkLCB0aGUgbW9yZSBzcGVjaWZpYyB0eXBlcyB3aWxsIGFwcGVhciBiZWZvcmUgdGhlIG1vcmUKCQkvLyBnZW5lcmljIHR5cGVzCgkJZmluZGVyID0gY29udGVudFR5cGVNYW5hZ2VyLmdldE1hdGNoZXIoCgkJCQluZXcgU3Vic2V0U2VsZWN0aW9uUG9saWN5KAoJCQkJCQluZXcgSUNvbnRlbnRUeXBlW10geyBpbmFwcHJvcHJpYXRlLCBhcHByb3ByaWF0ZSwgYXBwcm9wcmlhdGVTcGVjaWZpYzEsIGFwcHJvcHJpYXRlU3BlY2lmaWMyIH0pLAoJCQkJbnVsbCk7CgkJSUNvbnRlbnRUeXBlW10gc2VsZWN0ZWQgPSBmaW5kZXIuZmluZENvbnRlbnRUeXBlc0ZvcihnZXRJbnB1dFN0cmVhbShNSU5JTUFMX1hNTCksIG51bGwpOwoJCWFzc2VydEVxdWFscygiNC4wIiwgMywgc2VsZWN0ZWQubGVuZ3RoKTsKCQlhc3NlcnRUcnVlKCI0LjEiLCBhcHByb3ByaWF0ZVNwZWNpZmljMS5lcXVhbHMoc2VsZWN0ZWRbMF0pIHx8IGFwcHJvcHJpYXRlU3BlY2lmaWMxLmVxdWFscyhzZWxlY3RlZFsxXSkpOwoJCWFzc2VydFRydWUoIjQuMiIsIGFwcHJvcHJpYXRlU3BlY2lmaWMyLmVxdWFscyhzZWxlY3RlZFswXSkgfHwgYXBwcm9wcmlhdGVTcGVjaWZpYzIuZXF1YWxzKHNlbGVjdGVkWzFdKSk7CgkJYXNzZXJ0VHJ1ZSgiNC4zIiwgYXBwcm9wcmlhdGUuZXF1YWxzKHNlbGVjdGVkWzJdKSk7CgoJCS8vIGlmIGFwcHJvcHJpYXRlIGFuZCBhIG1vcmUgc3BlY2lmaWMgYXBwcm9wcmlhdGUgdHlwZSAoYnV0IHdpdGggbG93IHByaW9yaXR5KQoJCS8vIGFyZSBwcm92aWRlZCwgdGhlIHNwZWNpZmljIHR5cGUgd2lsbCBiZSBzZWxlY3RlZAoJCWZpbmRlciA9IGNvbnRlbnRUeXBlTWFuYWdlci5nZXRNYXRjaGVyKAoJCQkJbmV3IFN1YnNldFNlbGVjdGlvblBvbGljeShuZXcgSUNvbnRlbnRUeXBlW10geyBhcHByb3ByaWF0ZSwgYXBwcm9wcmlhdGVTcGVjaWZpYzFMb3dQcmlvcml0eSB9KSwgbnVsbCk7CgkJYXNzZXJ0RXF1YWxzKCI1LjAiLCBhcHByb3ByaWF0ZVNwZWNpZmljMUxvd1ByaW9yaXR5LAoJCQkJZmluZGVyLmZpbmRDb250ZW50VHlwZUZvcihnZXRJbnB1dFN0cmVhbShNSU5JTUFMX1hNTCksIG51bGwpKTsKCgkJLy8gaWYgYXBwcm9wcmlhdGUgYW5kIHR3byBzcGVjaWZpYyBhcHByb3ByaWF0ZSB0eXBlcyAoYnV0IG9uZSB3aXRoIGxvd2VyCgkJLy8gcHJpb3JpdHkpIGFyZSBwcm92aWRlZCwgdGhlIHNwZWNpZmljIHR5cGUgd2l0aCBoaWdoZXIgcHJpb3JpdHkgd2lsbCBiZQoJCS8vIHNlbGVjdGVkCgkJZmluZGVyID0gY29udGVudFR5cGVNYW5hZ2VyLmdldE1hdGNoZXIoCgkJCQluZXcgU3Vic2V0U2VsZWN0aW9uUG9saWN5KAoJCQkJCQluZXcgSUNvbnRlbnRUeXBlW10geyBhcHByb3ByaWF0ZSwgYXBwcm9wcmlhdGVTcGVjaWZpYzEsIGFwcHJvcHJpYXRlU3BlY2lmaWMxTG93UHJpb3JpdHkgfSksCgkJCQludWxsKTsKCQlhc3NlcnRFcXVhbHMoIjUuMSIsIGFwcHJvcHJpYXRlU3BlY2lmaWMxLCBmaW5kZXIuZmluZENvbnRlbnRUeXBlRm9yKGdldElucHV0U3RyZWFtKE1JTklNQUxfWE1MKSwgbnVsbCkpOwoJfQoKCUBUZXN0CglwdWJsaWMgdm9pZCB0ZXN0RGVmYXVsdFByb3BlcnRpZXMoKSB0aHJvd3MgSU9FeGNlcHRpb24gLyogbmV2ZXIgYWN0dWFsbHkgdGhyb3duICovIHsKCQlJQ29udGVudFR5cGVNYW5hZ2VyIGNvbnRlbnRUeXBlTWFuYWdlciA9IFBsYXRmb3JtLmdldENvbnRlbnRUeXBlTWFuYWdlcigpOwoKCQlJQ29udGVudFR5cGUgbXl0ZXh0ID0gY29udGVudFR5cGVNYW5hZ2VyLmdldENvbnRlbnRUeXBlKFBJX1JFU09VUkNFU19URVNUUyArICcuJyArICJteXRleHQiKTsKCQlJQ29udGVudFR5cGUgbXl0ZXh0MSA9IGNvbnRlbnRUeXBlTWFuYWdlci5nZXRDb250ZW50VHlwZShQSV9SRVNPVVJDRVNfVEVTVFMgKyAnLicgKyAibXl0ZXh0MSIpOwoJCUlDb250ZW50VHlwZSBteXRleHQyID0gY29udGVudFR5cGVNYW5hZ2VyLmdldENvbnRlbnRUeXBlKFBJX1JFU09VUkNFU19URVNUUyArICcuJyArICJteXRleHQyIik7CgkJYXNzZXJ0Tm90TnVsbCgiMC4xIiwgbXl0ZXh0KTsKCQlhc3NlcnROb3ROdWxsKCIwLjIiLCBteXRleHQxKTsKCQlhc3NlcnROb3ROdWxsKCIwLjMiLCBteXRleHQyKTsKCgkJUXVhbGlmaWVkTmFtZSBjaGFyc2V0ID0gSUNvbnRlbnREZXNjcmlwdGlvbi5DSEFSU0VUOwoJCVF1YWxpZmllZE5hbWUgbG9jYWxDaGFyc2V0ID0gbmV3IFF1YWxpZmllZE5hbWUoUElfUkVTT1VSQ0VTX1RFU1RTLCAiY2hhcnNldCIpOwoJCVF1YWxpZmllZE5hbWUgcHJvcGVydHkxID0gbmV3IFF1YWxpZmllZE5hbWUoUElfUkVTT1VSQ0VTX1RFU1RTLCAicHJvcGVydHkxIik7CgkJUXVhbGlmaWVkTmFtZSBwcm9wZXJ0eTIgPSBuZXcgUXVhbGlmaWVkTmFtZShQSV9SRVNPVVJDRVNfVEVTVFMsICJwcm9wZXJ0eTIiKTsKCQlRdWFsaWZpZWROYW1lIHByb3BlcnR5MyA9IG5ldyBRdWFsaWZpZWROYW1lKFBJX1JFU09VUkNFU19URVNUUywgInByb3BlcnR5MyIpOwoJCVF1YWxpZmllZE5hbWUgcHJvcGVydHk0ID0gbmV3IFF1YWxpZmllZE5hbWUoUElfUkVTT1VSQ0VTX1RFU1RTLCAicHJvcGVydHk0Iik7CgoJCUlDb250ZW50RGVzY3JpcHRpb24gZGVzY3JpcHRpb247CgkJSUNvbnRlbnRUeXBlTWF0Y2hlciBmaW5kZXIgPSBjb250ZW50VHlwZU1hbmFnZXIuZ2V0TWF0Y2hlcihuZXcgTG9jYWxTZWxlY3Rpb25Qb2xpY3koKSwgbnVsbCk7CgoJCWRlc2NyaXB0aW9uID0gZ2V0RGVzY3JpcHRpb25Gb3IoZmluZGVyLCAic29tZSBjb250ZW50cyIsIG51bGwsICJhYmMudHp0IiwgSUNvbnRlbnREZXNjcmlwdGlvbi5BTEwsIHRydWUpOwoJCWFzc2VydE5vdE51bGwoIjEuMCIsIGRlc2NyaXB0aW9uKTsKCQlhc3NlcnRFcXVhbHMoIjEuMSIsIG15dGV4dCwgZGVzY3JpcHRpb24uZ2V0Q29udGVudFR5cGUoKSk7CgkJYXNzZXJ0RXF1YWxzKCIxLjIiLCAidmFsdWUxIiwgZGVzY3JpcHRpb24uZ2V0UHJvcGVydHkocHJvcGVydHkxKSk7CgkJYXNzZXJ0TnVsbCgiMS4zIiwgZGVzY3JpcHRpb24uZ2V0UHJvcGVydHkocHJvcGVydHkyKSk7CgkJYXNzZXJ0RXF1YWxzKCIxLjQiLCAidmFsdWUzIiwgZGVzY3JpcHRpb24uZ2V0UHJvcGVydHkocHJvcGVydHkzKSk7CgkJYXNzZXJ0RXF1YWxzKCIxLjUiLCAiQkFSIiwgZGVzY3JpcHRpb24uZ2V0UHJvcGVydHkoY2hhcnNldCkpOwoKCQlkZXNjcmlwdGlvbiA9IGdldERlc2NyaXB0aW9uRm9yKGZpbmRlciwgInNvbWUgY29udGVudHMiLCBudWxsLCAiYWJjLnR6dDEiLCBJQ29udGVudERlc2NyaXB0aW9uLkFMTCwgdHJ1ZSk7CgkJYXNzZXJ0Tm90TnVsbCgiMi4wIiwgZGVzY3JpcHRpb24pOwoJCWFzc2VydEVxdWFscygiMi4xIiwgbXl0ZXh0MSwgZGVzY3JpcHRpb24uZ2V0Q29udGVudFR5cGUoKSk7CgkJYXNzZXJ0RXF1YWxzKCIyLjIiLCAidmFsdWUxIiwgZGVzY3JpcHRpb24uZ2V0UHJvcGVydHkocHJvcGVydHkxKSk7CgkJYXNzZXJ0RXF1YWxzKCIyLjMiLCAidmFsdWUyIiwgZGVzY3JpcHRpb24uZ2V0UHJvcGVydHkocHJvcGVydHkyKSk7CgkJYXNzZXJ0TnVsbCgiMi40IiwgZGVzY3JpcHRpb24uZ2V0UHJvcGVydHkocHJvcGVydHkzKSk7CgkJYXNzZXJ0RXF1YWxzKCIyLjUiLCAidmFsdWU0IiwgZGVzY3JpcHRpb24uZ2V0UHJvcGVydHkocHJvcGVydHk0KSk7CgkJYXNzZXJ0RXF1YWxzKCIyLjYiLCAiQkFSIiwgZGVzY3JpcHRpb24uZ2V0UHJvcGVydHkoY2hhcnNldCkpOwoKCQlkZXNjcmlwdGlvbiA9IGdldERlc2NyaXB0aW9uRm9yKGZpbmRlciwgInNvbWUgY29udGVudHMiLCBudWxsLCAiYWJjLnR6dDIiLCBJQ29udGVudERlc2NyaXB0aW9uLkFMTCwgdHJ1ZSk7CgkJYXNzZXJ0Tm90TnVsbCgiMy4wIiwgZGVzY3JpcHRpb24pOwoJCWFzc2VydEVxdWFscygiMy4xIiwgbXl0ZXh0MiwgZGVzY3JpcHRpb24uZ2V0Q29udGVudFR5cGUoKSk7CgkJYXNzZXJ0TnVsbCgiMy4yIiwgZGVzY3JpcHRpb24uZ2V0UHJvcGVydHkocHJvcGVydHkxKSk7CgkJYXNzZXJ0TnVsbCgiMy4zIiwgZGVzY3JpcHRpb24uZ2V0UHJvcGVydHkocHJvcGVydHkyKSk7CgkJYXNzZXJ0TnVsbCgiMy40IiwgZGVzY3JpcHRpb24uZ2V0UHJvcGVydHkocHJvcGVydHkzKSk7CgkJYXNzZXJ0TnVsbCgiMy41IiwgZGVzY3JpcHRpb24uZ2V0UHJvcGVydHkocHJvcGVydHk0KSk7CgkJYXNzZXJ0TnVsbCgiMy42IiwgZGVzY3JpcHRpb24uZ2V0UHJvcGVydHkoY2hhcnNldCkpOwoJCWFzc2VydEVxdWFscygiMy43IiwgIm15dGV4dDIiLCBkZXNjcmlwdGlvbi5nZXRQcm9wZXJ0eShsb2NhbENoYXJzZXQpKTsKCX0KCgkvKioKCSAqIFRoZSBmb29CYXIgY29udGVudCB0eXBlIGlzIGFzc29jaWF0ZWQgd2l0aCB0aGUgImZvby5iYXIiIGZpbGUgbmFtZSBhbmQgdGhlCgkgKiAiYmFyIiBmaWxlIGV4dGVuc2lvbiAod2hhdCBpcyBib2d1cywgYW55d2F5KS4gVGhpcyB0ZXN0IGVuc3VyZXMgaXQgZG9lcyBub3QKCSAqIGFwcGVhciB0d2ljZSBpbiB0aGUgbGlzdCBvZiBjb250ZW50IHR5cGVzIGFzc29jaWF0ZWQgd2l0aCB0aGUgImZvby5iYXIiIGZpbGUKCSAqIG5hbWUuCgkgKi8KCUBUZXN0CglwdWJsaWMgdm9pZCB0ZXN0RG91YmxlQXNzb2NpYXRpb24oKSB7CgkJSUNvbnRlbnRUeXBlTWFuYWdlciBjb250ZW50VHlwZU1hbmFnZXIgPSBQbGF0Zm9ybS5nZXRDb250ZW50VHlwZU1hbmFnZXIoKTsKCgkJSUNvbnRlbnRUeXBlIGZvb0JhclR5cGUgPSBjb250ZW50VHlwZU1hbmFnZXIuZ2V0Q29udGVudFR5cGUoUElfUkVTT1VSQ0VTX1RFU1RTICsgJy4nICsgImZvb0JhciIpOwoJCWFzc2VydE5vdE51bGwoIjEuMCIsIGZvb0JhclR5cGUpOwoJCUlDb250ZW50VHlwZSBzdWJGb29CYXJUeXBlID0gY29udGVudFR5cGVNYW5hZ2VyLmdldENvbnRlbnRUeXBlKFBJX1JFU09VUkNFU19URVNUUyArICcuJyArICJzdWJGb29CYXIiKTsKCQlhc3NlcnROb3ROdWxsKCIxLjEiLCBzdWJGb29CYXJUeXBlKTsKCQkvLyBlbnN1cmUgd2UgZG9uJ3QgZ2V0IGZvb0JhciB0d2ljZQoJCUlDb250ZW50VHlwZU1hdGNoZXIgZmluZGVyID0gY29udGVudFR5cGVNYW5hZ2VyLmdldE1hdGNoZXIobmV3IExvY2FsU2VsZWN0aW9uUG9saWN5KCksIG51bGwpOwoJCUlDb250ZW50VHlwZVtdIGZvb0JhckFzc29jaWF0ZWQgPSBmaW5kZXIuZmluZENvbnRlbnRUeXBlc0ZvcihjaGFuZ2VDYXNlKCJmb28uYmFyIikpOwoJCWFzc2VydEVxdWFscygiMi4xIiwgMiwgZm9vQmFyQXNzb2NpYXRlZC5sZW5ndGgpOwoJCWFzc2VydFRydWUoIjIuMiIsIGNvbnRhaW5zKGZvb0JhckFzc29jaWF0ZWQsIGZvb0JhclR5cGUpKTsKCQlhc3NlcnRUcnVlKCIyLjMiLCBjb250YWlucyhmb29CYXJBc3NvY2lhdGVkLCBzdWJGb29CYXJUeXBlKSk7Cgl9CgoJLyoqCgkgKiBPYnRhaW5zIGEgcmVmZXJlbmNlIHRvIGEga25vd24gY29udGVudCB0eXBlLCB0aGVuIGluc3RhbGxzIGEgYnVuZGxlIHRoYXQKCSAqIGNvbnRyaWJ1dGVzIGEgY29udGVudCB0eXBlLCBhbmQgbWFrZXMgc3VyZSBhIG5ldyBvYnRhaW5lZCByZWZlcmVuY2UgdG8gdGhlCgkgKiBzYW1lIGNvbnRlbnQgdHlwZSBpcyBub3QgaWRlbnRpY2FsIChzaG93cyB0aGF0IHRoZSBjb250ZW50IHR5cGUgY2F0YWxvZyBoYXMKCSAqIGJlZW4gZGlzY2FyZGVkIGFuZCByZWJ1aWx0KS4gVGhlbiB1bmluc3RhbGxzIHRoYXQgYnVuZGxlIGFuZCBjaGVja3MgYWdhaW4gdGhlCgkgKiBzYW1lIHRoaW5nIChiZWNhdXNlIHRoZSBjb250ZW50IHR5cGUgY2F0YWxvZyBzaG91bGQgYmUgcmVidWlsdCB3aGVuZXZlcgoJICogY29udGVudCB0eXBlcyBhcmUgZHluYW1pY2FseSBhZGRlZC9yZW1vdmVkKS4KCSAqLwoJQFRlc3QKCXB1YmxpYyB2b2lkIHRlc3REeW5hbWljQ2hhbmdlcygpIHsKCQlmaW5hbCBJQ29udGVudFR5cGVbXSB0ZXh0ID0gbmV3IElDb250ZW50VHlwZVs0XTsKCQlmaW5hbCBJQ29udGVudFR5cGVNYW5hZ2VyIG1hbmFnZXIgPSBQbGF0Zm9ybS5nZXRDb250ZW50VHlwZU1hbmFnZXIoKTsKCQl0ZXh0WzBdID0gbWFuYWdlci5nZXRDb250ZW50VHlwZShJQ29udGVudFR5cGVNYW5hZ2VyLkNUX1RFWFQpOwoJCWFzc2VydE5vdE51bGwoIjEuMCIsIHRleHRbMF0pOwoJCXRleHRbMV0gPSBtYW5hZ2VyLmdldENvbnRlbnRUeXBlKElDb250ZW50VHlwZU1hbmFnZXIuQ1RfVEVYVCk7CgkJYXNzZXJ0Tm90TnVsbCgiMS4xIiwgdGV4dFsxXSk7CgkJdGV4dFswXSA9ICgoQ29udGVudFR5cGVIYW5kbGVyKSB0ZXh0WzBdKS5nZXRUYXJnZXQoKTsKCQl0ZXh0WzFdID0gKChDb250ZW50VHlwZUhhbmRsZXIpIHRleHRbMV0pLmdldFRhcmdldCgpOwoJCWFzc2VydEVxdWFscygiMi4wIiwgdGV4dFswXSwgdGV4dFsxXSk7CgkJYXNzZXJ0RXF1YWxzKCIyLjEiLCB0ZXh0WzBdLCB0ZXh0WzFdKTsKCQkvLyBtYWtlIGFyYml0cmFyeSBkeW5hbWljIGNoYW5nZXMgdG8gdGhlIGNvbnRlbnRUeXBlcyBleHRlbnNpb24gcG9pbnQKCQlUZXN0UmVnaXN0cnlDaGFuZ2VMaXN0ZW5lciBsaXN0ZW5lciA9IG5ldyBUZXN0UmVnaXN0cnlDaGFuZ2VMaXN0ZW5lcihQbGF0Zm9ybS5QSV9SVU5USU1FLAoJCQkJQ29udGVudFR5cGVCdWlsZGVyLlBUX0NPTlRFTlRUWVBFUywgbnVsbCwgbnVsbCk7CgkJQnVuZGxlVGVzdGluZ0hlbHBlci5ydW5XaXRoQnVuZGxlcygiMyIsICgpIC0+IHsKCQkJSUNvbnRlbnRUeXBlIG1pc3NpbmcgPSBtYW5hZ2VyLmdldENvbnRlbnRUeXBlKCJvcmcuZWNsaXBzZS5idW5kbGUwMS5taXNzaW5nIik7CgkJCWFzc2VydE5vdE51bGwoIjMuMSIsIG1pc3NpbmcpOwoJCQkvLyBlbnN1cmUgdGhlIGNvbnRlbnQgdHlwZSBpbnN0YW5jZXMgYXJlIGRpZmZlcmVudAoJCQl0ZXh0WzJdID0gbWFuYWdlci5nZXRDb250ZW50VHlwZShJQ29udGVudFR5cGVNYW5hZ2VyLkNUX1RFWFQpOwoJCQlhc3NlcnROb3ROdWxsKCIzLjIiLCB0ZXh0WzJdKTsKCQkJdGV4dFsyXSA9ICgoQ29udGVudFR5cGVIYW5kbGVyKSB0ZXh0WzJdKS5nZXRUYXJnZXQoKTsKCQkJYXNzZXJ0RXF1YWxzKCIzLjMiLCB0ZXh0WzBdLCB0ZXh0WzJdKTsKCQkJYXNzZXJ0Tm90U2FtZSgiMy40IiwgdGV4dFswXSwgdGV4dFsyXSk7CgkJfSwgZ2V0Q29udGV4dCgpLCBuZXcgU3RyaW5nW10geyBDb250ZW50VHlwZVRlc3QuVEVTVF9GSUxFU19ST09UICsgImNvbnRlbnQvYnVuZGxlMDEiIH0sIGxpc3RlbmVyKTsKCQlhc3NlcnROdWxsKCI0LjAiLCBtYW5hZ2VyLmdldENvbnRlbnRUeXBlKCJvcmcuZWNsaXBzZS5idW5kbGUwMS5taXNzaW5nIikpOwoJCS8vIGVuc3VyZSB0aGUgY29udGVudCB0eXBlIGluc3RhbmNlcyBhcmUgYWxsIGRpZmZlcmVudAoJCXRleHRbM10gPSBtYW5hZ2VyLmdldENvbnRlbnRUeXBlKElDb250ZW50VHlwZU1hbmFnZXIuQ1RfVEVYVCk7CgkJYXNzZXJ0Tm90TnVsbCgiNS4wIiwgdGV4dFszXSk7CgkJdGV4dFszXSA9ICgoQ29udGVudFR5cGVIYW5kbGVyKSB0ZXh0WzNdKS5nZXRUYXJnZXQoKTsKCQlhc3NlcnRFcXVhbHMoIjUuMSIsIHRleHRbMF0sIHRleHRbM10pOwoJCWFzc2VydEVxdWFscygiNS4yIiwgdGV4dFsyXSwgdGV4dFszXSk7CgkJYXNzZXJ0Tm90U2FtZSgiNS4zIiwgdGV4dFswXSwgdGV4dFszXSk7CgkJYXNzZXJ0Tm90U2FtZSgiNS40IiwgdGV4dFsyXSwgdGV4dFszXSk7Cgl9CgoJLyoqCgkgKiBTaW1pbGFyIHRvIHRlc3REeW5hbWljQ2hhbmdlcywgYnV0IHVzaW5nIHRoZQoJICogb3JnLmVjbGlwc2UuY29yZS5jb250ZW50dHlwZS5jb250ZW50VHlwZXMgZXh0ZW5zaW9uIHBvaW50LgoJICovCglAVGVzdAoJcHVibGljIHZvaWQgdGVzdER5bmFtaWNDaGFuZ2VzTmV3RXh0ZW5zaW9uKCkgewoJCWZpbmFsIElDb250ZW50VHlwZVtdIHRleHQgPSBuZXcgSUNvbnRlbnRUeXBlWzRdOwoJCWZpbmFsIElDb250ZW50VHlwZU1hbmFnZXIgbWFuYWdlciA9IFBsYXRmb3JtLmdldENvbnRlbnRUeXBlTWFuYWdlcigpOwoJCXRleHRbMF0gPSBtYW5hZ2VyLmdldENvbnRlbnRUeXBlKElDb250ZW50VHlwZU1hbmFnZXIuQ1RfVEVYVCk7CgkJYXNzZXJ0Tm90TnVsbCgiMS4wIiwgdGV4dFswXSk7CgkJdGV4dFsxXSA9IG1hbmFnZXIuZ2V0Q29udGVudFR5cGUoSUNvbnRlbnRUeXBlTWFuYWdlci5DVF9URVhUKTsKCQlhc3NlcnROb3ROdWxsKCIxLjEiLCB0ZXh0WzFdKTsKCQl0ZXh0WzBdID0gKChDb250ZW50VHlwZUhhbmRsZXIpIHRleHRbMF0pLmdldFRhcmdldCgpOwoJCXRleHRbMV0gPSAoKENvbnRlbnRUeXBlSGFuZGxlcikgdGV4dFsxXSkuZ2V0VGFyZ2V0KCk7CgkJYXNzZXJ0RXF1YWxzKCIyLjAiLCB0ZXh0WzBdLCB0ZXh0WzFdKTsKCQlhc3NlcnRTYW1lKCIyLjEiLCB0ZXh0WzBdLCB0ZXh0WzFdKTsKCQkvLyBtYWtlIGFyYml0cmFyeSBkeW5hbWljIGNoYW5nZXMgdG8gdGhlIGNvbnRlbnRUeXBlcyBleHRlbnNpb24gcG9pbnQKCQlUZXN0UmVnaXN0cnlDaGFuZ2VMaXN0ZW5lciBsaXN0ZW5lciA9IG5ldyBUZXN0UmVnaXN0cnlDaGFuZ2VMaXN0ZW5lcihJQ29udGVudENvbnN0YW50cy5DT05URU5UX05BTUUsCgkJCQlDb250ZW50VHlwZUJ1aWxkZXIuUFRfQ09OVEVOVFRZUEVTLCBudWxsLCBudWxsKTsKCQlCdW5kbGVUZXN0aW5nSGVscGVyLnJ1bldpdGhCdW5kbGVzKCIzIiwgKCkgLT4gewoJCQlJQ29udGVudFR5cGUgY29udGVudFR5cGUgPSBtYW5hZ2VyLmdldENvbnRlbnRUeXBlKCJvcmcuZWNsaXBzZS5idWc0ODUyMjcuYnVnNDg1MjI3X2NvbnRlbnRUeXBlIik7CgkJCWFzc2VydE5vdE51bGwoIjMuMSBDb250cmlidXRlZCBjb250ZW50IHR5cGUgbm90IGZvdW5kIiwgY29udGVudFR5cGUpOwoJCQkvLyBlbnN1cmUgdGhlIGNvbnRlbnQgdHlwZSBpbnN0YW5jZXMgYXJlIGRpZmZlcmVudAoJCQl0ZXh0WzJdID0gbWFuYWdlci5nZXRDb250ZW50VHlwZShJQ29udGVudFR5cGVNYW5hZ2VyLkNUX1RFWFQpOwoJCQlhc3NlcnROb3ROdWxsKCIzLjIgVGV4dCBjb250ZW50IHR5cGUgbm90IG1vZGlmaWVkIiwgdGV4dFsyXSk7CgkJCXRleHRbMl0gPSAoKENvbnRlbnRUeXBlSGFuZGxlcikgdGV4dFsyXSkuZ2V0VGFyZ2V0KCk7CgkJCWFzc2VydEVxdWFscygiMy4zIiwgdGV4dFswXSwgdGV4dFsyXSk7CgkJCWFzc2VydE5vdFNhbWUoIjMuNCIsIHRleHRbMF0sIHRleHRbMl0pOwoJCQlhc3NlcnRFcXVhbHMoIjMuNSBkZWZhdWx0IGV4dGVuc2lvbiBub3QgYXNzb2NpYXRlZCIsIGNvbnRlbnRUeXBlLAoJCQkJCW1hbmFnZXIuZmluZENvbnRlbnRUeXBlRm9yKCJmaWxlLmJ1ZzQ4NTIyNyIpKTsKCQkJYXNzZXJ0RXF1YWxzKCIzLjYgYWRkaXRpb25hbCBleHRlbnNpb24gbm90IGFzc29jaWF0ZWQiLCBjb250ZW50VHlwZSwKCQkJCQltYW5hZ2VyLmZpbmRDb250ZW50VHlwZUZvcigiZmlsZS5idWc0ODUyMjdfMiIpKTsKCQl9LCBnZXRDb250ZXh0KCksIG5ldyBTdHJpbmdbXSB7IENvbnRlbnRUeXBlVGVzdC5URVNUX0ZJTEVTX1JPT1QgKyAiY29udGVudC9idWc0ODUyMjciIH0sIGxpc3RlbmVyKTsKCQlhc3NlcnROdWxsKCI0LjAgQ29udGVudCB0eXBlIG5vdCBjbGVhcmVkIGFmdGVyIGJ1bmRsZSB1bmluc3RhbGwiLAoJCQkJbWFuYWdlci5nZXRDb250ZW50VHlwZSgib3JnLmVjbGlwc2UuYnVnNDg1MjI3LmJ1ZzQ4NTIyN19jb250ZW50VHlwZSIpKTsKCQkvLyBlbnN1cmUgdGhlIGNvbnRlbnQgdHlwZSBpbnN0YW5jZXMgYXJlIGFsbCBkaWZmZXJlbnQKCQl0ZXh0WzNdID0gbWFuYWdlci5nZXRDb250ZW50VHlwZShJQ29udGVudFR5cGVNYW5hZ2VyLkNUX1RFWFQpOwoJCWFzc2VydE5vdE51bGwoIjUuMCIsIHRleHRbM10pOwoJCXRleHRbM10gPSAoKENvbnRlbnRUeXBlSGFuZGxlcikgdGV4dFszXSkuZ2V0VGFyZ2V0KCk7CgkJYXNzZXJ0RXF1YWxzKCI1LjEiLCB0ZXh0WzBdLCB0ZXh0WzNdKTsKCQlhc3NlcnRFcXVhbHMoIjUuMiIsIHRleHRbMl0sIHRleHRbM10pOwoJCWFzc2VydE5vdFNhbWUoIjUuMyIsIHRleHRbMF0sIHRleHRbM10pOwoJCWFzc2VydE5vdFNhbWUoIjUuNCIsIHRleHRbMl0sIHRleHRbM10pOwoJfQoKCUBUZXN0CglwdWJsaWMgdm9pZCB0ZXN0RXZlbnRzKCkgdGhyb3dzIENvcmVFeGNlcHRpb24gewoJCUlDb250ZW50VHlwZU1hbmFnZXIgY29udGVudFR5cGVNYW5hZ2VyID0gUGxhdGZvcm0uZ2V0Q29udGVudFR5cGVNYW5hZ2VyKCk7CgkJSUNvbnRlbnRUeXBlIG15VHlwZSA9IGNvbnRlbnRUeXBlTWFuYWdlci5nZXRDb250ZW50VHlwZShQSV9SRVNPVVJDRVNfVEVTVFMgKyAiLm15Q29udGVudCIpOwoJCWFzc2VydE5vdE51bGwoIjAuOSIsIG15VHlwZSk7CgoJCUNvbnRlbnRUeXBlQ2hhbmdlVHJhY2VyIHRyYWNlcjsKCgkJdHJhY2VyID0gbmV3IENvbnRlbnRUeXBlQ2hhbmdlVHJhY2VyKCk7CgkJY29udGVudFR5cGVNYW5hZ2VyLmFkZENvbnRlbnRUeXBlQ2hhbmdlTGlzdGVuZXIodHJhY2VyKTsKCgkJLy8gYWRkIGEgZmlsZSBzcGVjIGFuZCBjaGVjayBldmVudAoJCW15VHlwZS5hZGRGaWxlU3BlYygiYW5vdGhlci5maWxlLm5hbWUiLCBJQ29udGVudFR5cGUuRklMRV9OQU1FX1NQRUMpOwoJCWFzc2VydFRydWUoIjEuMSIsIHRyYWNlci5pc09ubHlDaGFuZ2UobXlUeXBlKSk7CgoJCS8vIHJlbW92ZSBhIG5vbi1leGlzdGluZyBmaWxlIHNwZWMgLSBzaG91bGQgbm90IGNhdXNlIGFuIGV2ZW50IHRvIGJlIGZpcmVkCgkJdHJhY2VyLnJlc2V0KCk7CgkJbXlUeXBlLnJlbW92ZUZpbGVTcGVjKCJhbm90aGVyLmZpbGUubmFtZSIsIElDb250ZW50VHlwZS5GSUxFX0VYVEVOU0lPTl9TUEVDKTsKCQlhc3NlcnRUcnVlKCIyLjEiLCAhdHJhY2VyLmlzT25seUNoYW5nZShteVR5cGUpKTsKCgkJLy8gYWRkIGEgZmlsZSBzcGVjIGFnYWluIGFuZCBjaGVjayBubyBldmVudCBpcyBnZW5lcmF0ZWQKCQl0cmFjZXIucmVzZXQoKTsKCQlteVR5cGUuYWRkRmlsZVNwZWMoImFub3RoZXIuZmlsZS5uYW1lIiwgSUNvbnRlbnRUeXBlLkZJTEVfTkFNRV9TUEVDKTsKCQlhc3NlcnRUcnVlKCIzLjEiLCAhdHJhY2VyLmlzT25seUNoYW5nZShteVR5cGUpKTsKCgkJLy8gcmVtb3ZlIGEgZmlsZSBzcGVjIGFuZCBjaGVjayBldmVudAoJCXRyYWNlci5yZXNldCgpOwoJCW15VHlwZS5yZW1vdmVGaWxlU3BlYygiYW5vdGhlci5maWxlLm5hbWUiLCBJQ29udGVudFR5cGUuRklMRV9OQU1FX1NQRUMpOwoJCWFzc2VydFRydWUoIjQuMSIsIHRyYWNlci5pc09ubHlDaGFuZ2UobXlUeXBlKSk7CgoJCS8vIGNoYW5nZSB0aGUgZGVmYXVsdCBjaGFyc2V0IGFuZCBjaGVjayBldmVudAoJCXRyYWNlci5yZXNldCgpOwoJCW15VHlwZS5zZXREZWZhdWx0Q2hhcnNldCgiRk9PIik7CgkJYXNzZXJ0VHJ1ZSgiNS4xIiwgdHJhY2VyLmlzT25seUNoYW5nZShteVR5cGUpKTsKCgkJLy8gc2V0IHRoZSBkZWZhdWx0IGNoYXJzZXQgdG8gdGhlIHNhbWUgLSBubyBldmVudCBzaG91bGQgYmUgZ2VuZXJhdGVkCgkJdHJhY2VyLnJlc2V0KCk7CgkJbXlUeXBlLnNldERlZmF1bHRDaGFyc2V0KCJGT08iKTsKCQlhc3NlcnRUcnVlKCI2LjEiLCAhdHJhY2VyLmlzT25seUNoYW5nZShteVR5cGUpKTsKCgkJbXlUeXBlLnNldERlZmF1bHRDaGFyc2V0KCJBQkMiKTsKCX0KCglAVGVzdAoJcHVibGljIHZvaWQgdGVzdEZpbGVTcGVjQ29uZmxpY3RzKCkgdGhyb3dzIElPRXhjZXB0aW9uIHsKCQlJQ29udGVudFR5cGVNYW5hZ2VyIG1hbmFnZXIgPSBQbGF0Zm9ybS5nZXRDb250ZW50VHlwZU1hbmFnZXIoKTsKCQkvLyB3aGVuIG5vdCBzdWJtaXR0aW5nIGNvbnRlbnRzLCBmb3IgcmVsYXRlZCB0eXBlcywgbW9zdCBnZW5lcmFsIHR5cGUgcHJldmFpbHMKCQlJQ29udGVudFR5cGUgY29uZmxpY3QxYSA9IG1hbmFnZXIuZ2V0Q29udGVudFR5cGUoUElfUkVTT1VSQ0VTX1RFU1RTICsgIi5iYXNlX2NvbmZsaWN0MSIpOwoJCUlDb250ZW50VHlwZSBjb25mbGljdDFiID0gbWFuYWdlci5nZXRDb250ZW50VHlwZShQSV9SRVNPVVJDRVNfVEVTVFMgKyAiLnN1Yl9jb25mbGljdDEiKTsKCQlhc3NlcnROb3ROdWxsKCIxLjAiLCBjb25mbGljdDFhKTsKCQlhc3NlcnROb3ROdWxsKCIxLjEiLCBjb25mbGljdDFiKTsKCQlJQ29udGVudFR5cGUgcHJlZmVycmVkQ29uZmxpY3QxID0gbWFuYWdlci5maW5kQ29udGVudFR5cGVGb3IoInRlc3QuY29uZmxpY3QxIik7CgkJYXNzZXJ0Tm90TnVsbCgiMS4yIiwgcHJlZmVycmVkQ29uZmxpY3QxKTsKCQlhc3NlcnRFcXVhbHMoIjEuMyIsIGNvbmZsaWN0MWEsIHByZWZlcnJlZENvbmZsaWN0MSk7CgoJCUlDb250ZW50VHlwZSBjb25mbGljdDJiYXNlID0gbWFuYWdlci5nZXRDb250ZW50VHlwZShQSV9SRVNPVVJDRVNfVEVTVFMgKyAiLmJhc2VfY29uZmxpY3QyIik7CgkJSUNvbnRlbnRUeXBlIGNvbmZsaWN0MnN1YiA9IG1hbmFnZXIuZ2V0Q29udGVudFR5cGUoUElfUkVTT1VSQ0VTX1RFU1RTICsgIi5zdWJfY29uZmxpY3QyIik7CgkJYXNzZXJ0Tm90TnVsbCgiMi4wIiwgY29uZmxpY3QyYmFzZSk7CgkJYXNzZXJ0Tm90TnVsbCgiMi4xIiwgY29uZmxpY3Qyc3ViKTsKCQkvLyB3aGVuIHN1Ym1pdHRpbmcgY29udGVudHMsIGZvciByZWxhdGVkIHR5cGVzLCBkZXNjZW5kYW50IGNvbWVzIGZpcnN0CgoJCUlDb250ZW50VHlwZVtdIHNlbGVjdGVkQ29uZmxpY3QyID0gbWFuYWdlci5maW5kQ29udGVudFR5cGVzRm9yKGdldFJhbmRvbUNvbnRlbnRzKCksICJ0ZXN0LmNvbmZsaWN0MiIpOwoJCWFzc2VydEVxdWFscygiMi4yIiwgMiwgc2VsZWN0ZWRDb25mbGljdDIubGVuZ3RoKTsKCQlhc3NlcnRFcXVhbHMoIjIuMyIsIHNlbGVjdGVkQ29uZmxpY3QyWzBdLCBjb25mbGljdDJiYXNlKTsKCQlhc3NlcnRFcXVhbHMoIjIuNCIsIHNlbGVjdGVkQ29uZmxpY3QyWzFdLCBjb25mbGljdDJzdWIpOwoKCQlJQ29udGVudFR5cGUgY29uZmxpY3QzYmFzZSA9IG1hbmFnZXIuZ2V0Q29udGVudFR5cGUoUElfUkVTT1VSQ0VTX1RFU1RTICsgIi5iYXNlX2NvbmZsaWN0MyIpOwoJCUlDb250ZW50VHlwZSBjb25mbGljdDNzdWIgPSBtYW5hZ2VyLmdldENvbnRlbnRUeXBlKFBJX1JFU09VUkNFU19URVNUUyArICIuc3ViX2NvbmZsaWN0MyIpOwoJCUlDb250ZW50VHlwZSBjb25mbGljdDN1bnJlbGF0ZWQgPSBtYW5hZ2VyLmdldENvbnRlbnRUeXBlKFBJX1JFU09VUkNFU19URVNUUyArICIudW5yZWxhdGVkX2NvbmZsaWN0MyIpOwoJCWFzc2VydE5vdE51bGwoIjMuMC4xIiwgY29uZmxpY3QzYmFzZSk7CgkJYXNzZXJ0Tm90TnVsbCgiMy4wLjIiLCBjb25mbGljdDNzdWIpOwoJCWFzc2VydE5vdE51bGwoIjMuMC4zIiwgY29uZmxpY3QzdW5yZWxhdGVkKTsKCgkJLy8gVHdvIHVucmVsYXRlZCB0eXBlcyAoc3ViX2NvbmZsaWN0MyBhbmQgdW5yZWxhdGVkIGNvbmZsaWN0MykgYXJlIGluIGNvbmZsaWN0LgoJCS8vIE9yZGVyIHdpbGwgYmUgYmFzZWQgb24gZGVwdGggKG1vcmUgZ2VuZXJhbCBmaXJzdCBzaW5jZSB0aGV5IGRvbid0IGhhdmUKCQkvLyBkZXNjcmliZXJzKQoKCQlJQ29udGVudFR5cGVbXSBzZWxlY3RlZENvbmZsaWN0MyA9IG1hbmFnZXIuZmluZENvbnRlbnRUeXBlc0ZvcihnZXRSYW5kb21Db250ZW50cygpLCAidGVzdC5jb25mbGljdDMiKTsKCQlhc3NlcnRFcXVhbHMoIjQuMCIsIDIsIHNlbGVjdGVkQ29uZmxpY3QzLmxlbmd0aCk7CgkJYXNzZXJ0RXF1YWxzKCI0LjEiLCBzZWxlY3RlZENvbmZsaWN0M1swXSwgY29uZmxpY3QzdW5yZWxhdGVkKTsKCQlhc3NlcnRFcXVhbHMoIjQuMiIsIHNlbGVjdGVkQ29uZmxpY3QzWzFdLCBjb25mbGljdDNzdWIpOwoJfQoKCUBUZXN0CglwdWJsaWMgdm9pZCB0ZXN0RmluZENvbnRlbnRUeXBlKCkgdGhyb3dzIElPRXhjZXB0aW9uIHsKCQlJQ29udGVudFR5cGVNYW5hZ2VyIGNvbnRlbnRUeXBlTWFuYWdlciA9IFBsYXRmb3JtLmdldENvbnRlbnRUeXBlTWFuYWdlcigpOwoJCUlDb250ZW50VHlwZU1hdGNoZXIgZmluZGVyID0gY29udGVudFR5cGVNYW5hZ2VyLmdldE1hdGNoZXIobmV3IExvY2FsU2VsZWN0aW9uUG9saWN5KCksIG51bGwpOwoKCQlJQ29udGVudFR5cGUgdGV4dENvbnRlbnRUeXBlID0gY29udGVudFR5cGVNYW5hZ2VyLmdldENvbnRlbnRUeXBlKFBsYXRmb3JtLlBJX1JVTlRJTUUgKyAnLicgKyAidGV4dCIpOwoJCUlDb250ZW50VHlwZSB4bWxDb250ZW50VHlwZSA9IGNvbnRlbnRUeXBlTWFuYWdlci5nZXRDb250ZW50VHlwZShQbGF0Zm9ybS5QSV9SVU5USU1FICsgIi54bWwiKTsKCgkJSUNvbnRlbnRUeXBlIHNpbmdsZTsKCgkJc2luZ2xlID0gZmluZGVyLmZpbmRDb250ZW50VHlwZUZvcihnZXRJbnB1dFN0cmVhbSgiSnVzdCBhIHRlc3QiKSwgY2hhbmdlQ2FzZSgiZmlsZS50eHQiKSk7CgkJYXNzZXJ0Tm90TnVsbCgiMS4wIiwgc2luZ2xlKTsKCQlhc3NlcnRFcXVhbHMoIjEuMSIsIHRleHRDb250ZW50VHlwZSwgc2luZ2xlKTsKCgkJc2luZ2xlID0gZmluZGVyLmZpbmRDb250ZW50VHlwZUZvcihnZXRJbnB1dFN0cmVhbShYTUxfVVRGXzgsIFN0YW5kYXJkQ2hhcnNldHMuVVRGXzgpLCBjaGFuZ2VDYXNlKCJmb28ueG1sIikpOwoJCWFzc2VydE5vdE51bGwoIjIuMCIsIHNpbmdsZSk7CgkJYXNzZXJ0RXF1YWxzKCIyLjEiLCB4bWxDb250ZW50VHlwZSwgc2luZ2xlKTsKCgkJSUNvbnRlbnRUeXBlW10gbXVsdGlwbGUgPSBmaW5kZXIuZmluZENvbnRlbnRUeXBlc0ZvcihnZXRJbnB1dFN0cmVhbShYTUxfVVRGXzgsIFN0YW5kYXJkQ2hhcnNldHMuVVRGXzgpLCBudWxsKTsKCQlhc3NlcnRUcnVlKCIzLjAiLCBjb250YWlucyhtdWx0aXBsZSwgeG1sQ29udGVudFR5cGUpKTsKCX0KCglAVGVzdAoJcHVibGljIHZvaWQgdGVzdEZpbmRDb250ZW50VHlwUHJlZGVmaW5lZFJlZ2V4cCgpIHRocm93cyBJT0V4Y2VwdGlvbiwgQ29yZUV4Y2VwdGlvbiB7CgkJSUNvbnRlbnRUeXBlTWFuYWdlciBjb250ZW50VHlwZU1hbmFnZXIgPSBQbGF0Zm9ybS5nZXRDb250ZW50VHlwZU1hbmFnZXIoKTsKCQlJQ29udGVudFR5cGVNYXRjaGVyIGZpbmRlciA9IGNvbnRlbnRUeXBlTWFuYWdlci5nZXRNYXRjaGVyKG5ldyBMb2NhbFNlbGVjdGlvblBvbGljeSgpLCBudWxsKTsKCgkJSUNvbnRlbnRUeXBlIHRhcmdldENvbnRlbnRUeXBlID0gY29udGVudFR5cGVNYW5hZ2VyCgkJCQkuZ2V0Q29udGVudFR5cGUoIm9yZy5lY2xpcHNlLmNvcmUudGVzdHMucmVzb3VyY2VzLnByZWRlZmluZWRDb250ZW50VHlwZVdpdGhSZWdleHAiKTsKCQlhc3NlcnROb3ROdWxsKCJUYXJnZXQgY29udGVudC10eXBlIG5vdCBmb3VuZCIsIHRhcmdldENvbnRlbnRUeXBlKTsKCgkJSUNvbnRlbnRUeXBlIHNpbmdsZSA9IGZpbmRlci5maW5kQ29udGVudFR5cGVGb3IoZ2V0SW5wdXRTdHJlYW0oIkp1c3QgYSB0ZXN0IiksCgkJCQkic29tZXByZWRlZmluZWRDb250ZW50VHlwZVdpdGhSZWdleHBGaWxlIik7CgkJYXNzZXJ0RXF1YWxzKHRhcmdldENvbnRlbnRUeXBlLCBzaW5nbGUpOwoJCXNpbmdsZSA9IGZpbmRlci5maW5kQ29udGVudFR5cGVGb3IoZ2V0SW5wdXRTdHJlYW0oIkp1c3QgYSB0ZXN0IiksICJzb21lcHJlZGVmaW5lZENvbnRlbnRUeXBlV2l0aFBhdHRlcm5GaWxlIik7CgkJYXNzZXJ0RXF1YWxzKHRhcmdldENvbnRlbnRUeXBlLCBzaW5nbGUpOwoJCXNpbmdsZSA9IGZpbmRlci5maW5kQ29udGVudFR5cGVGb3IoZ2V0SW5wdXRTdHJlYW0oIkp1c3QgYSB0ZXN0IiksICJzb21lcHJlZGVmaW5lZENvbnRlbnRUeXBlV2l0aFdpbGRjYXJkc0ZpbGUiKTsKCQlhc3NlcnRFcXVhbHModGFyZ2V0Q29udGVudFR5cGUsIHNpbmdsZSk7Cgl9CgoJQFRlc3QKCXB1YmxpYyB2b2lkIHRlc3RGaW5kQ29udGVudFR5cGVVc2VyUmVnZXhwKCkgdGhyb3dzIElPRXhjZXB0aW9uLCBDb3JlRXhjZXB0aW9uIHsKCQlJQ29udGVudFR5cGVNYW5hZ2VyIGNvbnRlbnRUeXBlTWFuYWdlciA9IFBsYXRmb3JtLmdldENvbnRlbnRUeXBlTWFuYWdlcigpOwoJCUlDb250ZW50VHlwZU1hdGNoZXIgZmluZGVyID0gY29udGVudFR5cGVNYW5hZ2VyLmdldE1hdGNoZXIobmV3IExvY2FsU2VsZWN0aW9uUG9saWN5KCksIG51bGwpOwoKCQlJQ29udGVudFR5cGUgdGV4dENvbnRlbnRUeXBlID0gY29udGVudFR5cGVNYW5hZ2VyLmdldENvbnRlbnRUeXBlKFBsYXRmb3JtLlBJX1JVTlRJTUUgKyAnLicgKyAidGV4dCIpOwoKCQlJQ29udGVudFR5cGUgc2luZ2xlID0gZmluZGVyLmZpbmRDb250ZW50VHlwZUZvcihnZXRJbnB1dFN0cmVhbSgiSnVzdCBhIHRlc3QiKSwgInNvbWVUZXh0LnVua25vd24iKTsKCQlhc3NlcnROdWxsKCJGaWxlIHBhdHRlcm4gdW5rbm93biBhdCB0aGF0IHBvaW50Iiwgc2luZ2xlKTsKCgkJdGV4dENvbnRlbnRUeXBlLmFkZEZpbGVTcGVjKCIqVGV4dCoiLCBJQ29udGVudFR5cGUuRklMRV9QQVRURVJOX1NQRUMpOwoJCXNpbmdsZSA9IGZpbmRlci5maW5kQ29udGVudFR5cGVGb3IoZ2V0SW5wdXRTdHJlYW0oIkp1c3QgYSB0ZXN0IiksICJzb21lVGV4dC51bmtub3duIik7CgkJYXNzZXJ0RXF1YWxzKCJUZXh0IGNvbnRlbnQgc2hvdWxkIG5vdyBtYXRjaCAqVGV4dCogZmlsZXMiLCB0ZXh0Q29udGVudFR5cGUsIHNpbmdsZSk7Cgl9CgoJQFRlc3QKCXB1YmxpYyB2b2lkIHRlc3RJbXBvcnRGaWxlQXNzb2NpYXRpb24oKSB0aHJvd3MgQ29yZUV4Y2VwdGlvbiB7CgkJSUNvbnRlbnRUeXBlTWFuYWdlciBjb250ZW50VHlwZU1hbmFnZXIgPSBQbGF0Zm9ybS5nZXRDb250ZW50VHlwZU1hbmFnZXIoKTsKCQlhc3NlcnROdWxsKGNvbnRlbnRUeXBlTWFuYWdlci5maW5kQ29udGVudFR5cGVGb3IoIiouYnVnMTIyMjE3IikpOwoJCUlQcmVmZXJlbmNlc1NlcnZpY2Ugc2VydmljZSA9IFBsYXRmb3JtLmdldFByZWZlcmVuY2VzU2VydmljZSgpOwoJCVN0cmluZyBwcmVmcyA9ICJmaWxlX2V4cG9ydF92ZXJzaW9uPTMuMFxuL2luc3RhbmNlL29yZy5lY2xpcHNlLmNvcmUucnVudGltZS9jb250ZW50LXR5cGVzL29yZy5lY2xpcHNlLmNvcmUucnVudGltZS54bWwvZmlsZS1leHRlbnNpb25zPWJ1ZzEyMjIxNyI7CgkJSUV4cG9ydGVkUHJlZmVyZW5jZXMgZXhwb3J0ZWQgPSBzZXJ2aWNlLnJlYWRQcmVmZXJlbmNlcyhuZXcgQnl0ZUFycmF5SW5wdXRTdHJlYW0ocHJlZnMuZ2V0Qnl0ZXMoKSkpOwoJCWFzc2VydFRydWUoc2VydmljZS5hcHBseVByZWZlcmVuY2VzKGV4cG9ydGVkKS5pc09LKCkpOwoJCWFzc2VydE5vdE51bGwoY29udGVudFR5cGVNYW5hZ2VyLmZpbmRDb250ZW50VHlwZUZvcigiKi5idWcxMjIyMTciKSk7Cgl9CgoJQFRlc3QKCXB1YmxpYyB2b2lkIHRlc3RJbnZhbGlkTWFya3VwKCkgewoJCWZpbmFsIElDb250ZW50VHlwZU1hbmFnZXIgY29udGVudFR5cGVNYW5hZ2VyID0gUGxhdGZvcm0uZ2V0Q29udGVudFR5cGVNYW5hZ2VyKCk7CgkJSUNvbnRlbnRUeXBlTWF0Y2hlciBmaW5kZXIgPSBjb250ZW50VHlwZU1hbmFnZXIuZ2V0TWF0Y2hlcihuZXcgTG9jYWxTZWxlY3Rpb25Qb2xpY3koKSwgbnVsbCk7CgkJYXNzZXJ0RXF1YWxzKCIxLjAiLCAwLCBmaW5kZXIuZmluZENvbnRlbnRUeXBlc0ZvcigiaW52YWxpZC5taXNzaW5nLmlkZW50aWZpZXIiKS5sZW5ndGgpOwoJCWFzc2VydEVxdWFscygiMi4wIiwgMCwgZmluZGVyLmZpbmRDb250ZW50VHlwZXNGb3IoImludmFsaWQubWlzc2luZy5uYW1lIikubGVuZ3RoKTsKCQlhc3NlcnROdWxsKCIzLjAiLCBjb250ZW50VHlwZU1hbmFnZXIuZ2V0Q29udGVudFR5cGUoUElfUkVTT1VSQ0VTX1RFU1RTICsgJy4nICsgImludmFsaWQtbWlzc2luZy1uYW1lIikpOwoJCVRlc3RSZWdpc3RyeUNoYW5nZUxpc3RlbmVyIGxpc3RlbmVyID0gbmV3IFRlc3RSZWdpc3RyeUNoYW5nZUxpc3RlbmVyKFBsYXRmb3JtLlBJX1JVTlRJTUUsCgkJCQlDb250ZW50VHlwZUJ1aWxkZXIuUFRfQ09OVEVOVFRZUEVTLCBudWxsLCBudWxsKTsKCQlCdW5kbGVUZXN0aW5nSGVscGVyLnJ1bldpdGhCdW5kbGVzKCIxIiwgKCkgLT4gewoJCQkvLyBlbnN1cmUgdGhlIGludmFsaWQgY29udGVudCB0eXBlcyBhcmUgbm90IGF2YWlsYWJsZQoJCQlhc3NlcnRFcXVhbHMoIjEuMiIsIDAsIGNvbnRlbnRUeXBlTWFuYWdlci5maW5kQ29udGVudFR5cGVzRm9yKCJpbnZhbGlkLm1pc3NpbmcuaWRlbnRpZmllciIpLmxlbmd0aCk7CgkJCWFzc2VydEVxdWFscygiMS4zIiwgMCwgY29udGVudFR5cGVNYW5hZ2VyLmZpbmRDb250ZW50VHlwZXNGb3IoImludmFsaWQubWlzc2luZy5uYW1lIikubGVuZ3RoKTsKCQkJYXNzZXJ0TnVsbCgiMS40IiwgY29udGVudFR5cGVNYW5hZ2VyLmdldENvbnRlbnRUeXBlKCJvcmcuZWNsaXBzZS5idW5kbGUwMy5pbnZhbGlkLW1pc3NpbmctbmFtZSIpKTsKCQkJLy8gdGhpcyBjb250ZW50IHR5cGUgaGFzIGdvb2QgbWFya3VwLCBidXQgaW52YWxpZCBkZXNjcmliZXIgY2xhc3MKCQkJSUNvbnRlbnRUeXBlIGludmFsaWREZXNjcmliZXIgPSBjb250ZW50VHlwZU1hbmFnZXIuZ2V0Q29udGVudFR5cGUoIm9yZy5lY2xpcHNlLmJ1bmRsZTAzLmludmFsaWQtZGVzY3JpYmVyIik7CgkJCWFzc2VydE5vdE51bGwoIjEuNSIsIGludmFsaWREZXNjcmliZXIpOwoJCQkvLyBuYW1lIGJhc2VkIG1hdGNoaW5nIHNob3VsZCB3b3JrIGZpbmUKCQkJYXNzZXJ0RXF1YWxzKCIxLjYiLCBpbnZhbGlkRGVzY3JpYmVyLCBjb250ZW50VHlwZU1hbmFnZXIuZmluZENvbnRlbnRUeXBlRm9yKCJpbnZhbGlkLmRlc2NyaWJlciIpKTsKCQkJLy8gdGhlIGRlc2NyaWJlciBjbGFzcyBpcyBpbnZhbGlkLCBjb250ZW50IG1hdGNob25nIHNob3VsZCBmYWlsCgkJCUlDb250ZW50VHlwZSBudWxsQ29udGVudFR5cGU7CgkJCXRyeSB7CgkJCQludWxsQ29udGVudFR5cGUgPSBjb250ZW50VHlwZU1hbmFnZXIuZmluZENvbnRlbnRUeXBlRm9yKGdldFJhbmRvbUNvbnRlbnRzKCksICJpbnZhbGlkLmRlc2NyaWJlciIpOwoJCQl9IGNhdGNoIChJT0V4Y2VwdGlvbiBlKSB7CgkJCQl0aHJvdyBuZXcgQXNzZXJ0aW9uRXJyb3IoZSk7CgkJCX0KCQkJYXNzZXJ0TnVsbCgiMS43IiwgbnVsbENvbnRlbnRUeXBlKTsKCQl9LCBnZXRDb250ZXh0KCksIG5ldyBTdHJpbmdbXSB7IENvbnRlbnRUeXBlVGVzdC5URVNUX0ZJTEVTX1JPT1QgKyAiY29udGVudC9idW5kbGUwMyIgfSwgbGlzdGVuZXIpOwoJfQoKCS8qKgoJICogQnVncyA2Nzg0MSBhbmQgNjI0NDMKCSAqLwoJQFRlc3QKCXB1YmxpYyB2b2lkIHRlc3RJT0V4Y2VwdGlvbigpIHRocm93cyBJT0V4Y2VwdGlvbiB7CgkJSUNvbnRlbnRUeXBlTWFuYWdlciBtYW5hZ2VyID0gUGxhdGZvcm0uZ2V0Q29udGVudFR5cGVNYW5hZ2VyKCk7CgkJSUNvbnRlbnRUeXBlIHhtbCA9IG1hbmFnZXIuZ2V0Q29udGVudFR5cGUoUGxhdGZvcm0uUElfUlVOVElNRSArICIueG1sIik7CgkJSUNvbnRlbnRUeXBlIHJvb3RFbGVtZW50ID0gbWFuYWdlci5nZXRDb250ZW50VHlwZShQSV9SRVNPVVJDRVNfVEVTVFMgKyAiLnJvb3QtZWxlbWVudCIpOwoJCS8vIGEgU0FYRXhjZXB0aW9uIGlzIHVzdWFsbHkgY2F1Z2h0IChhbmQgc2lsZW50bHkgaWdub3JlZCkgaW4KCQkvLyBYTUxSb290RWxlbWVudERlc2NyaWJlciBpbiB0aGVzZSBjYXNlcwoJCUlDb250ZW50VHlwZVtdIHNlbGVjdGVkID0gbWFuYWdlcgoJCQkJLmZpbmRDb250ZW50VHlwZXNGb3IoZ2V0SW5wdXRTdHJlYW0oWE1MX1VTX0FTQ0lJX0lOVkFMSUQsIFN0YW5kYXJkQ2hhcnNldHMuSVNPXzg4NTlfMSksICJ0ZXN0LnhtbCIpOwoJCWFzc2VydFRydWUoIjEuMSIsIGNvbnRhaW5zKHNlbGVjdGVkLCB4bWwpKTsKCQlhc3NlcnRUcnVlKCIxLjIiLCBjb250YWlucyhzZWxlY3RlZCwgcm9vdEVsZW1lbnQpKTsKCgkJLy8gaW5kdWNlIHJlZ3VsYXIgSU9FeGNlcHRpb25zLi4uIHRoZXNlIHNob3VsZCBiZSB0aHJvd24gdG8gY2xpZW50cwoJCWNsYXNzIEZha2VJT0V4Y2VwdGlvbiBleHRlbmRzIElPRXhjZXB0aW9uIHsKCQkJLyoqCgkJCSAqIEFsbCBzZXJpYWxpemFibGUgb2JqZWN0cyBzaG91bGQgaGF2ZSBhIHN0YWJsZSBzZXJpYWxWZXJzaW9uVUlECgkJCSAqLwoJCQlwcml2YXRlIHN0YXRpYyBmaW5hbCBsb25nIHNlcmlhbFZlcnNpb25VSUQgPSAxTDsKCgkJCUBPdmVycmlkZQoJCQlwdWJsaWMgU3RyaW5nIGdldE1lc3NhZ2UoKSB7CgkJCQlyZXR1cm4gIlRoaXMgZXhjZXB0aW9uIHdhcyB0aHJvd24gZm9yIHRlc3RpbmcgcHVycG9zZXMiOwoJCQl9CgkJfQoJCWFzc2VydFRocm93cyhGYWtlSU9FeGNlcHRpb24uY2xhc3MsICgpIC0+IG1hbmFnZXIuZmluZENvbnRlbnRUeXBlc0ZvcihuZXcgSW5wdXRTdHJlYW0oKSB7CgoJCQlAT3ZlcnJpZGUKCQkJcHVibGljIGludCBhdmFpbGFibGUoKSB7CgkJCQkvLyB0cmljayB0aGUgY2xpZW50IGludG8gcmVhZGluZyB0aGUgZmlsZQoJCQkJcmV0dXJuIEludGVnZXIuTUFYX1ZBTFVFOwoJCQl9CgoJCQlAT3ZlcnJpZGUKCQkJcHVibGljIGludCByZWFkKCkgdGhyb3dzIElPRXhjZXB0aW9uIHsKCQkJCXRocm93IG5ldyBGYWtlSU9FeGNlcHRpb24oKTsKCQkJfQoKCQkJQE92ZXJyaWRlCgkJCXB1YmxpYyBpbnQgcmVhZChieXRlW10gYiwgaW50IG9mZiwgaW50IGxlbikgdGhyb3dzIElPRXhjZXB0aW9uIHsKCQkJCXRocm93IG5ldyBGYWtlSU9FeGNlcHRpb24oKTsKCQkJfQoJCX0sICJ0ZXN0LnhtbCIpKTsKCX0KCglAVGVzdAoJcHVibGljIHZvaWQgdGVzdElzS2luZE9mKCkgewoJCUlDb250ZW50VHlwZU1hbmFnZXIgY29udGVudFR5cGVNYW5hZ2VyID0gUGxhdGZvcm0uZ2V0Q29udGVudFR5cGVNYW5hZ2VyKCk7CgkJSUNvbnRlbnRUeXBlIHRleHRDb250ZW50VHlwZSA9IGNvbnRlbnRUeXBlTWFuYWdlci5nZXRDb250ZW50VHlwZShQbGF0Zm9ybS5QSV9SVU5USU1FICsgJy4nICsgInRleHQiKTsKCQlJQ29udGVudFR5cGUgeG1sQ29udGVudFR5cGUgPSBjb250ZW50VHlwZU1hbmFnZXIuZ2V0Q29udGVudFR5cGUoUGxhdGZvcm0uUElfUlVOVElNRSArICIueG1sIik7CgkJSUNvbnRlbnRUeXBlIHhtbEJhc2VkRGlmZmVyZW50RXh0ZW5zaW9uQ29udGVudFR5cGUgPSBjb250ZW50VHlwZU1hbmFnZXIKCQkJCS5nZXRDb250ZW50VHlwZShQSV9SRVNPVVJDRVNfVEVTVFMgKyAnLicgKyAieG1sLWJhc2VkLWRpZmZlcmVudC1leHRlbnNpb24iKTsKCQlJQ29udGVudFR5cGUgeG1sQmFzZWRTcGVjaWZpY05hbWVDb250ZW50VHlwZSA9IGNvbnRlbnRUeXBlTWFuYWdlcgoJCQkJLmdldENvbnRlbnRUeXBlKFBJX1JFU09VUkNFU19URVNUUyArICcuJyArICJ4bWwtYmFzZWQtc3BlY2lmaWMtbmFtZSIpOwoJCUlDb250ZW50VHlwZSBiaW5hcnlDb250ZW50VHlwZSA9IGNvbnRlbnRUeXBlTWFuYWdlci5nZXRDb250ZW50VHlwZShQSV9SRVNPVVJDRVNfVEVTVFMgKyAnLicgKyAic2FtcGxlLWJpbmFyeTEiKTsKCQlhc3NlcnRUcnVlKCIxLjAiLCB0ZXh0Q29udGVudFR5cGUuaXNLaW5kT2YodGV4dENvbnRlbnRUeXBlKSk7CgkJYXNzZXJ0VHJ1ZSgiMi4wIiwgeG1sQ29udGVudFR5cGUuaXNLaW5kT2YodGV4dENvbnRlbnRUeXBlKSk7CgkJYXNzZXJ0RmFsc2UoIjIuMSIsIHRleHRDb250ZW50VHlwZS5pc0tpbmRPZih4bWxDb250ZW50VHlwZSkpOwoJCWFzc2VydFRydWUoIjIuMiIsIHhtbENvbnRlbnRUeXBlLmlzS2luZE9mKHhtbENvbnRlbnRUeXBlKSk7CgkJYXNzZXJ0VHJ1ZSgiMy4wIiwgeG1sQmFzZWREaWZmZXJlbnRFeHRlbnNpb25Db250ZW50VHlwZS5pc0tpbmRPZih0ZXh0Q29udGVudFR5cGUpKTsKCQlhc3NlcnRUcnVlKCIzLjEiLCB4bWxCYXNlZERpZmZlcmVudEV4dGVuc2lvbkNvbnRlbnRUeXBlLmlzS2luZE9mKHhtbENvbnRlbnRUeXBlKSk7CgkJYXNzZXJ0RmFsc2UoIjQuMCIsIHhtbEJhc2VkRGlmZmVyZW50RXh0ZW5zaW9uQ29udGVudFR5cGUuaXNLaW5kT2YoeG1sQmFzZWRTcGVjaWZpY05hbWVDb250ZW50VHlwZSkpOwoJCWFzc2VydEZhbHNlKCI1LjAiLCBiaW5hcnlDb250ZW50VHlwZS5pc0tpbmRPZih0ZXh0Q29udGVudFR5cGUpKTsKCX0KCglAVGVzdAoJcHVibGljIHZvaWQgdGVzdExpc3RQYXJzaW5nKCkgewoJCVN0cmluZ1tdIGxpc3Q7CgkJbGlzdCA9IFV0aWwucGFyc2VJdGVtcyhudWxsKTsKCQlhc3NlcnRFcXVhbHMoIjAuMCIsIDAsIGxpc3QubGVuZ3RoKTsKCQlsaXN0ID0gVXRpbC5wYXJzZUl0ZW1zKCIiKTsKCQlhc3NlcnRFcXVhbHMoIjEuMCIsIDEsIGxpc3QubGVuZ3RoKTsKCQlhc3NlcnRFcXVhbHMoIjEuMSIsICIiLCBsaXN0WzBdKTsKCQlsaXN0ID0gVXRpbC5wYXJzZUl0ZW1zKCJmb28iKTsKCQlhc3NlcnRFcXVhbHMoIjIuMCIsIDEsIGxpc3QubGVuZ3RoKTsKCQlhc3NlcnRFcXVhbHMoIjIuMSIsICJmb28iLCBsaXN0WzBdKTsKCQlsaXN0ID0gVXRpbC5wYXJzZUl0ZW1zKCIsIik7CgkJYXNzZXJ0RXF1YWxzKCIzLjAiLCAyLCBsaXN0Lmxlbmd0aCk7CgkJYXNzZXJ0RXF1YWxzKCIzLjEiLCAiIiwgbGlzdFswXSk7CgkJYXNzZXJ0RXF1YWxzKCIzLjIiLCAiIiwgbGlzdFsxXSk7CgkJbGlzdCA9IFV0aWwucGFyc2VJdGVtcygiLGZvbyxiYXIiKTsKCQlhc3NlcnRFcXVhbHMoIjQuMCIsIDMsIGxpc3QubGVuZ3RoKTsKCQlhc3NlcnRFcXVhbHMoIjQuMSIsICIiLCBsaXN0WzBdKTsKCQlhc3NlcnRFcXVhbHMoIjQuMiIsICJmb28iLCBsaXN0WzFdKTsKCQlhc3NlcnRFcXVhbHMoIjQuMyIsICJiYXIiLCBsaXN0WzJdKTsKCQlsaXN0ID0gVXRpbC5wYXJzZUl0ZW1zKCJmb28sYmFyLCIpOwoJCWFzc2VydEVxdWFscygiNS4wIiwgMywgbGlzdC5sZW5ndGgpOwoJCWFzc2VydEVxdWFscygiNS4xIiwgImZvbyIsIGxpc3RbMF0pOwoJCWFzc2VydEVxdWFscygiNS4yIiwgImJhciIsIGxpc3RbMV0pOwoJCWFzc2VydEVxdWFscygiNS4zIiwgIiIsIGxpc3RbMl0pOwoJCWxpc3QgPSBVdGlsLnBhcnNlSXRlbXMoImZvbywsYmFyIik7CgkJYXNzZXJ0RXF1YWxzKCI2LjAiLCAzLCBsaXN0Lmxlbmd0aCk7CgkJYXNzZXJ0RXF1YWxzKCI2LjEiLCAiZm9vIiwgbGlzdFswXSk7CgkJYXNzZXJ0RXF1YWxzKCI2LjIiLCAiIiwgbGlzdFsxXSk7CgkJYXNzZXJ0RXF1YWxzKCI2LjMiLCAiYmFyIiwgbGlzdFsyXSk7CgkJbGlzdCA9IFV0aWwucGFyc2VJdGVtcygiZm9vLCwsYmFyIik7CgkJYXNzZXJ0RXF1YWxzKCI3LjAiLCA0LCBsaXN0Lmxlbmd0aCk7CgkJYXNzZXJ0RXF1YWxzKCI3LjEiLCAiZm9vIiwgbGlzdFswXSk7CgkJYXNzZXJ0RXF1YWxzKCI3LjIiLCAiIiwgbGlzdFsxXSk7CgkJYXNzZXJ0RXF1YWxzKCI3LjMiLCAiIiwgbGlzdFsyXSk7CgkJYXNzZXJ0RXF1YWxzKCI3LjQiLCAiYmFyIiwgbGlzdFszXSk7CgkJbGlzdCA9IFV0aWwucGFyc2VJdGVtcygiLCxmb28sYmFyIik7CgkJYXNzZXJ0RXF1YWxzKCI4LjAiLCA0LCBsaXN0Lmxlbmd0aCk7CgkJYXNzZXJ0RXF1YWxzKCI4LjEiLCAiIiwgbGlzdFswXSk7CgkJYXNzZXJ0RXF1YWxzKCI4LjIiLCAiIiwgbGlzdFsxXSk7CgkJYXNzZXJ0RXF1YWxzKCI4LjMiLCAiZm9vIiwgbGlzdFsyXSk7CgkJYXNzZXJ0RXF1YWxzKCI4LjQiLCAiYmFyIiwgbGlzdFszXSk7CgkJbGlzdCA9IFV0aWwucGFyc2VJdGVtcygiZm9vLGJhciwsIik7CgkJYXNzZXJ0RXF1YWxzKCI5LjAiLCA0LCBsaXN0Lmxlbmd0aCk7CgkJYXNzZXJ0RXF1YWxzKCI5LjEiLCAiZm9vIiwgbGlzdFswXSk7CgkJYXNzZXJ0RXF1YWxzKCI5LjIiLCAiYmFyIiwgbGlzdFsxXSk7CgkJYXNzZXJ0RXF1YWxzKCI5LjMiLCAiIiwgbGlzdFsyXSk7CgkJYXNzZXJ0RXF1YWxzKCI5LjQiLCAiIiwgbGlzdFszXSk7CgkJbGlzdCA9IFV0aWwucGFyc2VJdGVtcygiLCwsIik7CgkJYXNzZXJ0RXF1YWxzKCIxMC4wIiwgNCwgbGlzdC5sZW5ndGgpOwoJCWFzc2VydEVxdWFscygiMTAuMSIsICIiLCBsaXN0WzBdKTsKCQlhc3NlcnRFcXVhbHMoIjEwLjIiLCAiIiwgbGlzdFsxXSk7CgkJYXNzZXJ0RXF1YWxzKCIxMC4zIiwgIiIsIGxpc3RbMl0pOwoJCWFzc2VydEVxdWFscygiMTAuNCIsICIiLCBsaXN0WzNdKTsKCX0KCglAVGVzdAoJcHVibGljIHZvaWQgdGVzdE15Q29udGVudERlc2NyaWJlcigpIHRocm93cyBJT0V4Y2VwdGlvbiB7CgkJSUNvbnRlbnRUeXBlTWFuYWdlciBtYW5hZ2VyID0gUGxhdGZvcm0uZ2V0Q29udGVudFR5cGVNYW5hZ2VyKCk7CgkJSUNvbnRlbnRUeXBlIG15Q29udGVudCA9IG1hbmFnZXIuZ2V0Q29udGVudFR5cGUoUElfUkVTT1VSQ0VTX1RFU1RTICsgJy4nICsgIm15Q29udGVudCIpOwoJCWFzc2VydE5vdE51bGwoIjAuNSIsIG15Q29udGVudCk7CgkJYXNzZXJ0RXF1YWxzKCIwLjYiLCBteUNvbnRlbnQsIG1hbmFnZXIuZmluZENvbnRlbnRUeXBlRm9yKCJteUNvbnRlbnQubWMxIikpOwoJCWFzc2VydEVxdWFscygiMC43IiwgbXlDb250ZW50LCBtYW5hZ2VyLmZpbmRDb250ZW50VHlwZUZvcigibXlDb250ZW50Lm1jMiIpKTsKCQlhc3NlcnRFcXVhbHMoIjAuOCIsIG15Q29udGVudCwgbWFuYWdlci5maW5kQ29udGVudFR5cGVGb3IoImZvby5teUNvbnRlbnQxIikpOwoJCWFzc2VydEVxdWFscygiMC45IiwgbXlDb250ZW50LCBtYW5hZ2VyLmZpbmRDb250ZW50VHlwZUZvcigiYmFyLm15Q29udGVudDIiKSk7CgkJSUNvbnRlbnREZXNjcmlwdGlvbiBkZXNjcmlwdGlvbiA9IG1hbmFnZXIuZ2V0RGVzY3JpcHRpb25Gb3IoCgkJCQlnZXRJbnB1dFN0cmVhbShNeUNvbnRlbnREZXNjcmliZXIuU0lHTkFUVVJFLCBTdGFuZGFyZENoYXJzZXRzLlVTX0FTQ0lJKSwgIm15Q29udGVudC5tYzEiLAoJCQkJSUNvbnRlbnREZXNjcmlwdGlvbi5BTEwpOwoJCWFzc2VydE5vdE51bGwoIjEuMCIsIGRlc2NyaXB0aW9uKTsKCQlhc3NlcnRFcXVhbHMoIjEuMSIsIG15Q29udGVudCwgZGVzY3JpcHRpb24uZ2V0Q29udGVudFR5cGUoKSk7CgkJYXNzZXJ0Tm90U2FtZSgiMS4yIiwgbXlDb250ZW50LmdldERlZmF1bHREZXNjcmlwdGlvbigpLCBkZXNjcmlwdGlvbik7CgkJZm9yIChpbnQgaSA9IDA7IGkgPCBNeUNvbnRlbnREZXNjcmliZXIuTVlfT1BUSU9OUy5sZW5ndGg7IGkrKykgewoJCQlhc3NlcnRFcXVhbHMoIjIuIiArIGksIE15Q29udGVudERlc2NyaWJlci5NWV9PUFRJT05fVkFMVUVTW2ldLAoJCQkJCWRlc2NyaXB0aW9uLmdldFByb3BlcnR5KE15Q29udGVudERlc2NyaWJlci5NWV9PUFRJT05TW2ldKSk7CgkJfQoJfQoKCUBUZXN0CglwdWJsaWMgdm9pZCB0ZXN0Tm9FeHRlbnNpb25Bc3NvY2lhdGlvbigpIHsKCQkvLyBUT0RPIHVzZSBhIElDb250ZW50VHlwZU1hdGNoZXIgaW5zdGVhZAoJCWZpbmFsIElDb250ZW50VHlwZU1hbmFnZXIgbWFuYWdlciA9IFBsYXRmb3JtLmdldENvbnRlbnRUeXBlTWFuYWdlcigpOwoKCQlJQ29udGVudFR5cGVbXSBzZWxlY3RlZCA9IG1hbmFnZXIuZmluZENvbnRlbnRUeXBlc0ZvcigiZmlsZV93aXRoX25vX2V4dGVuc2lvbiIpOwoJCWFzc2VydEVxdWFscygiMC4xIiwgMCwgc2VsZWN0ZWQubGVuZ3RoKTsKCgkJVGVzdFJlZ2lzdHJ5Q2hhbmdlTGlzdGVuZXIgbGlzdGVuZXIgPSBuZXcgVGVzdFJlZ2lzdHJ5Q2hhbmdlTGlzdGVuZXIoUGxhdGZvcm0uUElfUlVOVElNRSwKCQkJCUNvbnRlbnRUeXBlQnVpbGRlci5QVF9DT05URU5UVFlQRVMsIG51bGwsIG51bGwpOwoJCUJ1bmRsZVRlc3RpbmdIZWxwZXIucnVuV2l0aEJ1bmRsZXMoIjEiLCAoKSAtPiB7CgkJCWZpbmFsIFN0cmluZyBuYW1lc3BhY2UgPSAib3JnLmVjbGlwc2UuYnVuZGxlMDQiOwoKCQkJSUNvbnRlbnRUeXBlIGVtcHR5MSA9IG1hbmFnZXIuZ2V0Q29udGVudFR5cGUobmFtZXNwYWNlICsgIi5lbXB0eV9leHRlbnNpb24xIik7CgkJCUlDb250ZW50VHlwZSBlbXB0eTIgPSBtYW5hZ2VyLmdldENvbnRlbnRUeXBlKG5hbWVzcGFjZSArICIuZW1wdHlfZXh0ZW5zaW9uMiIpOwoJCQlJQ29udGVudFR5cGUgZW1wdHkzID0gbWFuYWdlci5nZXRDb250ZW50VHlwZShuYW1lc3BhY2UgKyAiLmVtcHR5X2V4dGVuc2lvbjMiKTsKCQkJSUNvbnRlbnRUeXBlIGVtcHR5NCA9IG1hbmFnZXIuZ2V0Q29udGVudFR5cGUobmFtZXNwYWNlICsgIi5lbXB0eV9leHRlbnNpb240Iik7CgkJCUlDb250ZW50VHlwZSBub25FbXB0eSA9IG1hbmFnZXIuZ2V0Q29udGVudFR5cGUobmFtZXNwYWNlICsgIi5ub25fZW1wdHlfZXh0ZW5zaW9uIik7CgoJCQlhc3NlcnROb3ROdWxsKCIxLjEuMSIsIGVtcHR5MSk7CgkJCWFzc2VydE5vdE51bGwoIjEuMS4yIiwgZW1wdHkyKTsKCQkJYXNzZXJ0Tm90TnVsbCgiMS4xLjMiLCBlbXB0eTMpOwoJCQlhc3NlcnROb3ROdWxsKCIxLjEuNCIsIGVtcHR5NCk7CgkJCWFzc2VydE5vdE51bGwoIjEuMS41Iiwgbm9uRW1wdHkpOwoKCQkJSUNvbnRlbnRUeXBlW10gc2VsZWN0ZWQxID0gbWFuYWdlci5maW5kQ29udGVudFR5cGVzRm9yKCJmaWxlX3dpdGhfbm9fZXh0ZW5zaW9uIik7CgkJCWFzc2VydEVxdWFscygiMS4yLjAiLCA0LCBzZWxlY3RlZDEubGVuZ3RoKTsKCQkJYXNzZXJ0VHJ1ZSgiMS4yLjEiLCBjb250YWlucyhzZWxlY3RlZDEsIGVtcHR5MSkpOwoJCQlhc3NlcnRUcnVlKCIxLjIuMiIsIGNvbnRhaW5zKHNlbGVjdGVkMSwgZW1wdHkyKSk7CgkJCWFzc2VydFRydWUoIjEuMi4zIiwgY29udGFpbnMoc2VsZWN0ZWQxLCBlbXB0eTMpKTsKCQkJYXNzZXJ0VHJ1ZSgiMS4yLjQiLCBjb250YWlucyhzZWxlY3RlZDEsIGVtcHR5NCkpOwoKCQkJc2VsZWN0ZWQxID0gbWFuYWdlci5maW5kQ29udGVudFR5cGVzRm9yKCJmaWxlX3dpdGhfZXh0ZW5zaW9uLm5vbi1lbXB0eSIpOwoJCQlhc3NlcnRFcXVhbHMoIjEuMi41IiwgMSwgc2VsZWN0ZWQxLmxlbmd0aCk7CgkJCWFzc2VydFRydWUoIjEuMi42IiwgY29udGFpbnMoc2VsZWN0ZWQxLCBub25FbXB0eSkpOwoKCQkJdHJ5IHsKCQkJCW5vbkVtcHR5LmFkZEZpbGVTcGVjKCIiLCBJQ29udGVudFR5cGUuRklMRV9FWFRFTlNJT05fU1BFQyk7CgkJCX0gY2F0Y2ggKENvcmVFeGNlcHRpb24gZSkgewoJCQkJdGhyb3cgbmV3IEFzc2VydGlvbkVycm9yKGUpOwoJCQl9CgkJCXRyeSB7CgkJCQlzZWxlY3RlZDEgPSBtYW5hZ2VyLmZpbmRDb250ZW50VHlwZXNGb3IoImZpbGVfd2l0aF9ub19leHRlbnNpb24iKTsKCQkJCWFzc2VydEVxdWFscygiMS4zLjEiLCA1LCBzZWxlY3RlZDEubGVuZ3RoKTsKCQkJCWFzc2VydFRydWUoIjEuMy4yIiwgY29udGFpbnMoc2VsZWN0ZWQxLCBub25FbXB0eSkpOwoJCQl9IGZpbmFsbHkgewoJCQkJdHJ5IHsKCQkJCQlub25FbXB0eS5yZW1vdmVGaWxlU3BlYygiIiwgSUNvbnRlbnRUeXBlLkZJTEVfRVhURU5TSU9OX1NQRUMpOwoJCQkJfSBjYXRjaCAoQ29yZUV4Y2VwdGlvbiBlKSB7CgkJCQkJdGhyb3cgbmV3IEFzc2VydGlvbkVycm9yKGUpOwoJCQkJfQoJCQl9CgkJCXNlbGVjdGVkMSA9IG1hbmFnZXIuZmluZENvbnRlbnRUeXBlc0ZvcigiZmlsZV93aXRoX25vX2V4dGVuc2lvbiIpOwoJCQlhc3NlcnRFcXVhbHMoIjEuNC4wIiwgNCwgc2VsZWN0ZWQxLmxlbmd0aCk7CgkJCWFzc2VydEZhbHNlKCIxLjQuMSIsIGNvbnRhaW5zKHNlbGVjdGVkMSwgbm9uRW1wdHkpKTsKCQl9LCBnZXRDb250ZXh0KCksIG5ldyBTdHJpbmdbXSB7IENvbnRlbnRUeXBlVGVzdC5URVNUX0ZJTEVTX1JPT1QgKyAiY29udGVudC9idW5kbGUwNCIgfSwgbGlzdGVuZXIpOwoJfQoKCUBUZXN0CglwdWJsaWMgdm9pZCB0ZXN0T3JkZXJXaXRoRW1wdHlGaWxlcygpIHRocm93cyBJT0V4Y2VwdGlvbiB7CgkJSUNvbnRlbnRUeXBlTWFuYWdlciBtYW5hZ2VyID0gUGxhdGZvcm0uZ2V0Q29udGVudFR5cGVNYW5hZ2VyKCk7CgkJSUNvbnRlbnRUeXBlTWF0Y2hlciBmaW5kZXIgPSBtYW5hZ2VyLmdldE1hdGNoZXIobmV3IExvY2FsU2VsZWN0aW9uUG9saWN5KCksIG51bGwpOwoKCQlJQ29udGVudFR5cGUgeG1sID0gbWFuYWdlci5nZXRDb250ZW50VHlwZShQbGF0Zm9ybS5QSV9SVU5USU1FICsgIi54bWwiKTsKCQltYW5hZ2VyLmdldENvbnRlbnRUeXBlKFBJX1JFU09VUkNFU19URVNUUyArICIucm9vdC1lbGVtZW50Iik7CgkJbWFuYWdlci5nZXRDb250ZW50VHlwZShQSV9SRVNPVVJDRVNfVEVTVFMgKyAiLmR0ZCIpOwoJCS8vIGZvciBhbiBlbXB0eSBmaWxlLCB0aGUgbW9zdCBnZW5lcmljIGNvbnRlbnQgdHlwZSBzaG91bGQgYmUgcmV0dXJuZWQKCQlJQ29udGVudFR5cGUgc2VsZWN0ZWQgPSBmaW5kZXIuZmluZENvbnRlbnRUeXBlRm9yKGdldElucHV0U3RyZWFtKCIiKSwgImZvby54bWwiKTsKCQlhc3NlcnRFcXVhbHMoIjEuMCIsIHhtbCwgc2VsZWN0ZWQpOwoJCS8vIGl0IHNob3VsZCBiZSBlcXVpdmFsZW50IHRvIG9taXR0aW5nIHRoZSBjb250ZW50cwoJCWFzc2VydEVxdWFscygiMS4xIiwgeG1sLCBmaW5kZXIuZmluZENvbnRlbnRUeXBlRm9yKCJmb28ueG1sIikpOwoJfQoKCS8qKgoJICogVGhpcyB0ZXN0IHNob3dzIGhvdyB3ZSBkZWFsIHdpdGggb3JwaGFuIGZpbGUgYXNzb2NpYXRpb25zIChhc3NvY2lhdGlvbnMgd2hvc2UKCSAqIGNvbnRlbnQgdHlwZXMgYXJlIG1pc3NpbmcpLgoJICovCglAVGVzdAoJcHVibGljIHZvaWQgdGVzdE9ycGhhbkNvbnRlbnRUeXBlKCkgewoJCWZpbmFsIElDb250ZW50VHlwZU1hbmFnZXIgY29udGVudFR5cGVNYW5hZ2VyID0gUGxhdGZvcm0uZ2V0Q29udGVudFR5cGVNYW5hZ2VyKCk7CgkJSUNvbnRlbnRUeXBlIG9ycGhhbiA9IGNvbnRlbnRUeXBlTWFuYWdlci5nZXRDb250ZW50VHlwZShQSV9SRVNPVVJDRVNfVEVTVFMgKyAiLm9ycGhhbiIpOwoJCWFzc2VydE51bGwoIjAuOCIsIG9ycGhhbik7CgkJSUNvbnRlbnRUeXBlIG1pc3NpbmcgPSBjb250ZW50VHlwZU1hbmFnZXIuZ2V0Q29udGVudFR5cGUoIm9yZy5lY2xpcHNlLmJ1bmRsZTAxLm1pc3NpbmciKTsKCQlhc3NlcnROdWxsKCIwLjkiLCBtaXNzaW5nKTsKCQlhc3NlcnRFcXVhbHMoIjEuMSIsIDAsIGNvbnRlbnRUeXBlTWFuYWdlci5maW5kQ29udGVudFR5cGVzRm9yKCJmb28ub3JwaGFuIikubGVuZ3RoKTsKCQlhc3NlcnRFcXVhbHMoIjEuMiIsIDAsIGNvbnRlbnRUeXBlTWFuYWdlci5maW5kQ29udGVudFR5cGVzRm9yKCJvcnBoYW4ub3JwaGFuIikubGVuZ3RoKTsKCQlhc3NlcnRFcXVhbHMoIjEuMyIsIDAsIGNvbnRlbnRUeXBlTWFuYWdlci5maW5kQ29udGVudFR5cGVzRm9yKCJmb28ub3JwaGFuMiIpLmxlbmd0aCk7CgoJCS8vIHRlc3QgbGF0ZSBhZGRpdGlvbiBvZiBjb250ZW50IHR5cGUgLSBvcnBoYW4yIHNob3VsZCBiZWNvbWUgdmlzaWJsZQoJCVRlc3RSZWdpc3RyeUNoYW5nZUxpc3RlbmVyIGxpc3RlbmVyID0gbmV3IFRlc3RSZWdpc3RyeUNoYW5nZUxpc3RlbmVyKFBsYXRmb3JtLlBJX1JVTlRJTUUsCgkJCQlDb250ZW50VHlwZUJ1aWxkZXIuUFRfQ09OVEVOVFRZUEVTLCBudWxsLCBudWxsKTsKCgkJQnVuZGxlVGVzdGluZ0hlbHBlci5ydW5XaXRoQnVuZGxlcygiMiIsICgpIC0+IHsKCQkJSUNvbnRlbnRUeXBlIG9ycGhhbjEgPSBjb250ZW50VHlwZU1hbmFnZXIuZ2V0Q29udGVudFR5cGUoUElfUkVTT1VSQ0VTX1RFU1RTICsgIi5vcnBoYW4iKTsKCQkJYXNzZXJ0Tm90TnVsbCgiMi4xIiwgb3JwaGFuMSk7CgkJCUlDb250ZW50VHlwZSBtaXNzaW5nMSA9IGNvbnRlbnRUeXBlTWFuYWdlci5nZXRDb250ZW50VHlwZSgib3JnLmVjbGlwc2UuYnVuZGxlMDEubWlzc2luZyIpOwoJCQlhc3NlcnROb3ROdWxsKCIyLjIiLCBtaXNzaW5nMSk7CgkJCS8vIGNoZWNrcyBvcnBoYW4ncyBhc3NvY2lhdGlvbnMKCQkJYXNzZXJ0RXF1YWxzKCIyLjMiLCAxLCBjb250ZW50VHlwZU1hbmFnZXIuZmluZENvbnRlbnRUeXBlc0ZvcigiZm9vLm9ycGhhbiIpLmxlbmd0aCk7CgkJCWFzc2VydEVxdWFscygiMi40Iiwgb3JwaGFuMSwgY29udGVudFR5cGVNYW5hZ2VyLmZpbmRDb250ZW50VHlwZXNGb3IoImZvby5vcnBoYW4iKVswXSk7CgkJCWFzc2VydEVxdWFscygiMi41IiwgMSwgY29udGVudFR5cGVNYW5hZ2VyLmZpbmRDb250ZW50VHlwZXNGb3IoIm9ycGhhbi5vcnBoYW4iKS5sZW5ndGgpOwoJCQlhc3NlcnRFcXVhbHMoIjIuNiIsIG9ycGhhbjEsIGNvbnRlbnRUeXBlTWFuYWdlci5maW5kQ29udGVudFR5cGVzRm9yKCJmb28ub3JwaGFuIilbMF0pOwoJCQkvLyBjaGVjayB3aGV0aGVyIGFuIG9ycGhhbiBhc3NvY2lhdGlvbiB3YXMgYWRkZWQgdG8gdGhlIGR5bmFtaWNhbGx5IGFkZGVkIGJ1bmRsZQoJCQlhc3NlcnRFcXVhbHMoIjIuNyIsIDEsIGNvbnRlbnRUeXBlTWFuYWdlci5maW5kQ29udGVudFR5cGVzRm9yKCJmb28ub3JwaGFuMiIpLmxlbmd0aCk7CgkJCWFzc2VydEVxdWFscygiMi44IiwgbWlzc2luZzEsIGNvbnRlbnRUeXBlTWFuYWdlci5maW5kQ29udGVudFR5cGVzRm9yKCJmb28ub3JwaGFuMiIpWzBdKTsKCQl9LCBnZXRDb250ZXh0KCksIG5ldyBTdHJpbmdbXSB7IENvbnRlbnRUeXBlVGVzdC5URVNUX0ZJTEVTX1JPT1QgKyAiY29udGVudC9idW5kbGUwMSIgfSwgbGlzdGVuZXIpOwoJfQoKCS8qKgoJICogUmVncmVzc2lvbiB0ZXN0IGZvciBidWcgNjg4OTQKCSAqLwoJQFRlc3QKCXB1YmxpYyB2b2lkIHRlc3RQcmVmZXJlbmNlcygpIHRocm93cyBDb3JlRXhjZXB0aW9uLCBCYWNraW5nU3RvcmVFeGNlcHRpb24gewoJCUlDb250ZW50VHlwZU1hbmFnZXIgbWFuYWdlciA9IFBsYXRmb3JtLmdldENvbnRlbnRUeXBlTWFuYWdlcigpOwoJCUlDb250ZW50VHlwZSB0ZXh0ID0gbWFuYWdlci5nZXRDb250ZW50VHlwZShJQ29udGVudFR5cGVNYW5hZ2VyLkNUX1RFWFQpOwoJCVByZWZlcmVuY2VzIHRleHRQcmVmcyA9IEluc3RhbmNlU2NvcGUuSU5TVEFOQ0UuZ2V0Tm9kZShDb250ZW50VHlwZU1hbmFnZXIuQ09OVEVOVF9UWVBFX1BSRUZfTk9ERSkKCQkJCS5ub2RlKHRleHQuZ2V0SWQoKSk7CgkJYXNzZXJ0Tm90TnVsbCgiMC4xIiwgdGV4dCk7CgoJCS8vIGVuc3VyZSB0aGUgImRlZmF1bHQgY2hhcnNldCIgcHJlZmVyZW5jZSBpcyBiZWluZyBwcm9wZXJseSB1c2VkCgkJYXNzZXJ0TnVsbCgiMS4wIiwgdGV4dC5nZXREZWZhdWx0Q2hhcnNldCgpKTsKCQlhc3NlcnROdWxsKCIxLjEiLCB0ZXh0UHJlZnMuZ2V0KENvbnRlbnRUeXBlLlBSRUZfREVGQVVMVF9DSEFSU0VULCBudWxsKSk7CgkJdGV4dC5zZXREZWZhdWx0Q2hhcnNldCgiVVRGLTgiKTsKCQlhc3NlcnRFcXVhbHMoIjEuMiIsICJVVEYtOCIsIHRleHRQcmVmcy5nZXQoQ29udGVudFR5cGUuUFJFRl9ERUZBVUxUX0NIQVJTRVQsIG51bGwpKTsKCQl0ZXh0LnNldERlZmF1bHRDaGFyc2V0KG51bGwpOwoJCWFzc2VydE51bGwoIjEuMyIsIHRleHRQcmVmcy5nZXQoQ29udGVudFR5cGUuUFJFRl9ERUZBVUxUX0NIQVJTRVQsIG51bGwpKTsKCgkJLy8gZW5zdXJlIHRoZSBmaWxlIHNwZWMgcHJlZmVyZW5jZXMgYXJlIGJlaW5nIHByb3Blcmx5IHVzZWQKCQkvLyBzb21lIHNhbml0eSBjaGVja2luZwoJCWFzc2VydEZhbHNlKCIyLjAxIiwgdGV4dC5pc0Fzc29jaWF0ZWRXaXRoKCJ4eXouZm9vIikpOwoJCWFzc2VydEZhbHNlKCIyLjAxIiwgdGV4dC5pc0Fzc29jaWF0ZWRXaXRoKCJ4eXouYmFyIikpOwoJCWFzc2VydEZhbHNlKCIyLjAzIiwgdGV4dC5pc0Fzc29jaWF0ZWRXaXRoKCJmb28uZXh0IikpOwoJCWFzc2VydEZhbHNlKCIyLjA0IiwgdGV4dC5pc0Fzc29jaWF0ZWRXaXRoKCJiYXIuZXh0IikpOwoJCS8vIE51bGwgZW50cmllcyBmaXJzdCB0byBhdm9pZCBpbnRlcmZlcmVuY2UgZnJvbSBvdGhlciB0ZXN0cwoJCXRleHRQcmVmcy5yZW1vdmUoQ29udGVudFR5cGUuUFJFRl9GSUxFX05BTUVTKTsKCQl0ZXh0UHJlZnMucmVtb3ZlKENvbnRlbnRUeXBlLlBSRUZfRklMRV9FWFRFTlNJT05TKTsKCQkvLyBwbGF5IHdpdGggZmlsZSBuYW1lIGFzc29jaWF0aW9ucyBmaXJzdC4uLgoJCWFzc2VydE51bGwoIjIuMGEiLCB0ZXh0UHJlZnMuZ2V0KENvbnRlbnRUeXBlLlBSRUZfRklMRV9OQU1FUywgbnVsbCkpOwoJCWFzc2VydE51bGwoIjIuMGIiLCB0ZXh0UHJlZnMuZ2V0KENvbnRlbnRUeXBlLlBSRUZfRklMRV9FWFRFTlNJT05TLCBudWxsKSk7CgkJdGV4dC5hZGRGaWxlU3BlYygiZm9vLmV4dCIsIElDb250ZW50VHlwZS5GSUxFX05BTUVfU1BFQyk7CgkJYXNzZXJ0VHJ1ZSgiMi4xIiwgdGV4dC5pc0Fzc29jaWF0ZWRXaXRoKCJmb28uZXh0IikpOwoJCWFzc2VydEVxdWFscygiMi4yIiwgImZvby5leHQiLCB0ZXh0UHJlZnMuZ2V0KENvbnRlbnRUeXBlLlBSRUZfRklMRV9OQU1FUywgbnVsbCkpOwoJCXRleHQuYWRkRmlsZVNwZWMoImJhci5leHQiLCBJQ29udGVudFR5cGUuRklMRV9OQU1FX1NQRUMpOwoJCWFzc2VydFRydWUoIjIuMyIsIHRleHQuaXNBc3NvY2lhdGVkV2l0aCgiYmFyLmV4dCIpKTsKCQlhc3NlcnRFcXVhbHMoIjIuNCIsICJmb28uZXh0LGJhci5leHQiLCB0ZXh0UHJlZnMuZ2V0KENvbnRlbnRUeXBlLlBSRUZfRklMRV9OQU1FUywgbnVsbCkpOwoJCS8vIC4uLiBhbmQgdGhlbiB3aXRoIGZpbGUgZXh0ZW5zaW9ucwoJCXRleHQuYWRkRmlsZVNwZWMoImZvbyIsIElDb250ZW50VHlwZS5GSUxFX0VYVEVOU0lPTl9TUEVDKTsKCQlhc3NlcnRUcnVlKCIyLjUiLCB0ZXh0LmlzQXNzb2NpYXRlZFdpdGgoInh5ei5mb28iKSk7CgkJYXNzZXJ0RXF1YWxzKCIyLjYiLCAiZm9vIiwgdGV4dFByZWZzLmdldChDb250ZW50VHlwZS5QUkVGX0ZJTEVfRVhURU5TSU9OUywgbnVsbCkpOwoJCXRleHQuYWRkRmlsZVNwZWMoImJhciIsIElDb250ZW50VHlwZS5GSUxFX0VYVEVOU0lPTl9TUEVDKTsKCQlhc3NlcnRUcnVlKCIyLjciLCB0ZXh0LmlzQXNzb2NpYXRlZFdpdGgoInh5ei5iYXIiKSk7CgkJYXNzZXJ0RXF1YWxzKCIyLjQiLCAiZm9vLGJhciIsIHRleHRQcmVmcy5nZXQoQ29udGVudFR5cGUuUFJFRl9GSUxFX0VYVEVOU0lPTlMsIG51bGwpKTsKCQkvLyByZW1vdmUgYWxsIGFzc29jaWF0aW9ucyBtYWRlCgkJdGV4dC5yZW1vdmVGaWxlU3BlYygiZm9vLmV4dCIsIElDb250ZW50VHlwZS5GSUxFX05BTUVfU1BFQyk7CgkJdGV4dC5yZW1vdmVGaWxlU3BlYygiYmFyLmV4dCIsIElDb250ZW50VHlwZS5GSUxFX05BTUVfU1BFQyk7CgkJdGV4dC5yZW1vdmVGaWxlU3BlYygiZm9vIiwgSUNvbnRlbnRUeXBlLkZJTEVfRVhURU5TSU9OX1NQRUMpOwoJCXRleHQucmVtb3ZlRmlsZVNwZWMoImJhciIsIElDb250ZW50VHlwZS5GSUxFX0VYVEVOU0lPTl9TUEVDKTsKCQkvLyBlbnN1cmUgYWxsIGlzIGFzIGJlZm9yZQoJCWFzc2VydEZhbHNlKCIzLjEiLCB0ZXh0LmlzQXNzb2NpYXRlZFdpdGgoInh5ei5mb28iKSk7CgkJYXNzZXJ0RmFsc2UoIjMuMiIsIHRleHQuaXNBc3NvY2lhdGVkV2l0aCgieHl6LmJhciIpKTsKCQlhc3NlcnRGYWxzZSgiMy4zIiwgdGV4dC5pc0Fzc29jaWF0ZWRXaXRoKCJmb28uZXh0IikpOwoJCWFzc2VydEZhbHNlKCIzLjQiLCB0ZXh0LmlzQXNzb2NpYXRlZFdpdGgoImJhci5leHQiKSk7CgoJCS8vIGVuc3VyZSB0aGUgc2VyaWFsaXphdGlvbiBmb3JtYXQgaXMgY29ycmVjdAoJCXRyeSB7CgkJCXRleHQuYWRkRmlsZVNwZWMoImZvby5iYXIiLCBJQ29udGVudFR5cGUuRklMRV9OQU1FX1NQRUMpOwoJCQl0ZXh0UHJlZnMuc3luYygpOwoJCQlhc3NlcnRFcXVhbHMoIjQuMCIsICJmb28uYmFyIiwgdGV4dFByZWZzLmdldChDb250ZW50VHlwZS5QUkVGX0ZJTEVfTkFNRVMsIG51bGwpKTsKCQl9IGZpbmFsbHkgewoJCQkvLyBjbGVhbi11cAoJCQl0ZXh0LnJlbW92ZUZpbGVTcGVjKCJmb28uYmFyIiwgSUNvbnRlbnRUeXBlLkZJTEVfTkFNRV9TUEVDKTsKCQl9Cgl9CgoJQFRlc3QKCXB1YmxpYyB2b2lkIHRlc3RSZWdpc3RyeSgpIHsKCQlJQ29udGVudFR5cGVNYW5hZ2VyIGNvbnRlbnRUeXBlTWFuYWdlciA9IFBsYXRmb3JtLmdldENvbnRlbnRUeXBlTWFuYWdlcigpOwoJCUlDb250ZW50VHlwZU1hdGNoZXIgZmluZGVyID0gY29udGVudFR5cGVNYW5hZ2VyLmdldE1hdGNoZXIobmV3IExvY2FsU2VsZWN0aW9uUG9saWN5KCksIG51bGwpOwoKCQlJQ29udGVudFR5cGUgdGV4dENvbnRlbnRUeXBlID0gY29udGVudFR5cGVNYW5hZ2VyLmdldENvbnRlbnRUeXBlKFBsYXRmb3JtLlBJX1JVTlRJTUUgKyAnLicgKyAidGV4dCIpOwoJCWFzc2VydE5vdE51bGwoIjEuMCIsIHRleHRDb250ZW50VHlwZSk7CgkJYXNzZXJ0VHJ1ZSgiMS4xIiwgaXNUZXh0KGNvbnRlbnRUeXBlTWFuYWdlciwgdGV4dENvbnRlbnRUeXBlKSk7CgkJYXNzZXJ0Tm90TnVsbCgiMS4yIiwgKChDb250ZW50VHlwZUhhbmRsZXIpIHRleHRDb250ZW50VHlwZSkuZ2V0VGFyZ2V0KCkuZ2V0RGVzY3JpYmVyKCkpOwoKCQlJQ29udGVudFR5cGUgeG1sQ29udGVudFR5cGUgPSBjb250ZW50VHlwZU1hbmFnZXIuZ2V0Q29udGVudFR5cGUoUGxhdGZvcm0uUElfUlVOVElNRSArICIueG1sIik7CgkJYXNzZXJ0Tm90TnVsbCgiMi4wIiwgeG1sQ29udGVudFR5cGUpOwoJCWFzc2VydFRydWUoIjIuMSIsIGlzVGV4dChjb250ZW50VHlwZU1hbmFnZXIsIHhtbENvbnRlbnRUeXBlKSk7CgkJYXNzZXJ0RXF1YWxzKCIyLjIiLCB0ZXh0Q29udGVudFR5cGUsIHhtbENvbnRlbnRUeXBlLmdldEJhc2VUeXBlKCkpOwoJCUlDb250ZW50RGVzY3JpYmVyIHhtbERlc2NyaWJlciA9ICgoQ29udGVudFR5cGVIYW5kbGVyKSB4bWxDb250ZW50VHlwZSkuZ2V0VGFyZ2V0KCkuZ2V0RGVzY3JpYmVyKCk7CgkJYXNzZXJ0Tm90TnVsbCgiMi4zIiwgeG1sRGVzY3JpYmVyKTsKCQlhc3NlcnRUcnVlKCIyLjQiLCB4bWxEZXNjcmliZXIgaW5zdGFuY2VvZiBYTUxDb250ZW50RGVzY3JpYmVyKTsKCgkJSUNvbnRlbnRUeXBlIHhtbEJhc2VkRGlmZmVyZW50RXh0ZW5zaW9uQ29udGVudFR5cGUgPSBjb250ZW50VHlwZU1hbmFnZXIKCQkJCS5nZXRDb250ZW50VHlwZShQSV9SRVNPVVJDRVNfVEVTVFMgKyAnLicgKyAieG1sLWJhc2VkLWRpZmZlcmVudC1leHRlbnNpb24iKTsKCQlhc3NlcnROb3ROdWxsKCIzLjAiLCB4bWxCYXNlZERpZmZlcmVudEV4dGVuc2lvbkNvbnRlbnRUeXBlKTsKCQlhc3NlcnRUcnVlKCIzLjEiLCBpc1RleHQoY29udGVudFR5cGVNYW5hZ2VyLCB4bWxCYXNlZERpZmZlcmVudEV4dGVuc2lvbkNvbnRlbnRUeXBlKSk7CgkJYXNzZXJ0RXF1YWxzKCIzLjIiLCB4bWxDb250ZW50VHlwZSwgeG1sQmFzZWREaWZmZXJlbnRFeHRlbnNpb25Db250ZW50VHlwZS5nZXRCYXNlVHlwZSgpKTsKCgkJSUNvbnRlbnRUeXBlIHhtbEJhc2VkU3BlY2lmaWNOYW1lQ29udGVudFR5cGUgPSBjb250ZW50VHlwZU1hbmFnZXIKCQkJCS5nZXRDb250ZW50VHlwZShQSV9SRVNPVVJDRVNfVEVTVFMgKyAnLicgKyAieG1sLWJhc2VkLXNwZWNpZmljLW5hbWUiKTsKCQlhc3NlcnROb3ROdWxsKCI0LjAiLCB4bWxCYXNlZFNwZWNpZmljTmFtZUNvbnRlbnRUeXBlKTsKCQlhc3NlcnRUcnVlKCI0LjEiLCBpc1RleHQoY29udGVudFR5cGVNYW5hZ2VyLCB4bWxCYXNlZFNwZWNpZmljTmFtZUNvbnRlbnRUeXBlKSk7CgkJYXNzZXJ0RXF1YWxzKCI0LjIiLCB4bWxDb250ZW50VHlwZSwgeG1sQmFzZWRTcGVjaWZpY05hbWVDb250ZW50VHlwZS5nZXRCYXNlVHlwZSgpKTsKCgkJSUNvbnRlbnRUeXBlW10geG1sVHlwZXMgPSBmaW5kZXIuZmluZENvbnRlbnRUeXBlc0ZvcihjaGFuZ2VDYXNlKCJmb28ueG1sIikpOwoJCWFzc2VydFRydWUoIjUuMSIsIGNvbnRhaW5zKHhtbFR5cGVzLCB4bWxDb250ZW50VHlwZSkpOwoKCQlJQ29udGVudFR5cGUgYmluYXJ5Q29udGVudFR5cGUgPSBjb250ZW50VHlwZU1hbmFnZXIuZ2V0Q29udGVudFR5cGUoUElfUkVTT1VSQ0VTX1RFU1RTICsgJy4nICsgInNhbXBsZS1iaW5hcnkxIik7CgkJYXNzZXJ0Tm90TnVsbCgiNi4wIiwgYmluYXJ5Q29udGVudFR5cGUpOwoJCWFzc2VydEZhbHNlKCI2LjEiLCBpc1RleHQoY29udGVudFR5cGVNYW5hZ2VyLCBiaW5hcnlDb250ZW50VHlwZSkpOwoJCWFzc2VydE51bGwoIjYuMiIsIGJpbmFyeUNvbnRlbnRUeXBlLmdldEJhc2VUeXBlKCkpOwoKCQlJQ29udGVudFR5cGVbXSBiaW5hcnlUeXBlcyA9IGZpbmRlci5maW5kQ29udGVudFR5cGVzRm9yKGNoYW5nZUNhc2UoImZvby5zYW1wbGViaW4xIikpOwoJCWFzc2VydEVxdWFscygiNy4wIiwgMSwgYmluYXJ5VHlwZXMubGVuZ3RoKTsKCQlhc3NlcnRFcXVhbHMoIjcuMSIsIGJpbmFyeUNvbnRlbnRUeXBlLCBiaW5hcnlUeXBlc1swXSk7CgoJCUlDb250ZW50VHlwZSBteVRleHQgPSBjb250ZW50VHlwZU1hbmFnZXIuZ2V0Q29udGVudFR5cGUoUElfUkVTT1VSQ0VTX1RFU1RTICsgIi5teXRleHQiKTsKCQlhc3NlcnROb3ROdWxsKCI4LjAiLCBteVRleHQpOwoJCWFzc2VydEVxdWFscygiOC4xIiwgIkJBUiIsIG15VGV4dC5nZXREZWZhdWx0Q2hhcnNldCgpKTsKCgkJSUNvbnRlbnRUeXBlW10gZm9vQmFyVHlwZXMgPSBmaW5kZXIuZmluZENvbnRlbnRUeXBlc0ZvcihjaGFuZ2VDYXNlKCJmb28uYmFyIikpOwoJCWFzc2VydEVxdWFscygiOS4wIiwgMiwgZm9vQmFyVHlwZXMubGVuZ3RoKTsKCgkJSUNvbnRlbnRUeXBlIGZvb0JhciA9IGNvbnRlbnRUeXBlTWFuYWdlci5nZXRDb250ZW50VHlwZShQSV9SRVNPVVJDRVNfVEVTVFMgKyAiLmZvb0JhciIpOwoJCWFzc2VydE5vdE51bGwoIjkuMSIsIGZvb0Jhcik7CgkJSUNvbnRlbnRUeXBlIHN1YkZvb0JhciA9IGNvbnRlbnRUeXBlTWFuYWdlci5nZXRDb250ZW50VHlwZShQSV9SRVNPVVJDRVNfVEVTVFMgKyAiLnN1YkZvb0JhciIpOwoJCWFzc2VydE5vdE51bGwoIjkuMiIsIHN1YkZvb0Jhcik7CgkJYXNzZXJ0VHJ1ZSgiOS4zIiwgY29udGFpbnMoZm9vQmFyVHlwZXMsIGZvb0JhcikpOwoJCWFzc2VydFRydWUoIjkuNCIsIGNvbnRhaW5zKGZvb0JhclR5cGVzLCBzdWJGb29CYXIpKTsKCX0KCglAVGVzdAoJcHVibGljIHZvaWQgdGVzdFJvb3RFbGVtZW50QW5kRFRERGVzY3JpYmVyKCkgdGhyb3dzIElPRXhjZXB0aW9uIHsKCQlJQ29udGVudFR5cGVNYW5hZ2VyIGNvbnRlbnRUeXBlTWFuYWdlciA9IFBsYXRmb3JtLmdldENvbnRlbnRUeXBlTWFuYWdlcigpOwoJCUlDb250ZW50VHlwZSByb290RWxlbWVudCA9IGNvbnRlbnRUeXBlTWFuYWdlci5nZXRDb250ZW50VHlwZShQSV9SRVNPVVJDRVNfVEVTVFMgKyAiLnJvb3QtZWxlbWVudCIpOwoJCUlDb250ZW50VHlwZSBkdGRFbGVtZW50ID0gY29udGVudFR5cGVNYW5hZ2VyLmdldENvbnRlbnRUeXBlKFBJX1JFU09VUkNFU19URVNUUyArICIuZHRkIik7CgkJSUNvbnRlbnRUeXBlIG5zUm9vdEVsZW1lbnQgPSBjb250ZW50VHlwZU1hbmFnZXIuZ2V0Q29udGVudFR5cGUoUElfUkVTT1VSQ0VTX1RFU1RTICsgIi5ucy1yb290LWVsZW1lbnQiKTsKCQlJQ29udGVudFR5cGUgbnNXaWxkY2FyZCA9IGNvbnRlbnRUeXBlTWFuYWdlci5nZXRDb250ZW50VHlwZShQSV9SRVNPVVJDRVNfVEVTVFMgKyAiLm5zLXdpbGRjYXJkIik7CgkJSUNvbnRlbnRUeXBlIGVtcHR5TnNSb290RWxlbWVudCA9IGNvbnRlbnRUeXBlTWFuYWdlcgoJCQkJLmdldENvbnRlbnRUeXBlKFBJX1JFU09VUkNFU19URVNUUyArICIuZW1wdHktbnMtcm9vdC1lbGVtZW50Iik7CgkJSUNvbnRlbnRUeXBlIHhtbFR5cGUgPSBjb250ZW50VHlwZU1hbmFnZXIuZ2V0Q29udGVudFR5cGUoUGxhdGZvcm0uUElfUlVOVElNRSArICIueG1sIik7CgoJCUlDb250ZW50VHlwZVtdIGNvbnRlbnRUeXBlcyA9IGNvbnRlbnRUeXBlTWFuYWdlci5maW5kQ29udGVudFR5cGVzRm9yKAoJCQkJZ2V0SW5wdXRTdHJlYW0oWE1MX1JPT1RfRUxFTUVOVF9JU09fODg1OV8xLCBTdGFuZGFyZENoYXJzZXRzLklTT184ODU5XzEpLCAiZmFrZS54bWwiKTsKCQlhc3NlcnRUcnVlKCIxLjAiLCBjb250ZW50VHlwZXMubGVuZ3RoID4gMCk7CgkJYXNzZXJ0RXF1YWxzKCIxLjEiLCByb290RWxlbWVudCwgY29udGVudFR5cGVzWzBdKTsKCgkJLy8gYnVncyA2NDA1MyBhbmQgNjMyOTgKCQljb250ZW50VHlwZXMgPSBjb250ZW50VHlwZU1hbmFnZXIuZmluZENvbnRlbnRUeXBlc0ZvcigKCQkJCWdldElucHV0U3RyZWFtKFhNTF9ST09UX0VMRU1FTlRfRVhURVJOQUxfRU5USVRZLCBTdGFuZGFyZENoYXJzZXRzLlVURl84KSwgImZha2UueG1sIik7CgkJYXNzZXJ0VHJ1ZSgiMi4wIiwgY29udGVudFR5cGVzLmxlbmd0aCA+IDApOwoJCWFzc2VydEVxdWFscygiMi4xIiwgcm9vdEVsZW1lbnQsIGNvbnRlbnRUeXBlc1swXSk7CgoJCS8vIGJ1ZyA2MzYyNQoJCWNvbnRlbnRUeXBlcyA9IGNvbnRlbnRUeXBlTWFuYWdlci5maW5kQ29udGVudFR5cGVzRm9yKAoJCQkJZ2V0SW5wdXRTdHJlYW0oWE1MX1JPT1RfRUxFTUVOVF9FWFRFUk5BTF9FTlRJVFkyLCBTdGFuZGFyZENoYXJzZXRzLlVURl84KSwgImZha2UueG1sIik7CgkJYXNzZXJ0VHJ1ZSgiMy4wIiwgY29udGVudFR5cGVzLmxlbmd0aCA+IDApOwoJCWFzc2VydEVxdWFscygiMy4xIiwgcm9vdEVsZW1lbnQsIGNvbnRlbnRUeXBlc1swXSk7CgoJCS8vIGJ1ZyAxMzU1NzUKCQljb250ZW50VHlwZXMgPSBjb250ZW50VHlwZU1hbmFnZXIKCQkJCS5maW5kQ29udGVudFR5cGVzRm9yKGdldElucHV0U3RyZWFtKFhNTF9ST09UX0VMRU1FTlRfTlNfTUFUQ0gxLCBTdGFuZGFyZENoYXJzZXRzLlVURl84KSwgImZha2UueG1sIik7CgkJYXNzZXJ0VHJ1ZSgiNC4wIiwgY29udGVudFR5cGVzLmxlbmd0aCA+IDApOwoJCWFzc2VydEVxdWFscygiNC4xIiwgbnNSb290RWxlbWVudCwgY29udGVudFR5cGVzWzBdKTsKCQljb250ZW50VHlwZXMgPSBjb250ZW50VHlwZU1hbmFnZXIKCQkJCS5maW5kQ29udGVudFR5cGVzRm9yKGdldElucHV0U3RyZWFtKFhNTF9ST09UX0VMRU1FTlRfTlNfTUFUQ0gyLCBTdGFuZGFyZENoYXJzZXRzLlVURl84KSwgImZha2UueG1sIik7CgkJYXNzZXJ0VHJ1ZSgiNC4yIiwgY29udGVudFR5cGVzLmxlbmd0aCA+IDApOwoJCWFzc2VydEVxdWFscygiNC4zIiwgbnNSb290RWxlbWVudCwgY29udGVudFR5cGVzWzBdKTsKCQljb250ZW50VHlwZXMgPSBjb250ZW50VHlwZU1hbmFnZXIuZmluZENvbnRlbnRUeXBlc0ZvcigKCQkJCWdldElucHV0U3RyZWFtKFhNTF9ST09UX0VMRU1FTlRfTlNfV1JPTkdfRUxFTSwgU3RhbmRhcmRDaGFyc2V0cy5VVEZfOCksICJmYWtlLnhtbCIpOwoJCWFzc2VydFRydWUoIjQuNCIsIGNvbnRlbnRUeXBlcy5sZW5ndGggPiAwKTsKCQlhc3NlcnRFcXVhbHMoIjQuNSIsIHhtbFR5cGUsIGNvbnRlbnRUeXBlc1swXSk7CgkJY29udGVudFR5cGVzID0gY29udGVudFR5cGVNYW5hZ2VyCgkJCQkuZmluZENvbnRlbnRUeXBlc0ZvcihnZXRJbnB1dFN0cmVhbShYTUxfUk9PVF9FTEVNRU5UX05TX1dST05HX05TLCBTdGFuZGFyZENoYXJzZXRzLlVURl84KSwgImZha2UueG1sIik7CgkJYXNzZXJ0VHJ1ZSgiNC42IiwgY29udGVudFR5cGVzLmxlbmd0aCA+IDApOwoJCWFzc2VydEVxdWFscygiNC43IiwgeG1sVHlwZSwgY29udGVudFR5cGVzWzBdKTsKCQljb250ZW50VHlwZXMgPSBjb250ZW50VHlwZU1hbmFnZXIKCQkJCS5maW5kQ29udGVudFR5cGVzRm9yKGdldElucHV0U3RyZWFtKFhNTF9ST09UX0VMRU1FTlRfTlNfTUlYVVAsIFN0YW5kYXJkQ2hhcnNldHMuVVRGXzgpLCAiZmFrZS54bWwiKTsKCQlhc3NlcnRUcnVlKCI0LjgiLCBjb250ZW50VHlwZXMubGVuZ3RoID4gMCk7CgkJYXNzZXJ0RXF1YWxzKCI0LjkiLCB4bWxUeXBlLCBjb250ZW50VHlwZXNbMF0pOwoJCWNvbnRlbnRUeXBlcyA9IGNvbnRlbnRUeXBlTWFuYWdlcgoJCQkJLmZpbmRDb250ZW50VHlwZXNGb3IoZ2V0SW5wdXRTdHJlYW0oWE1MX1JPT1RfRUxFTUVOVF9OU19XSUxEQ0FSRCwgU3RhbmRhcmRDaGFyc2V0cy5VVEZfOCksICJmYWtlLnhtbCIpOwoJCWFzc2VydFRydWUoIjQuMTAiLCBjb250ZW50VHlwZXMubGVuZ3RoID4gMCk7CgkJYXNzZXJ0RXF1YWxzKCI0LjExIiwgbnNXaWxkY2FyZCwgY29udGVudFR5cGVzWzBdKTsKCQljb250ZW50VHlwZXMgPSBjb250ZW50VHlwZU1hbmFnZXIKCQkJCS5maW5kQ29udGVudFR5cGVzRm9yKGdldElucHV0U3RyZWFtKFhNTF9ST09UX0VMRU1FTlRfTlNfV0lMRENBUkQyLCBTdGFuZGFyZENoYXJzZXRzLlVURl84KSwgImZha2UueG1sIik7CgkJYXNzZXJ0VHJ1ZSgiNC4xMiIsIGNvbnRlbnRUeXBlcy5sZW5ndGggPiAwKTsKCQlhc3NlcnRFcXVhbHMoIjQuMTMiLCBuc1dpbGRjYXJkLCBjb250ZW50VHlwZXNbMF0pOwoJCWNvbnRlbnRUeXBlcyA9IGNvbnRlbnRUeXBlTWFuYWdlcgoJCQkJLmZpbmRDb250ZW50VHlwZXNGb3IoZ2V0SW5wdXRTdHJlYW0oWE1MX1JPT1RfRUxFTUVOVF9FTVBUWV9OUywgU3RhbmRhcmRDaGFyc2V0cy5VVEZfOCksICJmYWtlLnhtbCIpOwoJCWFzc2VydFRydWUoIjQuMTQiLCBjb250ZW50VHlwZXMubGVuZ3RoID4gMCk7CgkJYXNzZXJ0RXF1YWxzKCI0LjE1IiwgZW1wdHlOc1Jvb3RFbGVtZW50LCBjb250ZW50VHlwZXNbMF0pOwoKCQljb250ZW50VHlwZXMgPSBjb250ZW50VHlwZU1hbmFnZXIKCQkJCS5maW5kQ29udGVudFR5cGVzRm9yKGdldElucHV0U3RyZWFtKFhNTF9EVERfVVNfQVNDSUksIFN0YW5kYXJkQ2hhcnNldHMuVVNfQVNDSUkpLCAiZmFrZS54bWwiKTsKCQlhc3NlcnRUcnVlKCI1LjAiLCBjb250ZW50VHlwZXMubGVuZ3RoID4gMCk7CgkJYXNzZXJ0RXF1YWxzKCI1LjEiLCBkdGRFbGVtZW50LCBjb250ZW50VHlwZXNbMF0pOwoJCWNvbnRlbnRUeXBlcyA9IGNvbnRlbnRUeXBlTWFuYWdlcgoJCQkJLmZpbmRDb250ZW50VHlwZXNGb3IoZ2V0SW5wdXRTdHJlYW0oWE1MX0RURF9FWFRFUk5BTF9FTlRJVFksIFN0YW5kYXJkQ2hhcnNldHMuVVRGXzgpLCAiZmFrZS54bWwiKTsKCQlhc3NlcnRUcnVlKCI1LjQiLCBjb250ZW50VHlwZXMubGVuZ3RoID4gMCk7CgkJYXNzZXJ0RXF1YWxzKCI1LjUiLCBkdGRFbGVtZW50LCBjb250ZW50VHlwZXNbMF0pOwoKCQkvLyBidWcgNjc5NzUKCQlJQ29udGVudERlc2NyaXB0aW9uIGRlc2NyaXB0aW9uID0gY29udGVudFR5cGVNYW5hZ2VyLmdldERlc2NyaXB0aW9uRm9yKGdldElucHV0U3RyZWFtKAoJCQkJbmV3IGJ5dGVbXVtdIHsgSUNvbnRlbnREZXNjcmlwdGlvbi5CT01fVVRGXzE2QkUsIFhNTF9ST09UX0VMRU1FTlRfTk9fREVDTC5nZXRCeXRlcygiVVRGLTE2QkUiKSB9KSwKCQkJCSJmYWtlLnhtbCIsIElDb250ZW50RGVzY3JpcHRpb24uQUxMKTsKCQlhc3NlcnROb3ROdWxsKCI2LjAiLCBkZXNjcmlwdGlvbik7CgkJYXNzZXJ0RXF1YWxzKCI2LjEiLCByb290RWxlbWVudCwgZGVzY3JpcHRpb24uZ2V0Q29udGVudFR5cGUoKSk7CgkJYXNzZXJ0RXF1YWxzKCI2LjIiLCBJQ29udGVudERlc2NyaXB0aW9uLkJPTV9VVEZfMTZCRSwKCQkJCWRlc2NyaXB0aW9uLmdldFByb3BlcnR5KElDb250ZW50RGVzY3JpcHRpb24uQllURV9PUkRFUl9NQVJLKSk7CgoJCWRlc2NyaXB0aW9uID0gY29udGVudFR5cGVNYW5hZ2VyLmdldERlc2NyaXB0aW9uRm9yKGdldElucHV0U3RyZWFtKAoJCQkJbmV3IGJ5dGVbXVtdIHsgSUNvbnRlbnREZXNjcmlwdGlvbi5CT01fVVRGXzE2TEUsIFhNTF9ST09UX0VMRU1FTlRfTk9fREVDTC5nZXRCeXRlcygiVVRGLTE2TEUiKSB9KSwKCQkJCSJmYWtlLnhtbCIsIElDb250ZW50RGVzY3JpcHRpb24uQUxMKTsKCQlhc3NlcnROb3ROdWxsKCI3LjAiLCBkZXNjcmlwdGlvbik7CgkJYXNzZXJ0RXF1YWxzKCI3LjEiLCByb290RWxlbWVudCwgZGVzY3JpcHRpb24uZ2V0Q29udGVudFR5cGUoKSk7CgkJYXNzZXJ0RXF1YWxzKCI3LjIiLCBJQ29udGVudERlc2NyaXB0aW9uLkJPTV9VVEZfMTZMRSwKCQkJCWRlc2NyaXB0aW9uLmdldFByb3BlcnR5KElDb250ZW50RGVzY3JpcHRpb24uQllURV9PUkRFUl9NQVJLKSk7CgoJCS8vIGR1ZSB0byBidWcgNjcwNDgsIHRoZSB0ZXN0IGJlbG93IGZhaWxzIHdpdGggQ3JpbXNvbiBwYXJzZXIgKGRvZXMgbm90IGhhbmRsZQoJCS8vIFVURi04IEJPTXMpCgkJLy8gZGVzY3JpcHRpb24gPSBjb250ZW50VHlwZU1hbmFnZXIuZ2V0RGVzY3JpcHRpb25Gb3IoZ2V0SW5wdXRTdHJlYW0obmV3CgkJLy8gYnl0ZVtdW10KCQkvLyB7SUNvbnRlbnREZXNjcmlwdGlvbi5CT01fVVRGXzgsWE1MX1JPT1RfRUxFTUVOVF9OT19ERUNMLmdldEJ5dGVzKCJVVEYtOCIpfSksCgkJLy8gImZha2UueG1sIiwgSUNvbnRlbnREZXNjcmlwdGlvbi5BTEwpOwoJCS8vIGFzc2VydFRydWUoIjcuMCIsIGRlc2NyaXB0aW9uICE9IG51bGwpOwoJCS8vIGFzc2VydEVxdWFscygiNy4xIiwgcm9vdEVsZW1lbnQsIGRlc2NyaXB0aW9uLmdldENvbnRlbnRUeXBlKCkpOwoJCS8vIGFzc2VydEVxdWFscygiNy4yIiwgSUNvbnRlbnREZXNjcmlwdGlvbi5CT01fVVRGXzgsCgkJLy8gZGVzY3JpcHRpb24uZ2V0UHJvcGVydHkoSUNvbnRlbnREZXNjcmlwdGlvbi5CWVRFX09SREVSX01BUkspKTsKCgkJLy8gYnVnIDg0MzU0CgkJY29udGVudFR5cGVzID0gY29udGVudFR5cGVNYW5hZ2VyCgkJCQkuZmluZENvbnRlbnRUeXBlc0ZvcihnZXRJbnB1dFN0cmVhbShYTUxfUk9PVF9FTEVNRU5UX05PX0RFQ0wsIFN0YW5kYXJkQ2hhcnNldHMuVVRGXzgpLCAidGVzdC50eHQiKTsKCQlhc3NlcnRUcnVlKCI4LjAiLCBjb250ZW50VHlwZXMubGVuZ3RoID4gMCk7CgkJYXNzZXJ0RXF1YWxzKCI4LjEiLCBjb250ZW50VHlwZU1hbmFnZXIuZ2V0Q29udGVudFR5cGUoSUNvbnRlbnRUeXBlTWFuYWdlci5DVF9URVhUKSwgY29udGVudFR5cGVzWzBdKTsKCX0KCgkvKioKCSAqIEJ1ZyA2Njk3NgoJICovCglAVGVzdAoJcHVibGljIHZvaWQgdGVzdFNpZ25hdHVyZUJleW9uZEJ1ZmZlckxpbWl0KCkgdGhyb3dzIElPRXhjZXB0aW9uIHsKCQlpbnQgYnVmZmVyTGltaXQgPSBDb250ZW50VHlwZU1hbmFnZXIuQkxPQ0tfU0laRSAqIDQ7CgkJLy8gY3JlYXRlIGEgbG9uZyBYTUwgY29tbWVudCBhcyBwcmVmaXgKCQlTdHJpbmdCdWlsZGVyIGNvbW1lbnQgPSBuZXcgU3RyaW5nQnVpbGRlcigiPCEtLSIpOwoJCWZvciAoaW50IGkgPSAwOyBpIDwgYnVmZmVyTGltaXQ7IGkrKykgewoJCQljb21tZW50LmFwcGVuZCgnKicpOwoJCX0KCQljb21tZW50LmFwcGVuZCgiLS0+Iik7CgkJSUNvbnRlbnRUeXBlTWFuYWdlciBtYW5hZ2VyID0gUGxhdGZvcm0uZ2V0Q29udGVudFR5cGVNYW5hZ2VyKCk7CgkJSUNvbnRlbnRUeXBlIHJvb3RFbGVtZW50ID0gbWFuYWdlci5nZXRDb250ZW50VHlwZShQSV9SRVNPVVJDRVNfVEVTVFMgKyAiLnJvb3QtZWxlbWVudCIpOwoJCUlDb250ZW50VHlwZSBzZWxlY3RlZCA9IG1hbmFnZXIuZmluZENvbnRlbnRUeXBlRm9yKAoJCQkJZ2V0SW5wdXRTdHJlYW0oY29tbWVudCArIFhNTF9ST09UX0VMRU1FTlRfTk9fREVDTCwgU3RhbmRhcmRDaGFyc2V0cy5VU19BU0NJSSksICJmYWtlLnhtbCIpOwoJCWFzc2VydE5vdE51bGwoIjEuMCIsIHNlbGVjdGVkKTsKCQlhc3NlcnRFcXVhbHMoIjEuMSIsIHJvb3RFbGVtZW50LCBzZWxlY3RlZCk7Cgl9CgoJLyoqCgkgKiBTZWUgYWxzbzogYnVnIDcyNzk2LgoJICovCglAVGVzdAoJcHVibGljIHZvaWQgdGVzdFVzZXJEZWZpbmVkQXNzb2NpYXRpb25zKCkgdGhyb3dzIENvcmVFeGNlcHRpb24gewoJCUlDb250ZW50VHlwZU1hbmFnZXIgbWFuYWdlciA9IFBsYXRmb3JtLmdldENvbnRlbnRUeXBlTWFuYWdlcigpOwoJCUlDb250ZW50VHlwZSB0ZXh0ID0gbWFuYWdlci5nZXRDb250ZW50VHlwZSgoUGxhdGZvcm0uUElfUlVOVElNRSArICIudGV4dCIpKTsKCgkJYXNzZXJ0TnVsbCgiMC4xIiwgbWFuYWdlci5maW5kQ29udGVudFR5cGVGb3IoInRlc3QubXl0ZXh0IikpOwoJCS8vIGFzc29jaWF0ZSBhIHVzZXItZGVmaW5lZCBmaWxlIHNwZWMKCQl0ZXh0LmFkZEZpbGVTcGVjKCJteXRleHQiLCBJQ29udGVudFR5cGUuRklMRV9FWFRFTlNJT05fU1BFQyk7CgkJYm9vbGVhbiBhc3NlcnRpb25GYWlsZWQgPSBmYWxzZTsKCQl0cnkgewoJCQlJQ29udGVudFR5cGUgcmVzdWx0ID0gbWFuYWdlci5maW5kQ29udGVudFR5cGVGb3IoInRlc3QubXl0ZXh0Iik7CgkJCWFzc2VydE5vdE51bGwoIjEuMSIsIHJlc3VsdCk7CgkJCWFzc2VydEVxdWFscygiMS4yIiwgdGV4dCwgcmVzdWx0KTsKCQl9IGNhdGNoIChBc3NlcnRpb25FcnJvciBhZmUpIHsKCQkJYXNzZXJ0aW9uRmFpbGVkID0gdHJ1ZTsKCQkJdGhyb3cgYWZlOwoJCX0gZmluYWxseSB7CgkJCXRleHQucmVtb3ZlRmlsZVNwZWMoIm15dGV4dCIsIElDb250ZW50VHlwZS5GSUxFX0VYVEVOU0lPTl9TUEVDKTsKCQkJYXNzZXJ0RmFsc2UoYXNzZXJ0aW9uRmFpbGVkKTsKCQl9CgkJSUNvbnRlbnRUeXBlIHJlc3VsdCA9IG1hbmFnZXIuZmluZENvbnRlbnRUeXBlRm9yKCJ0ZXN0Lm15dGV4dCIpOwoJCWFzc2VydE51bGwoIjMuMCIsIHJlc3VsdCk7Cgl9CgoJQFRlc3QKCXB1YmxpYyB2b2lkIHRlc3REZXNjcmliZXJJbnZhbGlkYXRpb24oKSB0aHJvd3MgSU9FeGNlcHRpb24gewoJCUlDb250ZW50VHlwZU1hbmFnZXIgY29udGVudFR5cGVNYW5hZ2VyID0gUGxhdGZvcm0uZ2V0Q29udGVudFR5cGVNYW5hZ2VyKCk7CgkJSUNvbnRlbnRUeXBlIHR5cGVfYnVnMTgyMzM3X0EgPSBjb250ZW50VHlwZU1hbmFnZXIuZ2V0Q29udGVudFR5cGUoUElfUkVTT1VSQ0VTX1RFU1RTICsgIi5CdWcxODIzMzdfQSIpOwoJCUlDb250ZW50VHlwZSB0eXBlX2J1ZzE4MjMzN19CID0gY29udGVudFR5cGVNYW5hZ2VyLmdldENvbnRlbnRUeXBlKFBJX1JFU09VUkNFU19URVNUUyArICIuQnVnMTgyMzM3X0IiKTsKCgkJSUNvbnRlbnRUeXBlW10gY29udGVudFR5cGVzID0gY29udGVudFR5cGVNYW5hZ2VyLmZpbmRDb250ZW50VHlwZXNGb3IoCgkJCQlnZXRJbnB1dFN0cmVhbShYTUxfUk9PVF9FTEVNRU5UX05TX01BVENIMiwgU3RhbmRhcmRDaGFyc2V0cy5VVEZfOCksICJCdWcxODIzMzcuQnVnMTgyMzM3Iik7CgkJYXNzZXJ0RXF1YWxzKCIxLjAiLCAyLCBjb250ZW50VHlwZXMubGVuZ3RoKTsKCQlhc3NlcnRFcXVhbHMoIjEuMSIsIHR5cGVfYnVnMTgyMzM3X0EsIGNvbnRlbnRUeXBlc1swXSk7CgkJYXNzZXJ0RXF1YWxzKCIxLjEiLCB0eXBlX2J1ZzE4MjMzN19CLCBjb250ZW50VHlwZXNbMV0pOwoKCQlJbnB1dFN0cmVhbSBpcyA9IG5ldyBJbnB1dFN0cmVhbSgpIHsKCQkJQE92ZXJyaWRlCgkJCXB1YmxpYyBpbnQgcmVhZCgpIHsKCQkJCS8vIHRocm93IGEgbm9uIGNoZWNrZWQgZXhjZXB0aW9uIHRvIGVtdWxhdGUgYSBwcm9ibGVtIHdpdGggdGhlIGRlc2NyaWJlciBpdHNlbGYKCQkJCXRocm93IG5ldyBSdW50aW1lRXhjZXB0aW9uKCk7CgkJCX0KCQl9OwoJCWNvbnRlbnRUeXBlcyA9IGNvbnRlbnRUeXBlTWFuYWdlci5maW5kQ29udGVudFR5cGVzRm9yKGlzLCAiQnVnMTgyMzM3LkJ1ZzE4MjMzNyIpOwoJCWFzc2VydEVxdWFscygiMS4yIiwgMCwgY29udGVudFR5cGVzLmxlbmd0aCk7CgoJCS8vIERlc2NyaWJlciBzaG91bGQgYmUgaW52YWxpZGF0ZWQgYnkgbm93CgkJY29udGVudFR5cGVzID0gY29udGVudFR5cGVNYW5hZ2VyLmZpbmRDb250ZW50VHlwZXNGb3IoCgkJCQlnZXRJbnB1dFN0cmVhbShYTUxfUk9PVF9FTEVNRU5UX05TX01BVENIMiwgU3RhbmRhcmRDaGFyc2V0cy5VVEZfOCksICJCdWcxODIzMzcuQnVnMTgyMzM3Iik7CgkJYXNzZXJ0RXF1YWxzKCIxLjMiLCAwLCBjb250ZW50VHlwZXMubGVuZ3RoKTsKCX0KCn0K