LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogQ29weXJpZ2h0IChjKSAyMDA2LCAyMDA4IEVjbGlwc2UgRm91bmRhdGlvbgogKiBBbGwgcmlnaHRzIHJlc2VydmVkLiBUaGlzIHByb2dyYW0gYW5kIHRoZSBhY2NvbXBhbnlpbmcgbWF0ZXJpYWxzCiAqIGFyZSBtYWRlIGF2YWlsYWJsZSB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEVjbGlwc2UgUHVibGljIExpY2Vuc2UgdjEuMAogKiB3aGljaCBhY2NvbXBhbmllcyB0aGlzIGRpc3RyaWJ1dGlvbiwgYW5kIGlzIGF2YWlsYWJsZSBhdAogKiBodHRwOi8vd3d3LmVjbGlwc2Uub3JnL2xlZ2FsL2VwbC12MTAuaHRtbAogKiAKICogQ29udHJpYnV0b3JzOgogKiAgICAgSmVzcGVyIFN0ZWVuIE34bGxlciAtIGplc3BlckBzZWxza2FiZXQub3JnCiAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLwpwYWNrYWdlIG9yZy5lY2xpcHNlLndzdC54bWwuY29yZS50ZXN0cy5mb3JtYXQ7CgppbXBvcnQgamF2YS5pby5CeXRlQXJyYXlPdXRwdXRTdHJlYW07CmltcG9ydCBqYXZhLmlvLkZpbGVOb3RGb3VuZEV4Y2VwdGlvbjsKaW1wb3J0IGphdmEuaW8uSU9FeGNlcHRpb247CmltcG9ydCBqYXZhLmlvLklucHV0U3RyZWFtOwppbXBvcnQgamF2YS5pby5VbnN1cHBvcnRlZEVuY29kaW5nRXhjZXB0aW9uOwoKaW1wb3J0IGp1bml0LmZyYW1ld29yay5UZXN0Q2FzZTsKCmltcG9ydCBvcmcuZWNsaXBzZS5jb3JlLnJlc291cmNlcy5JQ29udGFpbmVyOwppbXBvcnQgb3JnLmVjbGlwc2UuY29yZS5yZXNvdXJjZXMuSVByb2plY3Q7CmltcG9ydCBvcmcuZWNsaXBzZS5jb3JlLnJ1bnRpbWUuQ29yZUV4Y2VwdGlvbjsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zc2UuY29yZS5TdHJ1Y3R1cmVkTW9kZWxNYW5hZ2VyOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNzZS5jb3JlLmludGVybmFsLmZvcm1hdC5BYnN0cmFjdFN0cnVjdHVyZWRGb3JtYXRQcm9jZXNzb3I7CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc3NlLmNvcmUuaW50ZXJuYWwuZm9ybWF0LklTdHJ1Y3R1cmVkRm9ybWF0UHJlZmVyZW5jZXM7CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc3NlLmNvcmUuaW50ZXJuYWwucHJvdmlzaW9uYWwuSU1vZGVsTWFuYWdlcjsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC5zc2UuY29yZS5pbnRlcm5hbC5wcm92aXNpb25hbC5JU3RydWN0dXJlZE1vZGVsOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNzZS5jb3JlLmludGVybmFsLnV0aWwuVVJJUmVzb2x2ZXI7CmltcG9ydCBvcmcuZWNsaXBzZS53c3QueG1sLmNvcmUuaW50ZXJuYWwucHJvdmlzaW9uYWwuZm9ybWF0LkZvcm1hdFByb2Nlc3NvclhNTDsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC54bWwuY29yZS5pbnRlcm5hbC5wcm92aXNpb25hbC5mb3JtYXQuU3RydWN0dXJlZEZvcm1hdFByZWZlcmVuY2VzWE1MOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnhtbC5jb3JlLnRlc3RzLnV0aWwuU3RyaW5nQ29tcGFyZVV0aWw7CgovKioKICogQGRlcHJlY2F0ZWQgVXNlIFRlc3RQYXJ0aXRpb25Gb3JtYXR0ZXJYTUwgaW5zdGVhZAogKgogKi8KcHVibGljIGNsYXNzIFRlc3RGb3JtYXRQcm9jZXNzb3JYTUwgZXh0ZW5kcyBUZXN0Q2FzZSB7CgoJcHJpdmF0ZSBzdGF0aWMgZmluYWwgYm9vbGVhbiBTUExJVF9NVUxUSV9BVFRSUyA9IGZhbHNlOwoKCXByaXZhdGUgc3RhdGljIGZpbmFsIFN0cmluZyBJTkRFTlQgPSAiXHQiOwoKCXByaXZhdGUgc3RhdGljIGZpbmFsIGJvb2xlYW4gQ0xFQVJfQUxMX0JMQU5LX0xJTkVTID0gZmFsc2U7CgoJcHJpdmF0ZSBzdGF0aWMgZmluYWwgaW50IE1BWF9MSU5FX1dJRFRIID0gNzI7CgoJcHJpdmF0ZSBzdGF0aWMgZmluYWwgU3RyaW5nIFVURl84ID0gIlVURi04IjsKCglwcml2YXRlIFN0cmluZ0NvbXBhcmVVdGlsIGZTdHJpbmdDb21wYXJlVXRpbDsKCglwdWJsaWMgVGVzdEZvcm1hdFByb2Nlc3NvclhNTChTdHJpbmcgbmFtZSkgewoJCXN1cGVyKG5hbWUpOwoJfQoKCXByaXZhdGUgRm9ybWF0UHJvY2Vzc29yWE1MIGZvcm1hdFByb2Nlc3NvcjsKCglwcm90ZWN0ZWQgdm9pZCBzZXRVcCgpIHRocm93cyBFeGNlcHRpb24gewoJCWZvcm1hdFByb2Nlc3NvciA9IG5ldyBGb3JtYXRQcm9jZXNzb3JYTUwoKTsKCQlmU3RyaW5nQ29tcGFyZVV0aWwgPSBuZXcgU3RyaW5nQ29tcGFyZVV0aWwoKTsKCX0KCgkvKioKCSAqIG11c3QgcmVsZWFzZSBtb2RlbCAoZnJvbSBlZGl0KSBhZnRlcgoJICogCgkgKiBAcGFyYW0gZmlsZW5hbWUKCSAqICAgICAgICAgICAgcmVsYXRpdmUgdG8gdGhpcyBjbGFzcyAoVGVzdFN0cnVjdHVyZWRQYXJ0aXRpb25lcikKCSAqLwoJcHJpdmF0ZSBJU3RydWN0dXJlZE1vZGVsIGdldE1vZGVsRm9yRWRpdChmaW5hbCBTdHJpbmcgZmlsZW5hbWUpIHsKCgkJSVN0cnVjdHVyZWRNb2RlbCBtb2RlbCA9IG51bGw7CgkJdHJ5IHsKCQkJSU1vZGVsTWFuYWdlciBtb2RlbE1hbmFnZXIgPSBTdHJ1Y3R1cmVkTW9kZWxNYW5hZ2VyLmdldE1vZGVsTWFuYWdlcigpOwoJCQlJbnB1dFN0cmVhbSBpblN0cmVhbSA9IGdldENsYXNzKCkuZ2V0UmVzb3VyY2VBc1N0cmVhbShmaWxlbmFtZSk7CgkJCWlmIChpblN0cmVhbSA9PSBudWxsKQoJCQkJdGhyb3cgbmV3IEZpbGVOb3RGb3VuZEV4Y2VwdGlvbigiQ2FuJ3QgZmlsZSByZXNvdXJjZSBzdHJlYW0gIiArIGZpbGVuYW1lKTsKCQkJZmluYWwgU3RyaW5nIGJhc2VGaWxlID0gZ2V0Q2xhc3MoKS5nZXRSZXNvdXJjZShmaWxlbmFtZSkudG9TdHJpbmcoKTsKCQkJbW9kZWwgPSBtb2RlbE1hbmFnZXIuZ2V0TW9kZWxGb3JFZGl0KGJhc2VGaWxlLCBpblN0cmVhbSwgbmV3IFVSSVJlc29sdmVyKCkgewoKCQkJCVN0cmluZyBmQmFzZSA9IGJhc2VGaWxlOwoKCQkJCXB1YmxpYyBTdHJpbmcgZ2V0RmlsZUJhc2VMb2NhdGlvbigpIHsKCQkJCQlyZXR1cm4gZkJhc2U7CgkJCQl9CgoJCQkJcHVibGljIFN0cmluZyBnZXRMb2NhdGlvbkJ5VVJJKFN0cmluZyB1cmkpIHsKCQkJCQlyZXR1cm4gZ2V0TG9jYXRpb25CeVVSSSh1cmksIGZCYXNlKTsKCQkJCX0KCgkJCQlwdWJsaWMgU3RyaW5nIGdldExvY2F0aW9uQnlVUkkoU3RyaW5nIHVyaSwgYm9vbGVhbiByZXNvbHZlQ3Jvc3NQcm9qZWN0TGlua3MpIHsKCQkJCQlyZXR1cm4gZ2V0TG9jYXRpb25CeVVSSSh1cmkpOwoJCQkJfQoKCQkJCXB1YmxpYyBTdHJpbmcgZ2V0TG9jYXRpb25CeVVSSShTdHJpbmcgdXJpLCBTdHJpbmcgYmFzZVJlZmVyZW5jZSkgewoJCQkJCWludCBsYXN0U2xhc2ggPSBiYXNlUmVmZXJlbmNlLmxhc3RJbmRleE9mKCIvIik7CgkJCQkJaWYgKGxhc3RTbGFzaCA+IDApCgkJCQkJCXJldHVybiBiYXNlUmVmZXJlbmNlLnN1YnN0cmluZygwLCBsYXN0U2xhc2ggKyAxKSArIHVyaTsKCQkJCQlyZXR1cm4gYmFzZVJlZmVyZW5jZTsKCQkJCX0KCgkJCQlwdWJsaWMgU3RyaW5nIGdldExvY2F0aW9uQnlVUkkoU3RyaW5nIHVyaSwgU3RyaW5nIGJhc2VSZWZlcmVuY2UsIGJvb2xlYW4gcmVzb2x2ZUNyb3NzUHJvamVjdExpbmtzKSB7CgkJCQkJcmV0dXJuIGdldExvY2F0aW9uQnlVUkkodXJpLCBiYXNlUmVmZXJlbmNlKTsKCQkJCX0KCgkJCQlwdWJsaWMgSVByb2plY3QgZ2V0UHJvamVjdCgpIHsKCQkJCQlyZXR1cm4gbnVsbDsKCQkJCX0KCgkJCQlwdWJsaWMgSUNvbnRhaW5lciBnZXRSb290TG9jYXRpb24oKSB7CgkJCQkJcmV0dXJuIG51bGw7CgkJCQl9CgoJCQkJcHVibGljIElucHV0U3RyZWFtIGdldFVSSVN0cmVhbShTdHJpbmcgdXJpKSB7CgkJCQkJcmV0dXJuIGdldENsYXNzKCkuZ2V0UmVzb3VyY2VBc1N0cmVhbShnZXRMb2NhdGlvbkJ5VVJJKHVyaSkpOwoJCQkJfQoKCQkJCXB1YmxpYyB2b2lkIHNldEZpbGVCYXNlTG9jYXRpb24oU3RyaW5nIG5ld0xvY2F0aW9uKSB7CgkJCQkJdGhpcy5mQmFzZSA9IG5ld0xvY2F0aW9uOwoJCQkJfQoKCQkJCXB1YmxpYyB2b2lkIHNldFByb2plY3QoSVByb2plY3QgbmV3UHJvamVjdCkgewoJCQkJfQoJCQl9KTsKCQl9CgkJY2F0Y2ggKElPRXhjZXB0aW9uIGV4KSB7CgkJCWV4LnByaW50U3RhY2tUcmFjZSgpOwoJCX0KCQlyZXR1cm4gbW9kZWw7Cgl9CgoJcHJvdGVjdGVkIHZvaWQgZm9ybWF0QW5kQXNzZXJ0RXF1YWxzKFN0cmluZyBiZWZvcmVQYXRoLCBTdHJpbmcgYWZ0ZXJQYXRoKSB0aHJvd3MgVW5zdXBwb3J0ZWRFbmNvZGluZ0V4Y2VwdGlvbiwgSU9FeGNlcHRpb24sIENvcmVFeGNlcHRpb24gewoJCWZvcm1hdEFuZEFzc2VydEVxdWFscyhiZWZvcmVQYXRoLCBhZnRlclBhdGgsIHRydWUpOwoJfQoKCXByaXZhdGUgdm9pZCBmb3JtYXRBbmRBc3NlcnRFcXVhbHMoU3RyaW5nIGJlZm9yZVBhdGgsIFN0cmluZyBhZnRlclBhdGgsIGJvb2xlYW4gcmVzZXRQcmVmZXJlbmNlcykgdGhyb3dzIFVuc3VwcG9ydGVkRW5jb2RpbmdFeGNlcHRpb24sIElPRXhjZXB0aW9uLCBDb3JlRXhjZXB0aW9uIHsKCQlJU3RydWN0dXJlZE1vZGVsIGJlZm9yZU1vZGVsID0gbnVsbCwgYWZ0ZXJNb2RlbCA9IG51bGw7CgkJdHJ5IHsKCQkJYmVmb3JlTW9kZWwgPSBnZXRNb2RlbEZvckVkaXQoYmVmb3JlUGF0aCk7CgkJCWFzc2VydE5vdE51bGwoImNvdWxkIG5vdCByZXRyaWV2ZSBzdHJ1Y3R1cmVkIG1vZGVsIGZvciA6ICIgKyBiZWZvcmVQYXRoLCBiZWZvcmVNb2RlbCk7CgoJCQlhZnRlck1vZGVsID0gZ2V0TW9kZWxGb3JFZGl0KGFmdGVyUGF0aCk7CgkJCWFzc2VydE5vdE51bGwoImNvdWxkIG5vdCByZXRyaWV2ZSBzdHJ1Y3R1cmVkIG1vZGVsIGZvciA6ICIgKyBhZnRlclBhdGgsIGFmdGVyTW9kZWwpOwoKCQkJaWYgKHJlc2V0UHJlZmVyZW5jZXMpCgkJCQlyZXNldFByZWZlcmVuY2VzVG9EZWZhdWx0KCk7CgoJCQkoKEFic3RyYWN0U3RydWN0dXJlZEZvcm1hdFByb2Nlc3NvcikgZm9ybWF0UHJvY2Vzc29yKS5yZWZyZXNoRm9ybWF0UHJlZmVyZW5jZXMgPSBmYWxzZTsKCQkJZm9ybWF0UHJvY2Vzc29yLmZvcm1hdE1vZGVsKGJlZm9yZU1vZGVsKTsKCQkJKChBYnN0cmFjdFN0cnVjdHVyZWRGb3JtYXRQcm9jZXNzb3IpIGZvcm1hdFByb2Nlc3NvcikucmVmcmVzaEZvcm1hdFByZWZlcmVuY2VzID0gdHJ1ZTsKCgkJCUJ5dGVBcnJheU91dHB1dFN0cmVhbSBmb3JtYXR0ZWRCeXRlcyA9IG5ldyBCeXRlQXJyYXlPdXRwdXRTdHJlYW0oKTsKCQkJYmVmb3JlTW9kZWwuc2F2ZShmb3JtYXR0ZWRCeXRlcyk7IC8vICJiZWZvcmVNb2RlbCIgc2hvdWxkIG5vdyBiZQoJCQkvLyBhZnRlciB0aGUgZm9ybWF0dGVyCgoJCQlCeXRlQXJyYXlPdXRwdXRTdHJlYW0gYWZ0ZXJCeXRlcyA9IG5ldyBCeXRlQXJyYXlPdXRwdXRTdHJlYW0oKTsKCQkJYWZ0ZXJNb2RlbC5zYXZlKGFmdGVyQnl0ZXMpOwoKCQkJU3RyaW5nIGV4cGVjdGVkQ29udGVudHMgPSBuZXcgU3RyaW5nKGFmdGVyQnl0ZXMudG9CeXRlQXJyYXkoKSwgVVRGXzgpOwoJCQlTdHJpbmcgYWN0dWFsQ29udGVudHMgPSBuZXcgU3RyaW5nKGZvcm1hdHRlZEJ5dGVzLnRvQnl0ZUFycmF5KCksIFVURl84KTsKCQkJYXNzZXJ0VHJ1ZSgiRm9ybWF0dGVkIGRvY3VtZW50IGRpZmZlcnMgZnJvbSB0aGUgZXhwZWN0ZWQuXG5FeHBlY3RlZCBDb250ZW50czpcbiIgKyBleHBlY3RlZENvbnRlbnRzICsgIlxuQWN0dWFsIENvbnRlbnRzOlxuIiArIGFjdHVhbENvbnRlbnRzLCBmU3RyaW5nQ29tcGFyZVV0aWwuZXF1YWxzSWdub3JlTGluZVNlcGVyYXRvcihleHBlY3RlZENvbnRlbnRzLCBhY3R1YWxDb250ZW50cykpOwoJCX0KCQlmaW5hbGx5IHsKCQkJaWYgKGJlZm9yZU1vZGVsICE9IG51bGwpCgkJCQliZWZvcmVNb2RlbC5yZWxlYXNlRnJvbUVkaXQoKTsKCQkJaWYgKGFmdGVyTW9kZWwgIT0gbnVsbCkKCQkJCWFmdGVyTW9kZWwucmVsZWFzZUZyb21FZGl0KCk7CgkJfQoJfQoKCXByaXZhdGUgdm9pZCByZXNldFByZWZlcmVuY2VzVG9EZWZhdWx0KCkgewoJCUlTdHJ1Y3R1cmVkRm9ybWF0UHJlZmVyZW5jZXMgZm9ybWF0UHJlZmVyZW5jZXMgPSBmb3JtYXRQcm9jZXNzb3IuZ2V0Rm9ybWF0UHJlZmVyZW5jZXMoKTsKCQlmb3JtYXRQcmVmZXJlbmNlcy5zZXRMaW5lV2lkdGgoTUFYX0xJTkVfV0lEVEgpOwoJCWZvcm1hdFByZWZlcmVuY2VzLnNldENsZWFyQWxsQmxhbmtMaW5lcyhDTEVBUl9BTExfQkxBTktfTElORVMpOwoJCWZvcm1hdFByZWZlcmVuY2VzLnNldEluZGVudChJTkRFTlQpOwoJCSgoU3RydWN0dXJlZEZvcm1hdFByZWZlcmVuY2VzWE1MKSBmb3JtYXRQcmVmZXJlbmNlcykuc2V0U3BsaXRNdWx0aUF0dHJzKFNQTElUX01VTFRJX0FUVFJTKTsKCX0KCglwdWJsaWMgdm9pZCB0ZXN0U2ltcGxlWG1sKCkgdGhyb3dzIFVuc3VwcG9ydGVkRW5jb2RpbmdFeGNlcHRpb24sIElPRXhjZXB0aW9uLCBDb3JlRXhjZXB0aW9uIHsKCQlmb3JtYXRBbmRBc3NlcnRFcXVhbHMoInRlc3RmaWxlcy94bWwvc2ltcGxlLXN0YW5kYWxvbmUueG1sIiwgInRlc3RmaWxlcy94bWwvc2ltcGxlLXN0YW5kYWxvbmUtZm10LnhtbCIpOwoJfQoKCXB1YmxpYyB2b2lkIHRlc3RQcmVzZXJ2ZUZvcm1hdCgpIHRocm93cyBVbnN1cHBvcnRlZEVuY29kaW5nRXhjZXB0aW9uLCBJT0V4Y2VwdGlvbiwgQ29yZUV4Y2VwdGlvbiB7CgkJZm9ybWF0QW5kQXNzZXJ0RXF1YWxzKCJ0ZXN0ZmlsZXMveG1sL3htbC1zcGFjZS1wcmVzZXJ2ZS1zdGFuZGFsb25lLnhtbCIsICJ0ZXN0ZmlsZXMveG1sL3htbC1zcGFjZS1wcmVzZXJ2ZS1zdGFuZGFsb25lLWZtdC54bWwiKTsKCX0KCglwdWJsaWMgdm9pZCB0ZXN0UHJlc2VydmVGb3JtYXREVEQoKSB0aHJvd3MgVW5zdXBwb3J0ZWRFbmNvZGluZ0V4Y2VwdGlvbiwgSU9FeGNlcHRpb24sIENvcmVFeGNlcHRpb24gewoJCWZvcm1hdEFuZEFzc2VydEVxdWFscygidGVzdGZpbGVzL3htbC94bWwtc3BhY2UtcHJlc2VydmUtZHRkLnhtbCIsICJ0ZXN0ZmlsZXMveG1sL3htbC1zcGFjZS1wcmVzZXJ2ZS1kdGQtZm10LnhtbCIpOwoJfQoKCXB1YmxpYyB2b2lkIHRlc3RPbmVMaW5lRm9ybWF0KCkgdGhyb3dzIFVuc3VwcG9ydGVkRW5jb2RpbmdFeGNlcHRpb24sIElPRXhjZXB0aW9uLCBDb3JlRXhjZXB0aW9uIHsKCQkvLyBCVUcxMTU3MTYKCQlmb3JtYXRBbmRBc3NlcnRFcXVhbHMoInRlc3RmaWxlcy94bWwvb25lbGluZS54bWwiLCAidGVzdGZpbGVzL3htbC9vbmVsaW5lLWZtdC54bWwiKTsKCX0KCglwdWJsaWMgdm9pZCB0ZXN0T25lTGluZVRleHROb2RlRm9ybWF0KCkgdGhyb3dzIFVuc3VwcG9ydGVkRW5jb2RpbmdFeGNlcHRpb24sIElPRXhjZXB0aW9uLCBDb3JlRXhjZXB0aW9uIHsKCQkvLyBCVUcxNjY0NDEKCQlmb3JtYXRBbmRBc3NlcnRFcXVhbHMoInRlc3RmaWxlcy94bWwvb25lbGluZVRleHROb2RlLnhtbCIsICJ0ZXN0ZmlsZXMveG1sL29uZWxpbmVUZXh0Tm9kZS1mbXQueG1sIik7Cgl9CgoJcHVibGljIHZvaWQgdGVzdEVtcHR5Q29udGVudE5vZGVGb3JtYXQoKSB0aHJvd3MgVW5zdXBwb3J0ZWRFbmNvZGluZ0V4Y2VwdGlvbiwgSU9FeGNlcHRpb24sIENvcmVFeGNlcHRpb24gewoJCS8vIEJVRzE3NDI0MwoJCUlTdHJ1Y3R1cmVkRm9ybWF0UHJlZmVyZW5jZXMgZm9ybWF0UHJlZmVyZW5jZXMgPSBmb3JtYXRQcm9jZXNzb3IuZ2V0Rm9ybWF0UHJlZmVyZW5jZXMoKTsKCQkoKFN0cnVjdHVyZWRGb3JtYXRQcmVmZXJlbmNlc1hNTCkgZm9ybWF0UHJlZmVyZW5jZXMpLnNldFNwbGl0TXVsdGlBdHRycyh0cnVlKTsKCQlmb3JtYXRBbmRBc3NlcnRFcXVhbHMoInRlc3RmaWxlcy94bWwvdXNldGFnc3dpdGhlbXB0eWNvbnRlbnQueG1sIiwgInRlc3RmaWxlcy94bWwvdXNldGFnc3dpdGhlbXB0eWNvbnRlbnQtZm10LnhtbCIsIGZhbHNlKTsKCX0KCglwdWJsaWMgdm9pZCB0ZXN0WFNMRm9ybWF0KCkgdGhyb3dzIFVuc3VwcG9ydGVkRW5jb2RpbmdFeGNlcHRpb24sIElPRXhjZXB0aW9uLCBDb3JlRXhjZXB0aW9uIHsKCQkvLyBCVUcxMDgwNzQKCQlmb3JtYXRBbmRBc3NlcnRFcXVhbHMoInRlc3RmaWxlcy94bWwveHNsYXR0cmlidXRldGV4dC54c2wiLCAidGVzdGZpbGVzL3htbC94c2xhdHRyaWJ1dGV0ZXh0LWZtdC54c2wiKTsKCX0KCglwdWJsaWMgdm9pZCB0ZXN0RW50aXR5Rm9ybWF0KCkgdGhyb3dzIFVuc3VwcG9ydGVkRW5jb2RpbmdFeGNlcHRpb24sIElPRXhjZXB0aW9uLCBDb3JlRXhjZXB0aW9uIHsKCQkvLyBCVUcxMDIwNzYKCQlmb3JtYXRBbmRBc3NlcnRFcXVhbHMoInRlc3RmaWxlcy94bWwvZW50aXRpZXMueG1sIiwgInRlc3RmaWxlcy94bWwvZW50aXRpZXMtZm10LnhtbCIpOwoJfQoKCXB1YmxpYyB2b2lkIHRlc3RQcmVzZXJ2ZVBDREFUQUZvcm1hdCgpIHRocm93cyBVbnN1cHBvcnRlZEVuY29kaW5nRXhjZXB0aW9uLCBJT0V4Y2VwdGlvbiwgQ29yZUV4Y2VwdGlvbiB7CgkJLy8gQlVHODQ2ODgKCQlJU3RydWN0dXJlZEZvcm1hdFByZWZlcmVuY2VzIGZvcm1hdFByZWZlcmVuY2VzID0gZm9ybWF0UHJvY2Vzc29yLmdldEZvcm1hdFByZWZlcmVuY2VzKCk7CgkJKChTdHJ1Y3R1cmVkRm9ybWF0UHJlZmVyZW5jZXNYTUwpIGZvcm1hdFByZWZlcmVuY2VzKS5zZXRQcmVzZXJ2ZVBDREFUQUNvbnRlbnQodHJ1ZSk7CgkJZm9ybWF0QW5kQXNzZXJ0RXF1YWxzKCJ0ZXN0ZmlsZXMveG1sL3htbC1wcmVzZXJ2ZXBjZGF0YS54bWwiLCAidGVzdGZpbGVzL3htbC94bWwtcHJlc2VydmVwY2RhdGEteWVzLWZtdC54bWwiLCBmYWxzZSk7CgoJCSgoU3RydWN0dXJlZEZvcm1hdFByZWZlcmVuY2VzWE1MKSBmb3JtYXRQcmVmZXJlbmNlcykuc2V0UHJlc2VydmVQQ0RBVEFDb250ZW50KGZhbHNlKTsKCQlmb3JtYXRBbmRBc3NlcnRFcXVhbHMoInRlc3RmaWxlcy94bWwveG1sLXByZXNlcnZlcGNkYXRhLnhtbCIsICJ0ZXN0ZmlsZXMveG1sL3htbC1wcmVzZXJ2ZXBjZGF0YS1uby1mbXQueG1sIiwgZmFsc2UpOwoJfQoKCXB1YmxpYyB2b2lkIHRlc3RQcmVzZXJ2ZUNEQVRBRm9ybWF0KCkgdGhyb3dzIFVuc3VwcG9ydGVkRW5jb2RpbmdFeGNlcHRpb24sIElPRXhjZXB0aW9uLCBDb3JlRXhjZXB0aW9uIHsKCQkvLyBCVUcxNjEzMzAKCQlmb3JtYXRBbmRBc3NlcnRFcXVhbHMoInRlc3RmaWxlcy94bWwvdXNlY2RhdGEueG1sIiwgInRlc3RmaWxlcy94bWwvdXNlY2RhdGEtZm10LnhtbCIpOwoJCWZvcm1hdEFuZEFzc2VydEVxdWFscygidGVzdGZpbGVzL3htbC91c2VjZGF0YTIueG1sIiwgInRlc3RmaWxlcy94bWwvdXNlY2RhdGEyLWZtdC54bWwiKTsKCX0KCglwdWJsaWMgdm9pZCB0ZXN0U3BsaXRBdHRyaWJ1dGVzRm9ybWF0KCkgdGhyb3dzIFVuc3VwcG9ydGVkRW5jb2RpbmdFeGNlcHRpb24sIElPRXhjZXB0aW9uLCBDb3JlRXhjZXB0aW9uIHsKCQkvLyBCVUcxMTM1ODQKCQlJU3RydWN0dXJlZEZvcm1hdFByZWZlcmVuY2VzIGZvcm1hdFByZWZlcmVuY2VzID0gZm9ybWF0UHJvY2Vzc29yLmdldEZvcm1hdFByZWZlcmVuY2VzKCk7CgkJKChTdHJ1Y3R1cmVkRm9ybWF0UHJlZmVyZW5jZXNYTUwpIGZvcm1hdFByZWZlcmVuY2VzKS5zZXRTcGxpdE11bHRpQXR0cnModHJ1ZSk7CgkJKChTdHJ1Y3R1cmVkRm9ybWF0UHJlZmVyZW5jZXNYTUwpIGZvcm1hdFByZWZlcmVuY2VzKS5zZXRBbGlnbkVuZEJyYWNrZXQoZmFsc2UpOwoJCWZvcm1hdEFuZEFzc2VydEVxdWFscygidGVzdGZpbGVzL3htbC9tdWx0aWF0dHJpYnV0ZXMueG1sIiwgInRlc3RmaWxlcy94bWwvbXVsdGlhdHRyaWJ1dGVzLXllc3NwbGl0LW5vYWxpZ24tZm10LnhtbCIsIGZhbHNlKTsKCgkJKChTdHJ1Y3R1cmVkRm9ybWF0UHJlZmVyZW5jZXNYTUwpIGZvcm1hdFByZWZlcmVuY2VzKS5zZXRTcGxpdE11bHRpQXR0cnMoZmFsc2UpOwoJCSgoU3RydWN0dXJlZEZvcm1hdFByZWZlcmVuY2VzWE1MKSBmb3JtYXRQcmVmZXJlbmNlcykuc2V0QWxpZ25FbmRCcmFja2V0KGZhbHNlKTsKCQlmb3JtYXRBbmRBc3NlcnRFcXVhbHMoInRlc3RmaWxlcy94bWwvbXVsdGlhdHRyaWJ1dGVzLnhtbCIsICJ0ZXN0ZmlsZXMveG1sL211bHRpYXR0cmlidXRlcy1ub3NwbGl0LW5vYWxpZ24tZm10LnhtbCIsIGZhbHNlKTsKCgl9CgoJcHVibGljIHZvaWQgdGVzdEFsaWduRW5kQnJhY2tldEZvcm1hdCgpIHRocm93cyBVbnN1cHBvcnRlZEVuY29kaW5nRXhjZXB0aW9uLCBJT0V4Y2VwdGlvbiwgQ29yZUV4Y2VwdGlvbiB7CgkJLy8gQlVHMTEzNTg0CgkJSVN0cnVjdHVyZWRGb3JtYXRQcmVmZXJlbmNlcyBmb3JtYXRQcmVmZXJlbmNlcyA9IGZvcm1hdFByb2Nlc3Nvci5nZXRGb3JtYXRQcmVmZXJlbmNlcygpOwoJCSgoU3RydWN0dXJlZEZvcm1hdFByZWZlcmVuY2VzWE1MKSBmb3JtYXRQcmVmZXJlbmNlcykuc2V0U3BsaXRNdWx0aUF0dHJzKGZhbHNlKTsKCQkoKFN0cnVjdHVyZWRGb3JtYXRQcmVmZXJlbmNlc1hNTCkgZm9ybWF0UHJlZmVyZW5jZXMpLnNldEFsaWduRW5kQnJhY2tldCh0cnVlKTsKCQlmb3JtYXRBbmRBc3NlcnRFcXVhbHMoInRlc3RmaWxlcy94bWwvbXVsdGlhdHRyaWJ1dGVzLnhtbCIsICJ0ZXN0ZmlsZXMveG1sL211bHRpYXR0cmlidXRlcy1ub3NwbGl0LXllc2FsaWduLWZtdC54bWwiLCBmYWxzZSk7CgoJCSgoU3RydWN0dXJlZEZvcm1hdFByZWZlcmVuY2VzWE1MKSBmb3JtYXRQcmVmZXJlbmNlcykuc2V0U3BsaXRNdWx0aUF0dHJzKHRydWUpOwoJCSgoU3RydWN0dXJlZEZvcm1hdFByZWZlcmVuY2VzWE1MKSBmb3JtYXRQcmVmZXJlbmNlcykuc2V0QWxpZ25FbmRCcmFja2V0KHRydWUpOwoJCWZvcm1hdEFuZEFzc2VydEVxdWFscygidGVzdGZpbGVzL3htbC9tdWx0aWF0dHJpYnV0ZXMueG1sIiwgInRlc3RmaWxlcy94bWwvbXVsdGlhdHRyaWJ1dGVzLXllc3NwbGl0LXllc2FsaWduLWZtdC54bWwiLCBmYWxzZSk7CgoJfQp9Cg==