LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogQ29weXJpZ2h0IChjKSAyMDExIERyYWVnZXIgTWVkaWNhbCBHbWJIIChodHRwOi8vd3d3LmRyYWVnZXIuY29tKS4KICogQWxsIHJpZ2h0cyByZXNlcnZlZC4gVGhpcyBwcm9ncmFtIGFuZCB0aGUgYWNjb21wYW55aW5nIG1hdGVyaWFscwogKiBhcmUgbWFkZSBhdmFpbGFibGUgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBFY2xpcHNlIFB1YmxpYyBMaWNlbnNlIDIuMAogKiB3aGljaCBhY2NvbXBhbmllcyB0aGlzIGRpc3RyaWJ1dGlvbiwgYW5kIGlzIGF2YWlsYWJsZSBhdAogKiBodHRwczovL3d3dy5lY2xpcHNlLm9yZy9sZWdhbC9lcGwtMi4wLwogKgogKiBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogRVBMLTIuMAogKgogKiBDT05UUklCVVRPUlM6CiAqIAkJUGV0ZXIgS2FybGl0c2NoZWsgKGluaXRpYWwgY29udHJpYnV0aW9uKQogKgogKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KCnBhY2thZ2Ugb3JnLmVjbGlwc2UuZXRyaWNlLmdlbmVyYXRvci5jcHAuZ2VuCgppbXBvcnQgY29tLmdvb2dsZS5pbmplY3QuSW5qZWN0CmltcG9ydCBjb20uZ29vZ2xlLmluamVjdC5TaW5nbGV0b24KaW1wb3J0IGphdmEudXRpbC5MaXN0CmltcG9ydCBvcmcuZWNsaXBzZS5ldHJpY2UuY29yZS5nZW5tb2RlbC5ldHJpY2VnZW4uUm9vdAppbXBvcnQgb3JnLmVjbGlwc2UuZXRyaWNlLmNvcmUucm9vbS5Db21tdW5pY2F0aW9uVHlwZQppbXBvcnQgb3JnLmVjbGlwc2UuZXRyaWNlLmNvcmUucm9vbS5JbnRlcmZhY2VJdGVtCmltcG9ydCBvcmcuZWNsaXBzZS5ldHJpY2UuY29yZS5yb29tLk1lc3NhZ2UKaW1wb3J0IG9yZy5lY2xpcHNlLmV0cmljZS5jb3JlLnJvb20uUG9ydAppbXBvcnQgb3JnLmVjbGlwc2UuZXRyaWNlLmNvcmUucm9vbS5Qb3J0Q2xhc3MKaW1wb3J0IG9yZy5lY2xpcHNlLmV0cmljZS5jb3JlLnJvb20uUHJvdG9jb2xDbGFzcwppbXBvcnQgb3JnLmVjbGlwc2UuZXRyaWNlLmNvcmUucm9vbS5TQVAKaW1wb3J0IG9yZy5lY2xpcHNlLmV0cmljZS5jb3JlLnJvb20uU1BQCmltcG9ydCBvcmcuZWNsaXBzZS5ldHJpY2UuZ2VuZXJhdG9yLmNwcC5NYWluCmltcG9ydCBvcmcuZWNsaXBzZS5ldHJpY2UuZ2VuZXJhdG9yLmZzbS5iYXNlLkZpbGVTeXN0ZW1IZWxwZXJzCmltcG9ydCBvcmcuZWNsaXBzZS5ldHJpY2UuZ2VuZXJhdG9yLmJhc2UuaW8uSUdlbmVyYXRvckZpbGVJTwppbXBvcnQgb3JnLmVjbGlwc2UuZXRyaWNlLmdlbmVyYXRvci5nZW5lcmljLkdlbmVyaWNQcm90b2NvbENsYXNzR2VuZXJhdG9yCmltcG9ydCBvcmcuZWNsaXBzZS5ldHJpY2UuZ2VuZXJhdG9yLmdlbmVyaWMuUHJvY2VkdXJlSGVscGVycwppbXBvcnQgb3JnLmVjbGlwc2UuZXRyaWNlLmdlbmVyYXRvci5nZW5lcmljLlJvb21FeHRlbnNpb25zCmltcG9ydCBvcmcuZWNsaXBzZS5ldHJpY2UuZ2VuZXJhdG9yLmdlbmVyaWMuVHlwZUhlbHBlcnMKaW1wb3J0IG9yZy5lY2xpcHNlLmV0cmljZS5nZW5lcmF0b3IuZ2VuZXJpYy5JTGFuZ3VhZ2VFeHRlbnNpb24KaW1wb3J0IG9yZy5lY2xpcHNlLmV0cmljZS5jb3JlLmdlbm1vZGVsLmZzbS5JRGlhZ25vc3RpY2lhbgppbXBvcnQgb3JnLmVjbGlwc2UuZXRyaWNlLmdlbmVyYXRvci5jcHAuc2V0dXAuR2VuZXJhdG9yT3B0aW9uc0hlbHBlcgoKQFNpbmdsZXRvbgpjbGFzcyBQcm90b2NvbENsYXNzR2VuIGV4dGVuZHMgR2VuZXJpY1Byb3RvY29sQ2xhc3NHZW5lcmF0b3IgewoKCUBJbmplY3QgSUdlbmVyYXRvckZpbGVJTyBmaWxlSU8KCUBJbmplY3QgZXh0ZW5zaW9uIENwcEV4dGVuc2lvbnMgc3RkRXh0CglASW5qZWN0IGV4dGVuc2lvbiBSb29tRXh0ZW5zaW9ucyByb29tRXh0CglASW5qZWN0IGV4dGVuc2lvbiBQcm9jZWR1cmVIZWxwZXJzIGhlbHBlcnMKCUBJbmplY3QgZXh0ZW5zaW9uIFR5cGVIZWxwZXJzCglASW5qZWN0IGV4dGVuc2lvbiBGaWxlU3lzdGVtSGVscGVycwoJQEluamVjdCBleHRlbnNpb24gR2VuZXJhdG9yT3B0aW9uc0hlbHBlcgoJQEluamVjdCBJbml0aWFsaXphdGlvbiBpbml0SGVscGVyCglASW5qZWN0IElEaWFnbm9zdGljaWFuIGRpYWdub3N0aWNpYW4KCglkZWYgZG9HZW5lcmF0ZShSb290IHJvb3QpIHsKCgkJZm9yIChwYzogcm9vdC5wcm90b2NvbENsYXNzZXMuZmlsdGVyKGNsfGNsLmlzVmFsaWRHZW5lcmF0aW9uTG9jYXRpb24pKSB7CgkJCXZhbCBwYXRoID0gcGMuZ2V0UGF0aAoJCQlzd2l0Y2ggKHBjLmNvbW1UeXBlKSB7CgkJCQljYXNlIENvbW11bmljYXRpb25UeXBlOjpFVkVOVF9EUklWRU46ewoJCQkJCWZpbGVJTy5nZW5lcmF0ZUZpbGUoImdlbmVyYXRpbmcgUHJvdG9jb2xDbGFzcyBkZWNsYXJhdGlvbiIsIHBhdGggKyBwYy5jcHBIZWFkZXJGaWxlTmFtZSwgcm9vdC5nZW5lcmF0ZUhlYWRlckZpbGUocGMpKQoJCQkJCWZpbGVJTy5nZW5lcmF0ZUZpbGUoImdlbmVyYXRpbmcgUHJvdG9jb2xDbGFzcyBpbXBsZW1lbnRhdGlvbiIsIHBhdGggKyBwYy5jcHBTb3VyY2VGaWxlTmFtZSwgcm9vdC5nZW5lcmF0ZVNvdXJjZUZpbGUocGMpKQoJCQkJfQoJCQkJY2FzZSBDb21tdW5pY2F0aW9uVHlwZTo6REFUQV9EUklWRU46ewoJCQkJCWZpbGVJTy5nZW5lcmF0ZUZpbGUoImdlbmVyYXRpbmcgUHJvdG9jb2xDbGFzcyBkZWNsYXJhdGlvbiIsIHBhdGggKyBwYy5jcHBIZWFkZXJGaWxlTmFtZSwgcm9vdC5nZW5lcmF0ZURhdGFEcml2ZW5IZWFkZXJGaWxlKHBjKSkKCQkJCQlmaWxlSU8uZ2VuZXJhdGVGaWxlKCJnZW5lcmF0aW5nIFByb3RvY29sQ2xhc3MgaW1wbGVtZW50YXRpb24iLCBwYXRoICsgcGMuY3BwU291cmNlRmlsZU5hbWUsIHJvb3QuZ2VuZXJhdGVEYXRhRHJpdmVuU291cmNlRmlsZShwYykpCgkJCQl9CgkJCQljYXNlIENvbW11bmljYXRpb25UeXBlOjpTWU5DSFJPTk9VUzoKCQkJCQlkaWFnbm9zdGljaWFuLmVycm9yKCJzeW5jaHJvbm91cyBwcm90b2NvbHMgbm90IHN1cHBvcnRlZCB5ZXQiLCBwYywgbnVsbCkKCQkJfQoJCX0KCX0KCgoJZGVmIHByb3RlY3RlZCBnZW5lcmF0ZUhlYWRlckZpbGUoUm9vdCByb290LCBQcm90b2NvbENsYXNzIHBjKSB7JycnCgkJLyoqCgkJICogQGF1dGhvciBnZW5lcmF0ZWQgYnkgZVRyaWNlCgkJICoKCQkgKiBIZWFkZXIgRmlsZSBvZiBQcm90b2NvbENsYXNzIKtwYy5uYW1luwoJCSAqCgkJICovCgoJCatnZW5lcmF0ZUluY2x1ZGVHdWFyZEJlZ2luKHBjLCAnJym7CgoJCSNpbmNsdWRlICJjb21tb24vbW9kZWxiYXNlL0ludGVyZmFjZUl0ZW1CYXNlLmgiCgkJI2luY2x1ZGUgImNvbW1vbi9tb2RlbGJhc2UvUG9ydEJhc2UuaCIKCQkjaW5jbHVkZSAiY29tbW9uL21vZGVsYmFzZS9SZXBsaWNhdGVkSW50ZXJmYWNlSXRlbUJhc2UuaCIKCQkjaW5jbHVkZSAiY29tbW9uL21vZGVsYmFzZS9SZXBsaWNhdGVkUG9ydEJhc2UuaCIKCQkjaW5jbHVkZSAiY29tbW9uL2V0RGF0YXR5cGVzQ3BwLmhwcCIKCgkJq0ZPUiBkYXRhQ2xhc3MgOiByb290LmdldFJlZmVyZW5jZWREYXRhQ2xhc3NlcyhwYym7CgkJCSNpbmNsdWRlICKrZGF0YUNsYXNzLnBhdGi7q2RhdGFDbGFzcy5uYW1luy5oIgoJCatFTkRGT1K7CgoJCatwYy51c2VyQ29kZTEudXNlckNvZGW7CgoJCatwYy5nZW5lcmF0ZU5hbWVzcGFjZUJlZ2luuwoKCQljbGFzcyCrcGMubmFtZbsgewoJCSAgIHB1YmxpYzoKCQkJCS8qIG1lc3NhZ2UgSURzICovCgkJCQmrZ2VuTWVzc2FnZUlEcyhwYym7CgoJCQkJq3BjLnVzZXJDb2RlKDIpuwoKCQkJCXN0YXRpYyBib29sIGlzVmFsaWRFdnRJRChpbnQgZXZ0SWQpIHsKCQkJCQlyZXR1cm4gKChNU0dfTUlOIDwgZXZ0SWQpICYmIChldnRJZCA8IE1TR19NQVgpKTsKCQkJCX0KCQkJCXN0YXRpYyBib29sIGlzVmFsaWRPdXRnb2luZ0V2dElEKGludCBldnRJZCkgewoJCQkJCXJldHVybiAoKE1TR19NSU4gPCBldnRJZCkgJiYgKGV2dElkIDwgq0lGIHBjLmluY29taW5nTWVzc2FnZXMuc2l6ZSA9PSAwu01TR19NQVirRUxTRbtJTl+rcGMuaW5jb21pbmdNZXNzYWdlcy5nZXQoMCkubmFtZburRU5ESUa7KSk7CgkJCQl9CgkJCQlzdGF0aWMgYm9vbCBpc1ZhbGlkSW5jb21pbmdFdnRJRChpbnQgZXZ0SWQpIHsKCQkJCQlyZXR1cm4gKCirSUYgcGMuaW5jb21pbmdNZXNzYWdlcy5zaXplID09IDC7TVNHX01BWKtFTFNFu0lOX6twYy5pbmNvbWluZ01lc3NhZ2VzLmdldCgwKS5uYW1lu6tFTkRJRrsgPD0gZXZ0SWQpICYmIChldnRJZCA8IE1TR19NQVgpKTsKCQkJCX0KCQkJCXN0YXRpYyBjb25zdCBldFJ1bnRpbWU6OlN0cmluZyYgZ2V0TWVzc2FnZVN0cmluZyhpbnQgbXNnX2lkKTsKCgkJCXByaXZhdGU6CgkJCQlzdGF0aWMgY29uc3QgZXRSdW50aW1lOjpTdHJpbmcgc19tZXNzYWdlU3RyaW5nc1tdOwoKCQl9OwoKCQmrcG9ydENsYXNzRGVjbGFyYXRpb24ocGMsIGZhbHNlKbsKCQmrcG9ydENsYXNzRGVjbGFyYXRpb24ocGMsIHRydWUpuwoKCQmrcGMuZ2VuZXJhdGVOYW1lc3BhY2VFbmS7CgoJCatnZW5lcmF0ZUluY2x1ZGVHdWFyZEVuZChwYywgJycpuwoJJycnCgl9CgoJZGVmIHByb3RlY3RlZCBwb3J0Q2xhc3NEZWNsYXJhdGlvbihQcm90b2NvbENsYXNzIHBjLCBib29sZWFuIGNvbmopIHsKCQl2YXIgcGNsYXNzID0gcGMuZ2V0UG9ydENsYXNzKGNvbmopCgkJdmFyIHBvcnRDbGFzc05hbWUgPSBwYy5nZXRQb3J0Q2xhc3NOYW1lKGNvbmopCgkJdmFyIHJlcGxQb3J0Q2xhc3NOYW1lID0gcGMuZ2V0UG9ydENsYXNzTmFtZShjb25qLCB0cnVlKQoJJycnCgkvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoJLy8gq0lGIGNvbmq7Y29uanVnYXRlZCCrRU5ESUa7cG9ydCBjbGFzcwoJLy8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCWNsYXNzIKtwb3J0Q2xhc3NOYW1luyA6IHB1YmxpYyBldFJ1bnRpbWU6OlBvcnRCYXNlIHsKCQmrSUYgcGNsYXNzIT09bnVsbLsKCQkJq3BjbGFzcy51c2VyQ29kZS51c2VyQ29kZbsKCQmrRU5ESUa7CgkgICBwdWJsaWM6CgkJIKtwb3J0Q2xhc3NOYW1luyhldFJ1bnRpbWU6OklJbnRlcmZhY2VJdGVtT3duZXIqIGFjdG9yLCBjb25zdCBldFJ1bnRpbWU6OlN0cmluZyYgbmFtZSwgaW50IGxvY2FsSWQpOwoJCSCrcG9ydENsYXNzTmFtZbsoZXRSdW50aW1lOjpJSW50ZXJmYWNlSXRlbU93bmVyKiBhY3RvciwgY29uc3QgZXRSdW50aW1lOjpTdHJpbmcmIG5hbWUsIGludCBsb2NhbElkLCBpbnQgaWR4KTsKCgkJq0lGIE1haW46OnNldHRpbmdzLmdlbmVyYXRlTVNDSW5zdHJ1bWVudGF0aW9uuwoJCQl2aXJ0dWFsIHZvaWQgZGVzdHJveSgpOwoJCatFTkRJRrsKCgkJIHZpcnR1YWwgdm9pZCByZWNlaXZlKGNvbnN0IGV0UnVudGltZTo6TWVzc2FnZSogbSk7CgoJCatJRiBwY2xhc3MhPT1udWxsuwoJCQmrcGNsYXNzLmF0dHJpYnV0ZXMuYXR0cmlidXRlc7sKCQkJq3BjbGFzcy5vcGVyYXRpb25zLm9wZXJhdGlvbnNEZWNsYXJhdGlvbihwb3J0Q2xhc3NOYW1lKbsKCQmrRU5ESUa7CgoJCSAvLyBzZW50IG1lc3NhZ2VzCgkJq0ZPUiBtIDogcGMuZ2V0QWxsTWVzc2FnZXMoY29uaim7CgkJICAJq21lc3NhZ2VTaWduYXR1cmUobSwgZmFsc2UpuzsKCQkgIAmrbWVzc2FnZVNpZ25hdHVyZShtLCB0cnVlKbs7CgkJq0VOREZPUrsKCX07CgoJLy8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCS8vIKtJRiBjb25qu2Nvbmp1Z2F0ZWQgq0VORElGu3JlcGxpY2F0ZWQgcG9ydCBjbGFzcwoJLy8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCWNsYXNzIKtyZXBsUG9ydENsYXNzTmFtZbsgOiBwdWJsaWMgZXRSdW50aW1lOjpSZXBsaWNhdGVkUG9ydEJhc2UgewoKCQlwdWJsaWM6CgkJCatyZXBsUG9ydENsYXNzTmFtZbsoZXRSdW50aW1lOjpJSW50ZXJmYWNlSXRlbU93bmVyKiBhY3RvciwgY29uc3QgZXRSdW50aW1lOjpTdHJpbmcmIG5hbWUsIGludCBsb2NhbElkKTsKCgkJCWludCBnZXRSZXBsaWNhdGlvbigpIGNvbnN0IHsgcmV0dXJuIGdldE5JbnRlcmZhY2VJdGVtcygpOyB9CgkJCWludCBnZXRJbmRleE9mKGNvbnN0IGV0UnVudGltZTo6SW50ZXJmYWNlSXRlbUJhc2UmIGlmaXRlbSkgY29uc3QgeyByZXR1cm4gaWZpdGVtLmdldElkeCgpOyB9CgkJCatwb3J0Q2xhc3NOYW1luyYgZ2V0KGludCBpZHgpIGNvbnN0IHsgcmV0dXJuICpkeW5hbWljX2Nhc3Q8q3BvcnRDbGFzc05hbWW7Kj4oZ2V0SW50ZXJmYWNlSXRlbShpZHgpKTsgfQoKCQkJq0lGIGNvbmq7CgkJCQkvLyBpbmNvbWluZyBtZXNzYWdlcwoJCQkJq0ZPUiBtIDogcGMuZ2V0QWxsSW5jb21pbmdNZXNzYWdlcygpuwoJCQkJCattZXNzYWdlU2lnbmF0dXJlKG0sIGZhbHNlKbs7CgkJCQmrRU5ERk9SuwoJCQmrRUxTRbsKCQkJCS8vIG91dGdvaW5nIG1lc3NhZ2VzCgkJCQmrRk9SIG0gOiBwYy5nZXRBbGxPdXRnb2luZ01lc3NhZ2VzKCm7CgkJCQkJq21lc3NhZ2VTaWduYXR1cmUobSwgZmFsc2UpuzsKCQkJCatFTkRGT1K7CgkJCatFTkRJRrsKCgkJcHJvdGVjdGVkOgoJCQl2aXJ0dWFsIGV0UnVudGltZTo6SW50ZXJmYWNlSXRlbUJhc2UqIGNyZWF0ZUludGVyZmFjZUl0ZW0oZXRSdW50aW1lOjpJSW50ZXJmYWNlSXRlbU93bmVyKiByY3YsIGNvbnN0IGV0UnVudGltZTo6U3RyaW5nJiBuYW1lLCBpbnQgbGlkLCBpbnQgaWR4KSB7CgkJCQlyZXR1cm4gbmV3IKtwb3J0Q2xhc3NOYW1luyhyY3YsIG5hbWUsIGxpZCwgaWR4KTsKCQkJfQoKCX07CgknJycKCX0KCglkZWYgcHJvdGVjdGVkIGdlbmVyYXRlU291cmNlRmlsZShSb290IHJvb3QsIFByb3RvY29sQ2xhc3MgcGMpIHsnJycKCQkvKioKCQkgKiBAYXV0aG9yIGdlbmVyYXRlZCBieSBlVHJpY2UKCQkgKgoJCSAqIFNvdXJjZSBGaWxlIG9mIFByb3RvY29sQ2xhc3Mgq3BjLm5hbWW7CgkJICoKCQkgKi8KCgkJI2luY2x1ZGUgIqtwYy5nZXRDcHBIZWFkZXJGaWxlTmFtZbsiCgoJCSNpbmNsdWRlICJjb21tb24vZGVidWdnaW5nL0RlYnVnZ2luZ1NlcnZpY2UuaCIKCQkjaW5jbHVkZSAiY29tbW9uL2RlYnVnZ2luZy9NU0NGdW5jdGlvbk9iamVjdC5oIgoJCSNpbmNsdWRlICJjb21tb24vbWVzc2FnaW5nL0Fic3RyYWN0TWVzc2FnZVJlY2VpdmVyLmgiCgkJI2luY2x1ZGUgImNvbW1vbi9tZXNzYWdpbmcvQWRkcmVzcy5oIgoJCSNpbmNsdWRlICJjb21tb24vbWVzc2FnaW5nL01lc3NhZ2UuaCIKCQkjaW5jbHVkZSAiY29tbW9uL21vZGVsYmFzZS9JRXZlbnRSZWNlaXZlci5oIgoKCQl1c2luZyBuYW1lc3BhY2UgZXRSdW50aW1lOwoKCQmrcGMuZ2VuZXJhdGVOYW1lc3BhY2VCZWdpbrsKCgkJq3BjLnVzZXJDb2RlKDMpuwoKCQkvKiBtZXNzYWdlIG5hbWVzIGFzIHN0cmluZ3MgZm9yIGRlYnVnZ2luZyAoZ2VuZXJhdGUgTVNDKSAqLwoJCWNvbnN0IFN0cmluZyCrcGMubmFtZbs6OnNfbWVzc2FnZVN0cmluZ3NbXSA9IHsiTUlOIiwgq0ZPUiBtIDogcGMuZ2V0QWxsT3V0Z29pbmdNZXNzYWdlcygpuyKrbS5uYW1luyIsq0VOREZPUrsgq0ZPUiBtIDogcGMuZ2V0QWxsSW5jb21pbmdNZXNzYWdlcygpuyKrbS5uYW1luyIsq0VOREZPUrsiTUFYIn07CgoJCWNvbnN0IFN0cmluZyYgq3BjLm5hbWW7OjpnZXRNZXNzYWdlU3RyaW5nKGludCBtc2dfaWQpIHsKCQkJaWYgKChNU0dfTUlOIDwgbXNnX2lkICkgJiYgKCBtc2dfaWQgPCBNU0dfTUFYICkpIHsKCQkJCXJldHVybiBzX21lc3NhZ2VTdHJpbmdzW21zZ19pZF07CgkJCX0gZWxzZSB7CgkJCQkvLyBpZCBvdXQgb2YgcmFuZ2UKCQkJCXN0YXRpYyBjb25zdCBTdHJpbmcgZXJyb3JNc2cgPSAiTWVzc2FnZSBJRCBvdXQgb2YgcmFuZ2UiOwoJCQkJcmV0dXJuIGVycm9yTXNnOwoJCQl9CgkJfQoKCQmrcG9ydENsYXNzSW1wbGVtZW50YXRpb24ocGMsIGZhbHNlKbsKCQmrcG9ydENsYXNzSW1wbGVtZW50YXRpb24ocGMsIHRydWUpuwoKCQmrcGMuZ2VuZXJhdGVOYW1lc3BhY2VFbmS7CgoJJycnCgl9CgoKCWRlZiBwcm90ZWN0ZWQgcG9ydENsYXNzSW1wbGVtZW50YXRpb24oUHJvdG9jb2xDbGFzcyBwYywgYm9vbGVhbiBjb25qKSB7CgkJdmFyIHBjbGFzcyA9IHBjLmdldFBvcnRDbGFzcyhjb25qKQoJCXZhciBwb3J0Q2xhc3NOYW1lID0gcGMuZ2V0UG9ydENsYXNzTmFtZShjb25qKQoJCXZhciByZXBsUG9ydENsYXNzTmFtZSA9IHBjLmdldFBvcnRDbGFzc05hbWUoY29uaiwgdHJ1ZSkKCScnJwoJLy8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCS8vIKtJRiBjb25qu2Nvbmp1Z2F0ZWQgq0VORElGu3BvcnQgY2xhc3MKCS8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgoJq3BvcnRDbGFzc05hbWW7OjqrcG9ydENsYXNzTmFtZbsoSUludGVyZmFjZUl0ZW1Pd25lciogYWN0b3IsIGNvbnN0IFN0cmluZyYgbmFtZSwgaW50IGxvY2FsSWQpCgkJq3BjbGFzcy5nZW5lcmF0ZUNvbnN0cnVjdG9ySW5pdGFsaXplckxpc3QoJzAnKbsKCXsKCX0KCgmrcG9ydENsYXNzTmFtZbs6Oqtwb3J0Q2xhc3NOYW1luyhJSW50ZXJmYWNlSXRlbU93bmVyKiBhY3RvciwgY29uc3QgU3RyaW5nJiBuYW1lLCBpbnQgbG9jYWxJZCwgaW50IGlkeCkKCQmrcGNsYXNzLmdlbmVyYXRlQ29uc3RydWN0b3JJbml0YWxpemVyTGlzdCgnaWR4Jym7Cgl7CgkJq0lGIHBjbGFzcyAhPT0gbnVsbLuraW5pdEhlbHBlci5nZW5FeHRyYUluaXRpYWxpemVycyhwY2xhc3MuYXR0cmlidXRlcym7q0VORElGuwoJfQoJq0lGIE1haW46OnNldHRpbmdzLmdlbmVyYXRlTVNDSW5zdHJ1bWVudGF0aW9uuwoKCQl2b2lkIKtwb3J0Q2xhc3NOYW1luzo6ZGVzdHJveSgpIHsKCQkJRGVidWdnaW5nU2VydmljZTo6Z2V0SW5zdGFuY2UoKS5yZW1vdmVQb3J0SW5zdGFuY2UoKnRoaXMpOwoJCQlQb3J0QmFzZTo6ZGVzdHJveSgpOwoJCX0KCatFTkRJRrsKCgl2b2lkIKtwb3J0Q2xhc3NOYW1luzo6cmVjZWl2ZShjb25zdCBNZXNzYWdlKiBtc2cpIHsKCQkvLyBUT0RPIEpIIGZ1cnRoZXIKCQlpZiAoISCrcGMubmFtZbs6OqtJRiBjb25qu2lzVmFsaWRPdXRnb2luZ0V2dElEq0VMU0W7aXNWYWxpZEluY29taW5nRXZ0SUSrRU5ESUa7KG1zZy0+Z2V0RXZ0SWQoKSkpIHsKCQkJLy9zdGQ6OmNvdXQgPDwgInVua25vd24iIDw8IHN0ZDo6ZW5kbDsKCQl9CgoJCatJRiBNYWluOjpzZXR0aW5ncy5nZW5lcmF0ZU1TQ0luc3RydW1lbnRhdGlvbrsKCQkJRGVidWdnaW5nU2VydmljZTo6Z2V0SW5zdGFuY2UoKS5hZGRNZXNzYWdlQXN5bmNJbihnZXRQZWVyQWRkcmVzcygpLCBnZXRBZGRyZXNzKCksIKtwYy5uYW1luzo6Z2V0TWVzc2FnZVN0cmluZyhtc2ctPmdldEV2dElkKCkpLmNfc3RyKCkpOwoJCatFTkRJRrsKCgkJq0lGIHBjLmhhbmRsZXNSZWNlaXZlKGNvbmopuwoJCQlzd2l0Y2ggKG1zZy0+Z2V0RXZ0SWQoKSkgewoJCQkJq0ZPUiBoZGxyIDogcGMuZ2V0UmVjZWl2ZUhhbmRsZXJzKGNvbmopuwoJCQkJY2FzZSCrcGMubmFtZbs6OqtoZGxyLm1zZy5nZXRDb2RlTmFtZSgpuzoKCQkJCQl7CgkJCQkJCatGT1IgY29tbWFuZCA6IGhkbHIuZGV0YWlsQ29kZS5saW5lc7sKCQkJCQkJq2NvbW1hbmS7CgkJCQkJCatFTkRGT1K7CgkJCQkJfQoJCQkJCWJyZWFrOwoJCQkJq0VOREZPUrsKCQkJCWRlZmF1bHQ6CgkJCatFTkRJRrsKCQlnZXRBY3RvcigpLT5yZWNlaXZlRXZlbnQodGhpcywgbXNnLT5nZXRFdnRJZCgpLAltc2ctPmdldERhdGEoKSk7CgkJq0lGIHBjLmhhbmRsZXNSZWNlaXZlKGNvbmopuwoJCQkJCWJyZWFrOwoJCQl9CgkJq0VORElGuwoJfQoKCatJRiBwY2xhc3MhPT1udWxsuwoJCatwY2xhc3Mub3BlcmF0aW9ucy5vcGVyYXRpb25zSW1wbGVtZW50YXRpb24ocG9ydENsYXNzTmFtZSm7CgmrRU5ESUa7CgoJLy8gc2VudCBtZXNzYWdlcwoJq0ZPUiBtIDogcGMuZ2V0QWxsTWVzc2FnZXMoY29uaim7CgkJq3NlbmRNZXNzYWdlKG0sIHBjLm5hbWUsIHBvcnRDbGFzc05hbWUsIGNvbmopuwoJq0VOREZPUrsKCgkvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoJLy8gq0lGIGNvbmq7Y29uanVnYXRlZCCrRU5ESUa7cmVwbGljYXRlZCBwb3J0IGNsYXNzCgkvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoJq3JlcGxQb3J0Q2xhc3NOYW1luzo6q3JlcGxQb3J0Q2xhc3NOYW1luyhJSW50ZXJmYWNlSXRlbU93bmVyKiBhY3RvciwgY29uc3QgU3RyaW5nJiBuYW1lLCBpbnQgbG9jYWxJZCkgOgoJCQlSZXBsaWNhdGVkUG9ydEJhc2UoYWN0b3IsIG5hbWUsIGxvY2FsSWQpCgl7Cgl9CgoJq0lGIGNvbmq7CgkJLy8gaW5jb21pbmcgbWVzc2FnZXMKCQmrRk9SIG0gOiBwYy5nZXRBbGxJbmNvbWluZ01lc3NhZ2VzKCm7CgkJCattZXNzYWdlU2lnbmF0dXJlRGVmaW5pdGlvbihtLCByZXBsUG9ydENsYXNzTmFtZSwgZmFsc2Upu3sKCQkJCWZvciAoVmVjdG9yPGV0UnVudGltZTo6SW50ZXJmYWNlSXRlbUJhc2UqPjo6aXRlcmF0b3IgaXQgPSBnZXRJdGVtcygpLmJlZ2luKCk7IGl0ICE9IGdldEl0ZW1zKCkuZW5kKCk7ICsraXQpIHsKCQkJCQkoZHluYW1pY19jYXN0PKtwb3J0Q2xhc3NOYW1luyo+KCppdCkpLT6rbWVzc2FnZUNhbGwobSwgZmFsc2UpuzsKCQkJCX0KCQkJfQoJCatFTkRGT1K7CgmrRUxTRbsKCQkvLyBvdXRnb2luZyBtZXNzYWdlcwoJCatGT1IgbSA6IHBjLmdldEFsbE91dGdvaW5nTWVzc2FnZXMoKbsKCQkJq21lc3NhZ2VTaWduYXR1cmVEZWZpbml0aW9uKG0sIHJlcGxQb3J0Q2xhc3NOYW1lLCBmYWxzZSm7ewoJCQkJZm9yIChWZWN0b3I8ZXRSdW50aW1lOjpJbnRlcmZhY2VJdGVtQmFzZSo+OjppdGVyYXRvciBpdCA9IGdldEl0ZW1zKCkuYmVnaW4oKTsgaXQgIT0gZ2V0SXRlbXMoKS5lbmQoKTsgKytpdCkgewoJCQkJCShkeW5hbWljX2Nhc3Q8q3BvcnRDbGFzc05hbWW7Kj4oKml0KSktPqttZXNzYWdlQ2FsbChtLCBmYWxzZSm7OwoJCQkJfQoJCQl9CgkJq0VOREZPUrsKCatFTkRJRrsKCScnJwoJfQoKCWRlZiBwcml2YXRlIGdlbmVyYXRlQ29uc3RydWN0b3JJbml0YWxpemVyTGlzdChQb3J0Q2xhc3MgcGMsIFN0cmluZyBpbmRleCkgewoJCXZhbCBleHRlbnNpb24gaW5pdEhlbHBlciA9IGluaXRIZWxwZXIKCQl2YWwgTGlzdDxDaGFyU2VxdWVuY2U+IGluaXRMaXN0ID0gbmV3QXJyYXlMaXN0CgoJCWluaXRMaXN0ICs9ICcnJ1BvcnRCYXNlKGFjdG9yLCBuYW1lLCBsb2NhbElkLCCraW5kZXi7KScnJwoJCWlmKHBjICE9PSBudWxsKQoJCQlpbml0TGlzdCArPSBwYy5hdHRyaWJ1dGVzLm1hcFsnJyerbmFtZbsoq2luaXRpYWxpemVyTGlzdFZhbHVluyknJyddCgoJCWluaXRMaXN0LmdlbmVyYXRlQ3RvckluaXRpYWxpemVyTGlzdAoJfQoKCWRlZiBwcm90ZWN0ZWQgbWVzc2FnZUNhbGwoTWVzc2FnZSBtLCBib29sZWFuIGltcGwpIHsKCQknJyerbS5uYW1lu6tJRiBpbXBsu19pbXBsq0VORElGuyirSUYgbS5kYXRhIT09bnVsbLsgq0lMYW5ndWFnZUV4dGVuc2lvbi5HRU5FUklDX0RBVEFfTkFNRburRU5ESUa7KScnJwoJfQoKCglkZWYgcHJvdGVjdGVkIG1lc3NhZ2VTaWduYXR1cmUoTWVzc2FnZSBtLCBib29sZWFuIGltcGwpIHsKCQknJyerSUYgbS5wcml2fHxpbXBsu3ByaXZhdGU6q0VMU0W7cHVibGljOqtFTkRJRrsgdm9pZCCrbS5uYW1lu6tJRiBpbXBsu19pbXBsq0VORElGuyirSUYgbS5kYXRhIT09bnVsbLurbS5kYXRhLnJlZlR5cGUuc2lnbmF0dXJlU3RyaW5nuyCrSUxhbmd1YWdlRXh0ZW5zaW9uLkdFTkVSSUNfREFUQV9OQU1Fu6tFTkRJRrspJycnCgl9CgoJZGVmIHByb3RlY3RlZCBtZXNzYWdlU2lnbmF0dXJlRGVmaW5pdGlvbihNZXNzYWdlIG0sIFN0cmluZyBjbGFzc1ByZWZpeCwgYm9vbGVhbiBpbXBsKSB7CgkJJycndm9pZCCrY2xhc3NQcmVmaXi7OjqrbS5uYW1lu6tJRiBpbXBsu19pbXBsq0VORElGuyirSUYgbS5kYXRhIT09bnVsbLurbS5kYXRhLnJlZlR5cGUuc2lnbmF0dXJlU3RyaW5nuyCrSUxhbmd1YWdlRXh0ZW5zaW9uLkdFTkVSSUNfREFUQV9OQU1Fu6tFTkRJRrspJycnCgl9CgoJZGVmIHByb3RlY3RlZCBzZW5kTWVzc2FnZShNZXNzYWdlIG0sIFN0cmluZyBwb3J0Q2xhc3NOYW1lLCBTdHJpbmcgY2xhc3NQcmVmaXgsIGJvb2xlYW4gY29uaikgewoJCXZhciBkaXIgPSBpZiAoY29uaikgIklOIiBlbHNlICJPVVQiCgkJdmFyIGhkbHIgPSBtLmdldFNlbmRIYW5kbGVyKGNvbmopCgkJdmFsIGRhdGFBcmcgPSBpZihtLmRhdGEgIT09IG51bGwpICcnJywgq0lMYW5ndWFnZUV4dGVuc2lvbi5HRU5FUklDX0RBVEFfTkFNRbsnJycKCQl2YWwgbWVzc2FnZVR5cGUgPSBpZihtLmRhdGEgIT09IG51bGwgJiYgIW0uZGF0YS5yZWZUeXBlLnJlZikgJycnRGF0YU1lc3NhZ2U8q20uZGF0YS5yZWZUeXBlLnR5cGUudHlwZU5hbWW7PicnJyBlbHNlICcnJ01lc3NhZ2UnJycKCQl2YWwgbWVzc2FnZSA9ICcnJ25ldyAoYnVmZmVyKSCrbWVzc2FnZVR5cGW7KGdldFBlZXJBZGRyZXNzKCksIKtwb3J0Q2xhc3NOYW1luzo6q2Rpcrtfq20ubmFtZburZGF0YUFyZz86Jye7KScnJwoJCScnJwoJCQmrbWVzc2FnZVNpZ25hdHVyZURlZmluaXRpb24obSwgY2xhc3NQcmVmaXgsIGZhbHNlKbsgewoJCQkJq0lGIGhkbHIhPT1udWxsuwoJCQkJCatGT1IgY29tbWFuZCA6IGhkbHIuZGV0YWlsQ29kZS5saW5lc7sJq2NvbW1hbmS7CgkJCQkJq0VOREZPUrsKCQkJCatFTFNFuwoJCQkJCattZXNzYWdlQ2FsbChtLCB0cnVlKbs7CgkJCQmrRU5ESUa7CgkJCX0KCQkJCgkJCattZXNzYWdlU2lnbmF0dXJlRGVmaW5pdGlvbihtLCBjbGFzc1ByZWZpeCwgdHJ1ZSm7IHsKCQkJCatJRiBNYWluOjpzZXR0aW5ncy5nZW5lcmF0ZU1TQ0luc3RydW1lbnRhdGlvbrsKCQkJCQlEZWJ1Z2dpbmdTZXJ2aWNlOjpnZXRJbnN0YW5jZSgpLmFkZE1lc3NhZ2VBc3luY091dChnZXRBZGRyZXNzKCksIGdldFBlZXJBZGRyZXNzKCksCgkJCQkJCatwb3J0Q2xhc3NOYW1luzo6Z2V0TWVzc2FnZVN0cmluZyircG9ydENsYXNzTmFtZbs6OqtkaXK7X6ttLm5hbWW7KS5jX3N0cigpKTsKCQkJCatFTkRJRrsKCQkJCWlmIChnZXRQZWVyQWRkcmVzcygpLmlzVmFsaWQoKSkgewqrq6sJCQkJCXdlIGhhdmUgdG8gdXNlIGEgZHluYW1pYyBjYXN0IGhlcmUgYmVjYXVzZSB3ZSBoYXZlIGEgdmlydHVhbCBiYXNlIGNsYXNzCgkJCQkJTWVzc2FnZSogYnVmZmVyID0gZHluYW1pY19jYXN0PElNZXNzYWdlU2VydmljZSo+KGdldFBlZXJNc2dSZWNlaXZlcigpKS0+Z2V0TWVzc2FnZUJ1ZmZlcihzaXplb2Yoq21lc3NhZ2VUeXBluykpOwqrq6sJCQkJCS8vIFRPRE8gSkI6IEhhbmRsZSBidWZmZXIgPT0gTlVMTAoJCQkJCWlmIChidWZmZXIpIHsKCQkJCQkJZ2V0UGVlck1zZ1JlY2VpdmVyKCktPnJlY2VpdmUoq21lc3NhZ2W7KTsKCQkJCQl9CgkJCQl9CgkJCX0KCQknJycKCX0KCgoJZGVmIHByb3RlY3RlZCBnZW5lcmF0ZURhdGFEcml2ZW5IZWFkZXJGaWxlKFJvb3Qgcm9vdCwgUHJvdG9jb2xDbGFzcyBwYykgewoJCXZhbCBzZW50TXNncyA9IHBjLmFsbEluY29taW5nTWVzc2FnZXMuZmlsdGVyKG18bS5kYXRhIT09bnVsbCkKCQknJycKCQkJLyoqCgkJCSAqIEBhdXRob3IgZ2VuZXJhdGVkIGJ5IGVUcmljZQoJCQkgKgoJCQkgKiBIZWFkZXIgRmlsZSBvZiBQcm90b2NvbENsYXNzIKtwYy5uYW1luwoJCQkgKgoJCQkgKi8KCgkJCatwYy5nZW5lcmF0ZUluY2x1ZGVHdWFyZEJlZ2luKCcnKbsKCgkJCSNpbmNsdWRlICJjb21tb24vZXREYXRhdHlwZXNDcHAuaHBwIgoJCQkjaW5jbHVkZSAiY29tbW9uL21vZGVsYmFzZS9EYXRhUG9ydC5oIgoJCQmrRk9SIGRhdGFDbGFzcyA6IHJvb3QuZ2V0UmVmZXJlbmNlZERhdGFDbGFzc2VzKHBjKbsKCQkJCSNpbmNsdWRlICKrZGF0YUNsYXNzLnBhdGi7q2RhdGFDbGFzcy5uYW1luy5oIgoJCQmrRU5ERk9SuwoKCQkJq3BjLnVzZXJDb2RlMS51c2VyQ29kZbsKCgkJCatwYy5nZW5lcmF0ZU5hbWVzcGFjZUJlZ2luuwoKCQkJY2xhc3Mgq3BjLm5hbWW7IHsKCgkJCQmrcGMudXNlckNvZGUyLnVzZXJDb2RluwoKCQkJfTsKCgkJCS8vIHNlbmQgcG9ydCBob2xkcyBkYXRhCgkJCWNsYXNzIKtwYy5nZXRQb3J0Q2xhc3NOYW1lKHRydWUpuyA6IHB1YmxpYyBldFJ1bnRpbWU6OkRhdGFTZW5kUG9ydCB7CgoJCQlwdWJsaWM6CgkJCQmrcGMuZ2V0UG9ydENsYXNzTmFtZSh0cnVlKbsoZXRSdW50aW1lOjpJUlRPYmplY3QqIHBhcmVudCwgY29uc3QgZXRSdW50aW1lOjpTdHJpbmcmIG5hbWUsIGludCBsb2NhbElkKTsKCgkJCQkvLyBnZXR0ZXJzIGFuZCBzZXR0ZXJzCgkJCQmrRk9SIG1zZyA6IHNlbnRNc2dzuwoJCQkJCXZvaWQgq21zZy5uYW1luyirbXNnLmRhdGEucmVmVHlwZS50eXBlLnR5cGVOYW1luyCrbXNnLm5hbWW7KSB7CgkJCQkJCW1fq21zZy5uYW1luyA9IKttc2cubmFtZbs7CgkJCQkJfQoJCQkJCattc2cuZGF0YS5yZWZUeXBlLnR5cGUudHlwZU5hbWW7IKttc2cubmFtZbsoKSBjb25zdCB7CgkJCQkJCXJldHVybiBtX6ttc2cubmFtZbs7CgkJCQkJfQoJCQkJq0VOREZPUrsKCgkJCXByaXZhdGU6CgkJCQmrRk9SIG1zZyA6IHNlbnRNc2dzuwoJCQkJCattc2cuZGF0YS5yZWZUeXBlLnR5cGUudHlwZU5hbWW7IG1fq21zZy5uYW1luzsKCQkJCatFTkRGT1K7CgkJCX07CgoJCQkvLyByZWNlaXZlIHBvcnQgYWNjZXNzZXMgc2VuZCBwb3J0CgkJCWNsYXNzIKtwYy5nZXRQb3J0Q2xhc3NOYW1lKGZhbHNlKbsgOiBwdWJsaWMgZXRSdW50aW1lOjpEYXRhUmVjZWl2ZVBvcnQgewoKCQkJcHVibGljOgoJCQkJq3BjLmdldFBvcnRDbGFzc05hbWUoZmFsc2UpuyhldFJ1bnRpbWU6OklSVE9iamVjdCogcGFyZW50LCBjb25zdCBldFJ1bnRpbWU6OlN0cmluZyYgbmFtZSwgaW50IGxvY2FsSWQpOwoKCQkJCS8vIGdldHRlcnMKCQkJCatGT1IgbXNnIDogc2VudE1zZ3O7CgkJCQkJq21zZy5kYXRhLnJlZlR5cGUudHlwZS50eXBlTmFtZbsgq21zZy5uYW1luygpIGNvbnN0OwoJCQkJq0VOREZPUrsKCgkJCXByb3RlY3RlZDoKCQkJCXZpcnR1YWwgdm9pZCBjb25uZWN0KGV0UnVudGltZTo6RGF0YVNlbmRQb3J0KiBkYXRhU2VuZFBvcnQpOwoKCQkJcHJpdmF0ZToKCQkJCatwYy5nZXRQb3J0Q2xhc3NOYW1lKHRydWUpuyogbV9wZWVyOwoKCQkJfTsKCgkJCatwYy5nZW5lcmF0ZU5hbWVzcGFjZUVuZLsKCgkJCatwYy5nZW5lcmF0ZUluY2x1ZGVHdWFyZEVuZCgnJym7CgkJJycnCgl9CgoJZGVmIHByb3RlY3RlZCBnZW5lcmF0ZURhdGFEcml2ZW5Tb3VyY2VGaWxlKFJvb3Qgcm9vdCwgUHJvdG9jb2xDbGFzcyBwYykgewoJCXZhbCBzZW50TXNncyA9IHBjLmFsbEluY29taW5nTWVzc2FnZXMuZmlsdGVyKG18bS5kYXRhIT09bnVsbCkKCQknJycKCQkJLyoqCgkJCSAqIEBhdXRob3IgZ2VuZXJhdGVkIGJ5IGVUcmljZQoJCQkgKgoJCQkgKiBTb3VyY2UgRmlsZSBvZiBQcm90b2NvbENsYXNzIKtwYy5uYW1luwoJCQkgKgoJCQkgKi8KCgkJCSNpbmNsdWRlICKrcGMuZ2V0Q3BwSGVhZGVyRmlsZU5hbWW7IgoKCQkJdXNpbmcgbmFtZXNwYWNlIGV0UnVudGltZTsKCgkJCatwYy5nZW5lcmF0ZU5hbWVzcGFjZUJlZ2luuwoKCQkJq3BjLnVzZXJDb2RlMy51c2VyQ29kZbsKCqurqwkJCatGT1IgbW9kZWwgOiBtb2RlbHO7CqurqwkJCQlpbXBvcnQgq21vZGVsLm5hbWW7Lio7CqurqwkJCatFTkRGT1K7CgkJCS8vIHNlbmQgcG9ydCBob2xkcyBkYXRhCgoJCQkvLyBjb25zdHJ1Y3RvcgoJCQmrcGMuZ2V0UG9ydENsYXNzTmFtZSh0cnVlKbs6OqtwYy5nZXRQb3J0Q2xhc3NOYW1lKHRydWUpuyhJUlRPYmplY3QqIHBhcmVudCwgY29uc3QgU3RyaW5nJiBuYW1lLCBpbnQgbG9jYWxJZCkgOgoJCQkJCURhdGFTZW5kUG9ydChwYXJlbnQsIG5hbWUsIGxvY2FsSWQpCgkJCXsKCQkJfQoKCQkJLy8gcmVjZWl2ZSBwb3J0IGFjY2Vzc2VzIHNlbmQgcG9ydAoKCQkJLy8gY29uc3RydWN0b3IKCQkJq3BjLmdldFBvcnRDbGFzc05hbWUoZmFsc2Upuzo6q3BjLmdldFBvcnRDbGFzc05hbWUoZmFsc2UpuyhJUlRPYmplY3QqIHBhcmVudCwgY29uc3QgU3RyaW5nJiBuYW1lLCBpbnQgbG9jYWxJZCkgOgoJCQkJCURhdGFSZWNlaXZlUG9ydChwYXJlbnQsIG5hbWUsIGxvY2FsSWQpLAoJCQkJCW1fcGVlcigwKQoJCQl7CgoJCQl9CgoJCQkvLyBnZXR0ZXJzCgkJCatGT1IgbXNnIDogc2VudE1zZ3O7CgkJCQmrbXNnLmRhdGEucmVmVHlwZS50eXBlLnR5cGVOYW1luyCrcGMuZ2V0UG9ydENsYXNzTmFtZShmYWxzZSm7OjqrbXNnLm5hbWW7KCkgY29uc3QgewoJCQkJCS8vIFRPRE8gbmVlZHMgZGVmYXVsdCB2YWx1ZQoJCQkJCS8vaWYgKG1fcGVlciA9PSAwKQoJCQkJCS8qCXJldHVybiCrbXNnLmRhdGEucmVmVHlwZS50eXBlLmRlZmF1bHRWYWx1Zbs7ICovCgkJCQkJcmV0dXJuIG1fcGVlci0+q21zZy5uYW1luygpOwoJCQkJfQoJCQmrRU5ERk9SuwoKCQkJdm9pZCCrcGMuZ2V0UG9ydENsYXNzTmFtZShmYWxzZSm7Ojpjb25uZWN0KERhdGFTZW5kUG9ydCogZGF0YVNlbmRQb3J0KSB7CgkJCQmrcGMuZ2V0UG9ydENsYXNzTmFtZSh0cnVlKbsqIHBlZXIgPSBkeW5hbWljX2Nhc3Q8q3BjLmdldFBvcnRDbGFzc05hbWUodHJ1ZSm7Kj4oZGF0YVNlbmRQb3J0KTsKCQkJCWlmIChwZWVyICE9IDApCgkJCQkJbV9wZWVyID0gcGVlcjsKCQkJfQoKCQkJq3BjLmdlbmVyYXRlTmFtZXNwYWNlRW5kuwoKCQknJycKCX0KCglvdmVycmlkZSBnZXRNZXNzYWdlSUQoTWVzc2FnZSBtc2csIEludGVyZmFjZUl0ZW0gaXRlbSkgewoJCWlmIChpdGVtIGluc3RhbmNlb2YgUG9ydCkgewoJCQl2YXIgcCA9IGl0ZW0gYXMgUG9ydDsKCQkJdmFyIGRpcmVjdGlvbiA9IGlmIChwLmlzQ29uanVnYXRlZCgpKSJPVVRfIiBlbHNlICJJTl8iCgkJCXJldHVybiBlbnVtSW5Vc2UocC5nZXRQcm90b2NvbCgpLmdldE5hbWUoKSwgZGlyZWN0aW9uK21zZy5nZXROYW1lKCkpCgkJfQoJCWVsc2UgaWYgKGl0ZW0gaW5zdGFuY2VvZiBTQVApIHsKCQkJdmFyIHNhcCA9IGl0ZW0gYXMgU0FQOwoJCQlyZXR1cm4gZW51bUluVXNlKHNhcC5nZXRQcm90b2NvbCgpLmdldE5hbWUoKSwgIk9VVF8iK21zZy5nZXROYW1lKCkpCgkJfQoJCWVsc2UgaWYgKGl0ZW0gaW5zdGFuY2VvZiBTUFApIHsKCQkJdmFyIHNwcCA9IGl0ZW0gYXMgU1BQOwoJCQlyZXR1cm4gZW51bUluVXNlKHNwcC5nZXRQcm90b2NvbCgpLmdldE5hbWUoKSwgIklOXyIrbXNnLmdldE5hbWUoKSkKCQl9CgoJCXJldHVybiAidW5rbm93biBpbnRlcmZhY2UgaXRlbSI7Cgl9CgoJZGVmIHByb3RlY3RlZCBTdHJpbmcgZW51bUluVXNlKFN0cmluZyBuYW1lc3BhY2UsIFN0cmluZyBtZW1iZXIpIHsKCQlyZXR1cm4gbmFtZXNwYWNlKyI6OiIrbWVtYmVyCgl9Cn0=