LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogQ29weXJpZ2h0IChjKSAyMDAzLCAyMDA1IElCTSBDb3Jwb3JhdGlvbiBhbmQgb3RoZXJzLgogKiBBbGwgcmlnaHRzIHJlc2VydmVkLiBUaGlzIHByb2dyYW0gYW5kIHRoZSBhY2NvbXBhbnlpbmcgbWF0ZXJpYWxzCiAqIGFyZSBtYWRlIGF2YWlsYWJsZSB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEVjbGlwc2UgUHVibGljIExpY2Vuc2UgdjEuMAogKiB3aGljaCBhY2NvbXBhbmllcyB0aGlzIGRpc3RyaWJ1dGlvbiwgYW5kIGlzIGF2YWlsYWJsZSBhdAogKiBodHRwOi8vd3d3LmVjbGlwc2Uub3JnL2xlZ2FsL2VwbC12MTAuaHRtbAqgKgogKiBDb250cmlidXRvcnM6CiAqICAgIElCTSBDb3Jwb3JhdGlvbiAtIEluaXRpYWwgQVBJIGFuZCBpbXBsZW1lbnRhdGlvbgogKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KcGFja2FnZSBvcmcuZWNsaXBzZS5qc3Quc2VydmVyLnRvbWNhdC5jb3JlLmludGVybmFsOwoKaW1wb3J0IGphdmEuaW8uKjsKaW1wb3J0IGphdmEudXRpbC5BcnJheUxpc3Q7CmltcG9ydCBqYXZhLnV0aWwuSGFzaFNldDsKaW1wb3J0IGphdmEudXRpbC5JdGVyYXRvcjsKaW1wb3J0IGphdmEudXRpbC5MaXN0OwppbXBvcnQgamF2YS51dGlsLlNldDsKCmltcG9ydCBvcmcuZWNsaXBzZS5jb3JlLnJlc291cmNlcy5JRmlsZTsKaW1wb3J0IG9yZy5lY2xpcHNlLmNvcmUucmVzb3VyY2VzLklGb2xkZXI7CmltcG9ydCBvcmcuZWNsaXBzZS5jb3JlLnJ1bnRpbWUuKjsKaW1wb3J0IG9yZy5lY2xpcHNlLmpzdC5zZXJ2ZXIudG9tY2F0LmNvcmUuaW50ZXJuYWwueG1sLkZhY3Rvcnk7CmltcG9ydCBvcmcuZWNsaXBzZS5qc3Quc2VydmVyLnRvbWNhdC5jb3JlLmludGVybmFsLnhtbC5YTUxVdGlsOwppbXBvcnQgb3JnLmVjbGlwc2UuanN0LnNlcnZlci50b21jYXQuY29yZS5pbnRlcm5hbC54bWwuc2VydmVyNDAuKjsKaW1wb3J0IG9yZy53M2MuZG9tLkRvY3VtZW50OwppbXBvcnQgb3JnLnhtbC5zYXguSW5wdXRTb3VyY2U7CgppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNlcnZlci5jb3JlLlNlcnZlclBvcnQ7Ci8qKgogKiBUb21jYXQgdjUuMCBzZXJ2ZXIgY29uZmlndXJhdGlvbi4KICovCnB1YmxpYyBjbGFzcyBUb21jYXQ1MENvbmZpZ3VyYXRpb24gZXh0ZW5kcyBUb21jYXRDb25maWd1cmF0aW9uIHsKCXByb3RlY3RlZCBzdGF0aWMgZmluYWwgU3RyaW5nIERFRkFVTFRfU0VSVklDRSA9ICJDYXRhbGluYSI7Cglwcm90ZWN0ZWQgU2VydmVyIHNlcnZlcjsKCXByb3RlY3RlZCBGYWN0b3J5IHNlcnZlckZhY3Rvcnk7Cglwcm90ZWN0ZWQgYm9vbGVhbiBpc1NlcnZlckRpcnR5OwoKCXByb3RlY3RlZCBXZWJBcHBEb2N1bWVudCB3ZWJBcHBEb2N1bWVudDsKCglwcm90ZWN0ZWQgRG9jdW1lbnQgdG9tY2F0VXNlcnNEb2N1bWVudDsKCglwcm90ZWN0ZWQgU3RyaW5nIHBvbGljeUZpbGU7Cglwcm90ZWN0ZWQgYm9vbGVhbiBpc1BvbGljeURpcnR5OwoKCS8qKgoJICogVG9tY2F0NTBDb25maWd1cmF0aW9uIGNvbnN0cnVjdG9yIGNvbW1lbnQuCgkgKi8KCXB1YmxpYyBUb21jYXQ1MENvbmZpZ3VyYXRpb24oSUZvbGRlciBwYXRoKSB7CgkJc3VwZXIocGF0aCk7Cgl9CgkKCS8qKgoJICogUmV0dXJucyB0aGUgcm9vdCBvZiB0aGUgZG9jYmFzZSBwYXJhbWV0ZXIuCgkgKgoJICogQHJldHVybiBqYXZhLmxhbmcuU3RyaW5nCgkgKi8KCXByb3RlY3RlZCBTdHJpbmcgZ2V0RG9jQmFzZVJvb3QoKSB7CgkJcmV0dXJuICJ3ZWJhcHBzLyI7Cgl9CgoJLyoqCgkgKiBSZXR1cm4gdGhlIHBvcnQgbnVtYmVyLgoJICogQHJldHVybiBpbnQKCSAqLwoJcHVibGljIFNlcnZlclBvcnQgZ2V0TWFpblBvcnQoKSB7CgkJSXRlcmF0b3IgaXRlcmF0b3IgPSBnZXRTZXJ2ZXJQb3J0cygpLml0ZXJhdG9yKCk7CgkJd2hpbGUgKGl0ZXJhdG9yLmhhc05leHQoKSkgewoJCQlTZXJ2ZXJQb3J0IHBvcnQgPSAoU2VydmVyUG9ydCkgaXRlcmF0b3IubmV4dCgpOwoJCQlpZiAocG9ydC5nZXROYW1lKCkuZXF1YWxzKCJIVFRQIikpCgkJCQlyZXR1cm4gcG9ydDsKCQl9CgkJcmV0dXJuIG51bGw7Cgl9CgkKCS8qKgoJICogUmV0dXJucyB0aGUgbWltZSBtYXBwaW5ncy4KCSAqIEByZXR1cm4gamF2YS51dGlsLkxpc3QKCSAqLwoJcHVibGljIExpc3QgZ2V0TWltZU1hcHBpbmdzKCkgewoJCXJldHVybiB3ZWJBcHBEb2N1bWVudC5nZXRNaW1lTWFwcGluZ3MoKTsKCX0KCQoJLyoqCgkgKiBSZXR1cm5zIHRoZSBwcmVmaXggdGhhdCBpcyB1c2VkIGluIGZyb250IG9mIHRoZQoJICogd2ViIG1vZHVsZSBwYXRoIHByb3BlcnR5LiAoZS5nLiAid2ViYXBwcyIpCgkgKgoJICogQHJldHVybiBqYXZhLmxhbmcuU3RyaW5nCgkgKi8KCXB1YmxpYyBTdHJpbmcgZ2V0UGF0aFByZWZpeCgpIHsKCQlyZXR1cm4gIiI7Cgl9CgkKCS8qKgoJICogUmV0dXJuIHRoZSBkb2NCYXNlIG9mIHRoZSBST09UIHdlYiBtb2R1bGUuCgkgKgoJICogQHJldHVybiBqYXZhLmxhbmcuU3RyaW5nCgkgKi8KCXByb3RlY3RlZCBTdHJpbmcgZ2V0Uk9PVE1vZHVsZURvY0Jhc2UoKSB7CgkJcmV0dXJuICJST09UIjsKCX0KCQoJLyoqCgkgKiBSZXR1cm5zIGEgbGlzdCBvZiBTZXJ2ZXJQb3J0cyB0aGF0IHRoaXMgY29uZmlndXJhdGlvbiB1c2VzLgoJICoKCSAqIEByZXR1cm4gamF2YS51dGlsLkxpc3QKCSAqLwoJcHVibGljIExpc3QgZ2V0U2VydmVyUG9ydHMoKSB7CgkJTGlzdCBwb3J0cyA9IG5ldyBBcnJheUxpc3QoKTsKCQoJCS8vIGZpcnN0IGFkZCBzZXJ2ZXIgcG9ydAoJCXRyeSB7CgkJCWludCBwb3J0ID0gSW50ZWdlci5wYXJzZUludChzZXJ2ZXIuZ2V0UG9ydCgpKTsKCQkJcG9ydHMuYWRkKG5ldyBTZXJ2ZXJQb3J0KCJzZXJ2ZXIiLCBUb21jYXRQbHVnaW4uZ2V0UmVzb3VyY2UoIiVwb3J0U2VydmVyIiksIHBvcnQsICJUQ1BJUCIpKTsKCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkvLyBpZ25vcmUKCQl9CgkKCQkvLyBhZGQgY29ubmVjdG9ycwoJCXRyeSB7CgkJCWludCBzaXplID0gc2VydmVyLmdldFNlcnZpY2VDb3VudCgpOwoJCQlmb3IgKGludCBpID0gMDsgaSA8IHNpemU7IGkrKykgewoJCQkJU2VydmljZSBzZXJ2aWNlID0gc2VydmVyLmdldFNlcnZpY2UoaSk7CgkJCQlpbnQgc2l6ZTIgPSBzZXJ2aWNlLmdldENvbm5lY3RvckNvdW50KCk7CgkJCQlmb3IgKGludCBqID0gMDsgaiA8IHNpemUyOyBqKyspIHsKCQkJCQlDb25uZWN0b3IgY29ubmVjdG9yID0gc2VydmljZS5nZXRDb25uZWN0b3Ioaik7CgkJCQkJU3RyaW5nIG5hbWUgPSAiSFRUUCI7CgkJCQkJU3RyaW5nIHByb3RvY29sMiA9ICJIVFRQIjsKCQkJCQlib29sZWFuIGFkdmFuY2VkID0gdHJ1ZTsKCQkJCQlTdHJpbmdbXSBjb250ZW50VHlwZXMgPSBudWxsOwoJCQkJCWludCBwb3J0ID0gLTE7CgkJCQkJdHJ5IHsKCQkJCQkJcG9ydCA9IEludGVnZXIucGFyc2VJbnQoY29ubmVjdG9yLmdldFBvcnQoKSk7CgkJCQkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJCQkJLy8gaWdub3JlCgkJCQkJfQoJCQkJCVN0cmluZyBwcm90b2NvbCA9IGNvbm5lY3Rvci5nZXRQcm90b2NvbCgpOwoJCQkJCWlmIChwcm90b2NvbCAhPSBudWxsICYmIHByb3RvY29sLmxlbmd0aCgpID4gMCkgewoJCQkJCQluYW1lID0gcHJvdG9jb2w7CgkJCQkJCXByb3RvY29sMiA9IHByb3RvY29sOyAKCQkJCQl9CgkJCQkJaWYgKCJIVFRQIi5lcXVhbHMocHJvdG9jb2wpKQoJCQkJCQljb250ZW50VHlwZXMgPSBuZXcgU3RyaW5nW10geyAid2ViIiwgIndlYnNlcnZpY2VzIiB9OwoJCQkJCVN0cmluZyBzZWN1cmUgPSBjb25uZWN0b3IuZ2V0U2VjdXJlKCk7CgkJCQkJaWYgKHNlY3VyZSAhPSBudWxsICYmIHNlY3VyZS5sZW5ndGgoKSA+IDApIHsKCQkJCQkJbmFtZSA9ICJTU0wiOwoJCQkJCQlwcm90b2NvbDIgPSAiU1NMIjsKCQkJCQl9IGVsc2UKCQkJCQkJYWR2YW5jZWQgPSBmYWxzZTsKCQkJCQlwb3J0cy5hZGQobmV3IFNlcnZlclBvcnQoaSArIi8iICsgaiwgbmFtZSwgcG9ydCwgcHJvdG9jb2wyLCBjb250ZW50VHlwZXMsIGFkdmFuY2VkKSk7CgkJCQl9CgkJCX0KCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQlUcmFjZS50cmFjZShUcmFjZS5TRVZFUkUsICJFcnJvciBnZXR0aW5nIHNlcnZlciBwb3J0cyIsIGUpOwoJCX0KCQlyZXR1cm4gcG9ydHM7Cgl9CgkKCS8qKgoJICogUmV0dXJuIGEgbGlzdCBvZiB0aGUgd2ViIG1vZHVsZXMgaW4gdGhpcyBzZXJ2ZXIuCgkgKiBAcmV0dXJuIGphdmEudXRpbC5MaXN0CgkgKi8KCXB1YmxpYyBMaXN0IGdldFdlYk1vZHVsZXMoKSB7CgkJTGlzdCBsaXN0ID0gbmV3IEFycmF5TGlzdCgpOwoJCgkJdHJ5IHsKCQkJaW50IHNpemUgPSBzZXJ2ZXIuZ2V0U2VydmljZUNvdW50KCk7CgkJCWZvciAoaW50IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKSB7CgkJCQlTZXJ2aWNlIHNlcnZpY2UgPSBzZXJ2ZXIuZ2V0U2VydmljZShpKTsKCQkJCWlmIChzZXJ2aWNlLmdldE5hbWUoKS5lcXVhbHNJZ25vcmVDYXNlKERFRkFVTFRfU0VSVklDRSkpIHsKCQkJCQlFbmdpbmUgZW5naW5lID0gc2VydmljZS5nZXRFbmdpbmUoKTsKCQkJCQlIb3N0IGhvc3QgPSBlbmdpbmUuZ2V0SG9zdCgpOwoJCQkJCWludCBzaXplMiA9IGhvc3QuZ2V0Q29udGV4dENvdW50KCk7CgkJCQkJZm9yIChpbnQgaiA9IDA7IGogPCBzaXplMjsgaisrKSB7CgkJCQkJCUNvbnRleHQgY29udGV4dCA9IGhvc3QuZ2V0Q29udGV4dChqKTsKCQkJCQkJU3RyaW5nIHJlbG9hZCA9IGNvbnRleHQuZ2V0UmVsb2FkYWJsZSgpOwoJCQkJCQlpZiAocmVsb2FkID09IG51bGwpCgkJCQkJCQlyZWxvYWQgPSAiZmFsc2UiOwoJCQkJCQlXZWJNb2R1bGUgbW9kdWxlID0gbmV3IFdlYk1vZHVsZShjb250ZXh0LmdldFBhdGgoKSwgCgkJCQkJCQljb250ZXh0LmdldERvY0Jhc2UoKSwgY29udGV4dC5nZXRTb3VyY2UoKSwKCQkJCQkJCXJlbG9hZC5lcXVhbHNJZ25vcmVDYXNlKCJ0cnVlIikgPyB0cnVlIDogZmFsc2UpOwoJCQkJCQlsaXN0LmFkZChtb2R1bGUpOwoJCQkJCX0KCQkJCX0KCQkJfQoJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCVRyYWNlLnRyYWNlKFRyYWNlLlNFVkVSRSwgIkVycm9yIGdldHRpbmcgcHJvamVjdCByZWZzIiwgZSk7CgkJfQoJCXJldHVybiBsaXN0OwoJfQoJCgkvKioKCSAqIEBwYXJhbSBwYXRoIGEgcGF0aAoJICogQHBhcmFtIG1vbml0b3IgYSBwcm9ncmVzcyBtb25pdG9yCgkgKi8KCXB1YmxpYyB2b2lkIGxvYWQoSVBhdGggcGF0aCwgSVByb2dyZXNzTW9uaXRvciBtb25pdG9yKSB0aHJvd3MgQ29yZUV4Y2VwdGlvbiB7CgkJdHJ5IHsKCQkJbW9uaXRvciA9IFByb2dyZXNzVXRpbC5nZXRNb25pdG9yRm9yKG1vbml0b3IpOwoJCQltb25pdG9yLmJlZ2luVGFzayhUb21jYXRQbHVnaW4uZ2V0UmVzb3VyY2UoIiVsb2FkaW5nVGFzayIpLCA1KTsKCQkJCgkJCS8vIGNoZWNrIGZvciBjYXRhbGluYS5wb2xpY3kgdG8gdmVyaWZ5IHRoYXQgdGhpcyBpcyBhIHY1LjAgY29uZmlnCgkJCUlucHV0U3RyZWFtIGluID0gbmV3IEZpbGVJbnB1dFN0cmVhbShwYXRoLmFwcGVuZCgiY2F0YWxpbmEucG9saWN5IikudG9GaWxlKCkpOwoJCQlpbi5yZWFkKCk7CgkJCWluLmNsb3NlKCk7CgkJCW1vbml0b3Iud29ya2VkKDEpOwoKCQkJc2VydmVyRmFjdG9yeSA9IG5ldyBGYWN0b3J5KCk7CgkJCXNlcnZlckZhY3Rvcnkuc2V0UGFja2FnZU5hbWUoIm9yZy5lY2xpcHNlLmpzdC5zZXJ2ZXIudG9tY2F0LmNvcmUuaW50ZXJuYWwueG1sLnNlcnZlcjQwIik7CgkJCXNlcnZlciA9IChTZXJ2ZXIpIHNlcnZlckZhY3RvcnkubG9hZERvY3VtZW50KG5ldyBGaWxlSW5wdXRTdHJlYW0ocGF0aC5hcHBlbmQoInNlcnZlci54bWwiKS50b0ZpbGUoKSkpOwoJCQltb25pdG9yLndvcmtlZCgxKTsKCgkJCXdlYkFwcERvY3VtZW50ID0gbmV3IFdlYkFwcERvY3VtZW50KHBhdGguYXBwZW5kKCJ3ZWIueG1sIikpOwoJCQltb25pdG9yLndvcmtlZCgxKTsKCQkJCgkJCXRvbWNhdFVzZXJzRG9jdW1lbnQgPSBYTUxVdGlsLmdldERvY3VtZW50QnVpbGRlcigpLnBhcnNlKG5ldyBJbnB1dFNvdXJjZShuZXcgRmlsZUlucHV0U3RyZWFtKHBhdGguYXBwZW5kKCJ0b21jYXQtdXNlcnMueG1sIikudG9GaWxlKCkpKSk7CgkJCW1vbml0b3Iud29ya2VkKDEpOwoJCQkKCQkJLy8gbG9hZCBwb2xpY3kgZmlsZQoJCQlCdWZmZXJlZFJlYWRlciBiciA9IG51bGw7CgkJCXRyeSB7CgkJCQliciA9IG5ldyBCdWZmZXJlZFJlYWRlcihuZXcgSW5wdXRTdHJlYW1SZWFkZXIobmV3IEZpbGVJbnB1dFN0cmVhbShwYXRoLmFwcGVuZCgiY2F0YWxpbmEucG9saWN5IikudG9GaWxlKCkpKSk7CgkJCQlTdHJpbmcgdGVtcCA9IGJyLnJlYWRMaW5lKCk7CgkJCQlwb2xpY3lGaWxlID0gIiI7CgkJCQl3aGlsZSAodGVtcCAhPSBudWxsKSB7CgkJCQkJcG9saWN5RmlsZSArPSB0ZW1wICsgIlxuIjsKCQkJCQl0ZW1wID0gYnIucmVhZExpbmUoKTsKCQkJCX0KCQkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJCVRyYWNlLnRyYWNlKFRyYWNlLldBUk5JTkcsICJDb3VsZCBub3QgbG9hZCBwb2xpY3kgZmlsZSIsIGUpOwoJCQl9IGZpbmFsbHkgewoJCQkJaWYgKGJyICE9IG51bGwpCgkJCQkJYnIuY2xvc2UoKTsKCQkJfQoJCQltb25pdG9yLndvcmtlZCgxKTsKCQkJCgkJCWlmIChtb25pdG9yLmlzQ2FuY2VsZWQoKSkKCQkJCXJldHVybjsKCQkJbW9uaXRvci5kb25lKCk7CgkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJVHJhY2UudHJhY2UoVHJhY2UuV0FSTklORywgIkNvdWxkIG5vdCBsb2FkIFRvbWNhdCB2NS4wIGNvbmZpZ3VyYXRpb24gZnJvbSAiICsgcGF0aC50b09TU3RyaW5nKCkgKyAiOiAiICsgZS5nZXRNZXNzYWdlKCkpOwoJCQl0aHJvdyBuZXcgQ29yZUV4Y2VwdGlvbihuZXcgU3RhdHVzKElTdGF0dXMuRVJST1IsIFRvbWNhdFBsdWdpbi5QTFVHSU5fSUQsIDAsIFRvbWNhdFBsdWdpbi5nZXRSZXNvdXJjZSgiJWVycm9yQ291bGROb3RMb2FkQ29uZmlndXJhdGlvbiIsIHBhdGgudG9PU1N0cmluZygpKSwgZSkpOwoJCX0KCX0KCgkvKioKCSAqIFJlbG9hZCB0aGUgY29uZmlndXJhdGlvbi4KCSAqIAoJICogQHBhcmFtIGZvbGRlciBhIGZvbGRlcgoJICogQHBhcmFtIG1vbml0b3IgYSBwcm9ncmVzcyBtb25pdG9yCgkgKi8KCXB1YmxpYyB2b2lkIGxvYWQoSUZvbGRlciBmb2xkZXIsIElQcm9ncmVzc01vbml0b3IgbW9uaXRvcikgdGhyb3dzIENvcmVFeGNlcHRpb24gewoJCXRyeSB7CgkJCW1vbml0b3IgPSBQcm9ncmVzc1V0aWwuZ2V0TW9uaXRvckZvcihtb25pdG9yKTsKCQkJbW9uaXRvci5iZWdpblRhc2soVG9tY2F0UGx1Z2luLmdldFJlc291cmNlKCIlbG9hZGluZ1Rhc2siKSwgODAwKTsKCQoJCQkvLyBjaGVjayBmb3IgY2F0YWxpbmEucG9saWN5IHRvIHZlcmlmeSB0aGF0IHRoaXMgaXMgYSB2NC4wIGNvbmZpZwoJCQlJRmlsZSBmaWxlID0gZm9sZGVyLmdldEZpbGUoImNhdGFsaW5hLnBvbGljeSIpOwoJCQlpZiAoIWZpbGUuZXhpc3RzKCkpCgkJCQl0aHJvdyBuZXcgQ29yZUV4Y2VwdGlvbihuZXcgU3RhdHVzKElTdGF0dXMuV0FSTklORywgVG9tY2F0UGx1Z2luLlBMVUdJTl9JRCwgMCwgVG9tY2F0UGx1Z2luLmdldFJlc291cmNlKCIlZXJyb3JDb3VsZE5vdExvYWRDb25maWd1cmF0aW9uIiwgZm9sZGVyLmdldEZ1bGxQYXRoKCkudG9PU1N0cmluZygpKSwgbnVsbCkpOwoJCgkJCS8vIGxvYWQgc2VydmVyLnhtbAoJCQlmaWxlID0gZm9sZGVyLmdldEZpbGUoInNlcnZlci54bWwiKTsKCQkJSW5wdXRTdHJlYW0gaW4gPSBmaWxlLmdldENvbnRlbnRzKCk7CgkJCXNlcnZlckZhY3RvcnkgPSBuZXcgRmFjdG9yeSgpOwoJCQlzZXJ2ZXJGYWN0b3J5LnNldFBhY2thZ2VOYW1lKCJvcmcuZWNsaXBzZS5qc3Quc2VydmVyLnRvbWNhdC5jb3JlLmludGVybmFsLnhtbC5zZXJ2ZXI0MCIpOwoJCQlzZXJ2ZXIgPSAoU2VydmVyKSBzZXJ2ZXJGYWN0b3J5LmxvYWREb2N1bWVudChpbik7CgkJCW1vbml0b3Iud29ya2VkKDIwMCk7CgkKCQkJLy8gbG9hZCB3ZWIueG1sCgkJCWZpbGUgPSBmb2xkZXIuZ2V0RmlsZSgid2ViLnhtbCIpOwoJCQl3ZWJBcHBEb2N1bWVudCA9IG5ldyBXZWJBcHBEb2N1bWVudChmaWxlKTsKCQkJbW9uaXRvci53b3JrZWQoMjAwKTsKCQoJCQkvLyBsb2FkIHRvbWNhdC11c2Vycy54bWwKCQkJZmlsZSA9IGZvbGRlci5nZXRGaWxlKCJ0b21jYXQtdXNlcnMueG1sIik7CgkJCWluID0gZmlsZS5nZXRDb250ZW50cygpOwoJCQkKCQkJdG9tY2F0VXNlcnNEb2N1bWVudCA9IFhNTFV0aWwuZ2V0RG9jdW1lbnRCdWlsZGVyKCkucGFyc2UobmV3IElucHV0U291cmNlKGluKSk7CgkJCW1vbml0b3Iud29ya2VkKDIwMCk7CgkJCgkJCS8vIGxvYWQgY2F0YWxpbmEucG9saWN5CgkJCWZpbGUgPSBmb2xkZXIuZ2V0RmlsZSgiY2F0YWxpbmEucG9saWN5Iik7CgkJCWluID0gZmlsZS5nZXRDb250ZW50cygpOwoJCQlCdWZmZXJlZFJlYWRlciBiciA9IG51bGw7CgkJCXRyeSB7CgkJCQliciA9IG5ldyBCdWZmZXJlZFJlYWRlcihuZXcgSW5wdXRTdHJlYW1SZWFkZXIoaW4pKTsKCQkJCVN0cmluZyB0ZW1wID0gYnIucmVhZExpbmUoKTsKCQkJCXBvbGljeUZpbGUgPSAiIjsKCQkJCXdoaWxlICh0ZW1wICE9IG51bGwpIHsKCQkJCQlwb2xpY3lGaWxlICs9IHRlbXAgKyAiXG4iOwoJCQkJCXRlbXAgPSBici5yZWFkTGluZSgpOwoJCQkJfQoJCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkJVHJhY2UudHJhY2UoVHJhY2UuV0FSTklORywgIkNvdWxkIG5vdCBsb2FkIHBvbGljeSBmaWxlIiwgZSk7CgkJCX0gZmluYWxseSB7CgkJCQlpZiAoYnIgIT0gbnVsbCkKCQkJCQlici5jbG9zZSgpOwoJCQl9CgkJCW1vbml0b3Iud29ya2VkKDIwMCk7CgkKCQkJaWYgKG1vbml0b3IuaXNDYW5jZWxlZCgpKQoJCQkJdGhyb3cgbmV3IEV4Y2VwdGlvbigiQ2FuY2VsbGVkIik7CgkJCW1vbml0b3IuZG9uZSgpOwoJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCVRyYWNlLnRyYWNlKFRyYWNlLldBUk5JTkcsICJDb3VsZCBub3QgcmVsb2FkIFRvbWNhdCB2NS4wIGNvbmZpZ3VyYXRpb24gZnJvbTogIiArIGZvbGRlci5nZXRGdWxsUGF0aCgpICsgIjogIiArIGUuZ2V0TWVzc2FnZSgpKTsKCQkJdGhyb3cgbmV3IENvcmVFeGNlcHRpb24obmV3IFN0YXR1cyhJU3RhdHVzLkVSUk9SLCBUb21jYXRQbHVnaW4uUExVR0lOX0lELCAwLCBUb21jYXRQbHVnaW4uZ2V0UmVzb3VyY2UoIiVlcnJvckNvdWxkTm90TG9hZENvbmZpZ3VyYXRpb24iLCBmb2xkZXIuZ2V0RnVsbFBhdGgoKS50b09TU3RyaW5nKCkpLCBlKSk7CgkJfQoJfQoKCS8qKgoJICogU2F2ZSB0byB0aGUgZ2l2ZW4gZGlyZWN0b3J5LgoJICogQHBhcmFtIHBhdGggYSBwYXRoCgkgKiBAcGFyYW0gZm9yY2VEaXJ0eSBib29sZWFuCgkgKiBAcGFyYW0gbW9uaXRvciBhIHByb2dyZXNzIG1vbml0b3IKCSAqIEBleGNlcHRpb24gQ29yZUV4Y2VwdGlvbgoJICovCglwcm90ZWN0ZWQgdm9pZCBzYXZlKElQYXRoIHBhdGgsIGJvb2xlYW4gZm9yY2VEaXJ0eSwgSVByb2dyZXNzTW9uaXRvciBtb25pdG9yKSB0aHJvd3MgQ29yZUV4Y2VwdGlvbiB7CgkJdHJ5IHsKCQkJbW9uaXRvciA9IFByb2dyZXNzVXRpbC5nZXRNb25pdG9yRm9yKG1vbml0b3IpOwoJCQltb25pdG9yLmJlZ2luVGFzayhUb21jYXRQbHVnaW4uZ2V0UmVzb3VyY2UoIiVzYXZpbmdUYXNrIiksIDMpOwoJCgkJCS8vIG1ha2Ugc3VyZSBkaXJlY3RvcnkgZXhpc3RzCgkJCWlmICghcGF0aC50b0ZpbGUoKS5leGlzdHMoKSkgewoJCQkJZm9yY2VEaXJ0eSA9IHRydWU7CgkJCQlwYXRoLnRvRmlsZSgpLm1rZGlyKCk7CgkJCX0KCQkJbW9uaXRvci53b3JrZWQoMSk7CgkKCQkJLy8gc2F2ZSBmaWxlcwoJCQlpZiAoZm9yY2VEaXJ0eSB8fCBpc1NlcnZlckRpcnR5KQoJCQkJc2VydmVyRmFjdG9yeS5zYXZlKHBhdGguYXBwZW5kKCJzZXJ2ZXIueG1sIikudG9PU1N0cmluZygpKTsKCQkJbW9uaXRvci53b3JrZWQoMSk7CgkKCQkJLy9pZiAoZm9yY2VEaXJ0eSB8fCBpc1dlYkFwcERpcnR5KQoJCQkvLwl3ZWJBcHBGYWN0b3J5LnNhdmUoZGlyUGF0aCArICJ3ZWIueG1sIik7CgkJCS8vd2ViQXBwRG9jdW1lbnQuc2F2ZShwYXRoLnRvT1NTdHJpbmcoKSwgZm9yY2VEaXJ0eSB8fCBpc1BvbGljeURpcnR5KTsKCQkJd2ViQXBwRG9jdW1lbnQuc2F2ZShwYXRoLmFwcGVuZCgid2ViLnhtbCIpLnRvT1NTdHJpbmcoKSwgZm9yY2VEaXJ0eSk7CgkJCW1vbml0b3Iud29ya2VkKDEpOwoJCgkJCWlmIChmb3JjZURpcnR5KQoJCQkJWE1MVXRpbC5zYXZlKHBhdGguYXBwZW5kKCJ0b21jYXQtdXNlcnMueG1sIikudG9PU1N0cmluZygpLCB0b21jYXRVc2Vyc0RvY3VtZW50KTsKCQkJbW9uaXRvci53b3JrZWQoMSk7CgkKCQkJaWYgKGZvcmNlRGlydHkgfHwgaXNQb2xpY3lEaXJ0eSkgewoJCQkJQnVmZmVyZWRXcml0ZXIgYncgPSBuZXcgQnVmZmVyZWRXcml0ZXIobmV3IEZpbGVXcml0ZXIocGF0aC5hcHBlbmQoImNhdGFsaW5hLnBvbGljeSIpLnRvRmlsZSgpKSk7CgkJCQlidy53cml0ZShwb2xpY3lGaWxlKTsKCQkJCWJ3LmNsb3NlKCk7CgkJCX0KCQkJbW9uaXRvci53b3JrZWQoMSk7CgkJCWlzU2VydmVyRGlydHkgPSBmYWxzZTsKCQkJaXNQb2xpY3lEaXJ0eSA9IGZhbHNlOwoJCgkJCWlmIChtb25pdG9yLmlzQ2FuY2VsZWQoKSkKCQkJCXJldHVybjsKCQkJbW9uaXRvci5kb25lKCk7CgkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiQ291bGQgbm90IHNhdmUgVG9tY2F0IHY1LjAgY29uZmlndXJhdGlvbiB0byAiICsgcGF0aCwgZSk7CgkJCXRocm93IG5ldyBDb3JlRXhjZXB0aW9uKG5ldyBTdGF0dXMoSVN0YXR1cy5FUlJPUiwgVG9tY2F0UGx1Z2luLlBMVUdJTl9JRCwgMCwgVG9tY2F0UGx1Z2luLmdldFJlc291cmNlKCIlZXJyb3JDb3VsZE5vdFNhdmVDb25maWd1cmF0aW9uIiwgbmV3IFN0cmluZ1tdIHtlLmdldExvY2FsaXplZE1lc3NhZ2UoKX0pLCBlKSk7CgkJfQoJfQoJCglwdWJsaWMgdm9pZCBzYXZlKElQYXRoIHBhdGgsIElQcm9ncmVzc01vbml0b3IgbW9uaXRvcikgdGhyb3dzIENvcmVFeGNlcHRpb24gewoJCXNhdmUocGF0aCwgdHJ1ZSwgbW9uaXRvcik7Cgl9CgoJLyoqCgkgKiBTYXZlIHRoZSBpbmZvcm1hdGlvbiBoZWxkIGJ5IHRoaXMgb2JqZWN0IHRvIHRoZSBnaXZlbiBkaXJlY3RvcnkuCgkgKgoJICogQHBhcmFtIGZvbGRlciBhIGZvbGRlcgoJICogQHBhcmFtIG1vbml0b3IgYSBwcm9ncmVzcyBtb25pdG9yCgkgKiBAdGhyb3dzIENvcmVFeGNlcHRpb24KCSAqLwoJcHVibGljIHZvaWQgc2F2ZShJRm9sZGVyIGZvbGRlciwgSVByb2dyZXNzTW9uaXRvciBtb25pdG9yKSB0aHJvd3MgQ29yZUV4Y2VwdGlvbiB7CgkJdHJ5IHsKCQkJbW9uaXRvciA9IFByb2dyZXNzVXRpbC5nZXRNb25pdG9yRm9yKG1vbml0b3IpOwoJCQltb25pdG9yLmJlZ2luVGFzayhUb21jYXRQbHVnaW4uZ2V0UmVzb3VyY2UoIiVzYXZpbmdUYXNrIiksIDkwMCk7CgkKCQkJLy8gc2F2ZSBzZXJ2ZXIueG1sCgkJCWJ5dGVbXSBkYXRhID0gc2VydmVyRmFjdG9yeS5nZXRDb250ZW50cygpOwoJCQlJbnB1dFN0cmVhbSBpbiA9IG5ldyBCeXRlQXJyYXlJbnB1dFN0cmVhbShkYXRhKTsKCQkJSUZpbGUgZmlsZSA9IGZvbGRlci5nZXRGaWxlKCJzZXJ2ZXIueG1sIik7CgkJCWlmIChmaWxlLmV4aXN0cygpKSB7CgkJCQlpZiAoaXNTZXJ2ZXJEaXJ0eSkKCQkJCQlmaWxlLnNldENvbnRlbnRzKGluLCB0cnVlLCB0cnVlLCBQcm9ncmVzc1V0aWwuZ2V0U3ViTW9uaXRvckZvcihtb25pdG9yLCAyMDApKTsKCQkJCWVsc2UKCQkJCQltb25pdG9yLndvcmtlZCgyMDApOwoJCQl9IGVsc2UKCQkJCWZpbGUuY3JlYXRlKGluLCB0cnVlLCBQcm9ncmVzc1V0aWwuZ2V0U3ViTW9uaXRvckZvcihtb25pdG9yLCAyMDApKTsKCQoJCQkvLyBzYXZlIHdlYi54bWwKCQkJd2ViQXBwRG9jdW1lbnQuc2F2ZShmb2xkZXIuZ2V0RmlsZSgid2ViLnhtbCIpLCBQcm9ncmVzc1V0aWwuZ2V0U3ViTW9uaXRvckZvcihtb25pdG9yLCAyMDApKTsKCQoJCQkvLyBzYXZlIHRvbWNhdC11c2Vycy54bWwKCQkJZGF0YSA9IFhNTFV0aWwuZ2V0Q29udGVudHModG9tY2F0VXNlcnNEb2N1bWVudCk7CgkJCWluID0gbmV3IEJ5dGVBcnJheUlucHV0U3RyZWFtKGRhdGEpOwoJCQlmaWxlID0gZm9sZGVyLmdldEZpbGUoInRvbWNhdC11c2Vycy54bWwiKTsKCQkJaWYgKGZpbGUuZXhpc3RzKCkpCgkJCQltb25pdG9yLndvcmtlZCgyMDApOwoJCQkJLy9maWxlLnNldENvbnRlbnRzKGluLCB0cnVlLCB0cnVlLCBQcm9ncmVzc1V0aWwuZ2V0U3ViTW9uaXRvckZvcihtb25pdG9yLCAyMDApKTsKCQkJZWxzZQoJCQkJZmlsZS5jcmVhdGUoaW4sIHRydWUsIFByb2dyZXNzVXRpbC5nZXRTdWJNb25pdG9yRm9yKG1vbml0b3IsIDIwMCkpOwoJCgkJCS8vIHNhdmUgY2F0YWxpbmEucG9saWN5CgkJCWluID0gbmV3IEJ5dGVBcnJheUlucHV0U3RyZWFtKHBvbGljeUZpbGUuZ2V0Qnl0ZXMoKSk7CgkJCWZpbGUgPSBmb2xkZXIuZ2V0RmlsZSgiY2F0YWxpbmEucG9saWN5Iik7CgkJCWlmIChmaWxlLmV4aXN0cygpKQoJCQkJbW9uaXRvci53b3JrZWQoMjAwKTsKCQkJCS8vZmlsZS5zZXRDb250ZW50cyhpbiwgdHJ1ZSwgdHJ1ZSwgUHJvZ3Jlc3NVdGlsLmdldFN1Yk1vbml0b3JGb3IobW9uaXRvciwgMjAwKSk7CgkJCWVsc2UKCQkJCWZpbGUuY3JlYXRlKGluLCB0cnVlLCBQcm9ncmVzc1V0aWwuZ2V0U3ViTW9uaXRvckZvcihtb25pdG9yLCAyMDApKTsKCQoJCQlpZiAobW9uaXRvci5pc0NhbmNlbGVkKCkpCgkJCQlyZXR1cm47CgkJCW1vbml0b3IuZG9uZSgpOwoJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCVRyYWNlLnRyYWNlKFRyYWNlLlNFVkVSRSwgIkNvdWxkIG5vdCBzYXZlIFRvbWNhdCB2NS4wIGNvbmZpZ3VyYXRpb24gdG8gIiArIGZvbGRlci50b1N0cmluZygpLCBlKTsKCQkJdGhyb3cgbmV3IENvcmVFeGNlcHRpb24obmV3IFN0YXR1cyhJU3RhdHVzLkVSUk9SLCBUb21jYXRQbHVnaW4uUExVR0lOX0lELCAwLCBUb21jYXRQbHVnaW4uZ2V0UmVzb3VyY2UoIiVlcnJvckNvdWxkTm90U2F2ZUNvbmZpZ3VyYXRpb24iLCBuZXcgU3RyaW5nW10ge2UuZ2V0TG9jYWxpemVkTWVzc2FnZSgpfSksIGUpKTsKCQl9Cgl9CgoJcHJvdGVjdGVkIHN0YXRpYyBib29sZWFuIGhhc01EQkxpc3RlbmVyKFNlcnZlciBzZXJ2ZXIpIHsKCQlpZiAoc2VydmVyID09IG51bGwpCgkJCXJldHVybiBmYWxzZTsKCQkKCQlpbnQgY291bnQgPSBzZXJ2ZXIuZ2V0TGlzdGVuZXJDb3VudCgpOwoJCWlmIChjb3VudCA9PSAwKQoJCQlyZXR1cm4gZmFsc2U7CgkJCQoJCWZvciAoaW50IGkgPSAwOyBpIDwgY291bnQ7IGkrKykgewoJCQlMaXN0ZW5lciBsaXN0ZW5lciA9IHNlcnZlci5nZXRMaXN0ZW5lcihpKTsKCQkJaWYgKGxpc3RlbmVyICE9IG51bGwgJiYgbGlzdGVuZXIuZ2V0Q2xhc3NOYW1lKCkgIT0gbnVsbCAmJiBsaXN0ZW5lci5nZXRDbGFzc05hbWUoKS5pbmRleE9mKCJtYmVhbiIpID49IDApCgkJCQlyZXR1cm4gdHJ1ZTsKCQl9CgkJcmV0dXJuIGZhbHNlOwoJfQoJCgkvKioKCSAqIEFkZHMgYSBtaW1lIG1hcHBpbmcuCgkgKiAKCSAqIEBwYXJhbSBpbmRleAoJICogQHBhcmFtIG1hcAoJICovCglwdWJsaWMgdm9pZCBhZGRNaW1lTWFwcGluZyhpbnQgaW5kZXgsIElNaW1lTWFwcGluZyBtYXApIHsKCQl3ZWJBcHBEb2N1bWVudC5hZGRNaW1lTWFwcGluZyhpbmRleCwgbWFwKTsKCQlmaXJlUHJvcGVydHlDaGFuZ2VFdmVudChBRERfTUFQUElOR19QUk9QRVJUWSwgbmV3IEludGVnZXIoaW5kZXgpLCBtYXApOwoJfQoKCS8qKgoJICogQWRkIGEgd2ViIG1vZHVsZS4KCSAqIEBwYXJhbSBtb2R1bGUgb3JnLmVjbGlwc2UuanN0LnNlcnZlci50b21jYXQuV2ViTW9kdWxlCgkgKi8KCXB1YmxpYyB2b2lkIGFkZFdlYk1vZHVsZShpbnQgaW5kZXgsIElUb21jYXRXZWJNb2R1bGUgbW9kdWxlKSB7CgkJdHJ5IHsKCQkJaW50IHNpemUgPSBzZXJ2ZXIuZ2V0U2VydmljZUNvdW50KCk7CgkJCWZvciAoaW50IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKSB7CgkJCQlTZXJ2aWNlIHNlcnZpY2UgPSBzZXJ2ZXIuZ2V0U2VydmljZShpKTsKCQkJCWlmIChzZXJ2aWNlLmdldE5hbWUoKS5lcXVhbHNJZ25vcmVDYXNlKERFRkFVTFRfU0VSVklDRSkpIHsKCQkJCQlFbmdpbmUgZW5naW5lID0gc2VydmljZS5nZXRFbmdpbmUoKTsKCQkJCQlIb3N0IGhvc3QgPSBlbmdpbmUuZ2V0SG9zdCgpOwoJCQkJCUNvbnRleHQgY29udGV4dCA9IChDb250ZXh0KSBob3N0LmNyZWF0ZUVsZW1lbnQoaW5kZXgsICJDb250ZXh0Iik7CgkJCQkJY29udGV4dC5zZXREb2NCYXNlKG1vZHVsZS5nZXREb2N1bWVudEJhc2UoKSk7CgkJCQkJY29udGV4dC5zZXRQYXRoKG1vZHVsZS5nZXRQYXRoKCkpOwoJCQkJCWNvbnRleHQuc2V0UmVsb2FkYWJsZShtb2R1bGUuaXNSZWxvYWRhYmxlKCkgPyAidHJ1ZSIgOiAiZmFsc2UiKTsKCQkJCQlpZiAobW9kdWxlLmdldE1lbWVudG8oKSAhPSBudWxsICYmIG1vZHVsZS5nZXRNZW1lbnRvKCkubGVuZ3RoKCkgPiAwKQoJCQkJCQljb250ZXh0LnNldFNvdXJjZShtb2R1bGUuZ2V0TWVtZW50bygpKTsKCQkJCQlpc1NlcnZlckRpcnR5ID0gdHJ1ZTsKCQkJCQlmaXJlUHJvcGVydHlDaGFuZ2VFdmVudChBRERfV0VCX01PRFVMRV9QUk9QRVJUWSwgbnVsbCwgbW9kdWxlKTsKCQkJCQlyZXR1cm47CgkJCQl9CgkJCX0KCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQlUcmFjZS50cmFjZShUcmFjZS5TRVZFUkUsICJFcnJvciBhZGRpbmcgd2ViIG1vZHVsZSAiICsgbW9kdWxlLmdldFBhdGgoKSwgZSk7CgkJfQoJfQoKCS8qKgoJICogTG9jYWxpemUgdGhlIHdlYiBwcm9qZWN0cyBpbiB0aGlzIGNvbmZpZ3VyYXRpb24uCgkgKgoJICogQHBhcmFtIHBhdGggYSBwYXRoCgkgKiBAcGFyYW0gbW9uaXRvciBhIHByb2dyZXNzIG1vbml0b3IKCSAqLwoJcHVibGljIHZvaWQgbG9jYWxpemVDb25maWd1cmF0aW9uKElQYXRoIHBhdGgsIFRvbWNhdFNlcnZlciBzZXJ2ZXIyLCBUb21jYXRSdW50aW1lIHJ1bnRpbWUsIElQcm9ncmVzc01vbml0b3IgbW9uaXRvcikgewoJCXRyeSB7CgkJCW1vbml0b3IgPSBQcm9ncmVzc1V0aWwuZ2V0TW9uaXRvckZvcihtb25pdG9yKTsKCQkJbW9uaXRvci5iZWdpblRhc2soVG9tY2F0UGx1Z2luLmdldFJlc291cmNlKCIldXBkYXRpbmdDb25maWd1cmF0aW9uVGFzayIpLCAxMDApOwoJCQkKCQkJVG9tY2F0NTBDb25maWd1cmF0aW9uIGNvbmZpZyA9IG5ldyBUb21jYXQ1MENvbmZpZ3VyYXRpb24obnVsbCk7CgkJCWNvbmZpZy5sb2FkKHBhdGgsIFByb2dyZXNzVXRpbC5nZXRTdWJNb25pdG9yRm9yKG1vbml0b3IsIDQwKSk7CgkKCQkJaWYgKG1vbml0b3IuaXNDYW5jZWxlZCgpKQoJCQkJcmV0dXJuOwoJCgkJCWlmICghc2VydmVyMi5pc1Rlc3RFbnZpcm9ubWVudCgpKSB7CgkJCQkvL0lTZXJ2ZXJDb25maWd1cmF0aW9uV29ya2luZ0NvcHkgc2N3YyA9IGNvbmZpZy5nZXRTZXJ2ZXJDb25maWd1cmF0aW9uKCkuY3JlYXRlV29ya2luZ0NvcHkoKTsKCQkJCS8vVG9tY2F0NTBDb25maWd1cmF0aW9uIGNmZyA9IChUb21jYXQ1MENvbmZpZ3VyYXRpb24pIHNjd2MuZ2V0QWRhcHRlcihUb21jYXQ1MENvbmZpZ3VyYXRpb24uY2xhc3MpOwoJCQkJY29uZmlnLmxvY2FsaXplV2ViTW9kdWxlcygpOwoJCQl9CgkJCW1vbml0b3Iud29ya2VkKDIwKTsKCQoJCQlpZiAobW9uaXRvci5pc0NhbmNlbGVkKCkpCgkJCQlyZXR1cm47CgkKCQkJY29uZmlnLnNhdmUocGF0aCwgZmFsc2UsIFByb2dyZXNzVXRpbC5nZXRTdWJNb25pdG9yRm9yKG1vbml0b3IsIDQwKSk7CgkKCQkJaWYgKCFtb25pdG9yLmlzQ2FuY2VsZWQoKSkKCQkJCW1vbml0b3IuZG9uZSgpOwoJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCVRyYWNlLnRyYWNlKFRyYWNlLlNFVkVSRSwgIkVycm9yIGxvY2FsaXppbmcgY29uZmlndXJhdGlvbiIsIGUpOwoJCX0KCX0KCQoJLyoqCgkgKiBHbyB0aHJvdWdoIGFsbCBvZiB0aGUgd2ViIG1vZHVsZXMgYW5kIG1ha2UgdGhlIGRvY3VtZW50CgkgKiBiYXNlICJsb2NhbCIgdG8gdGhlIGNvbmZpZ3VyYXRpb24uCgkgKi8KCXByb3RlY3RlZCB2b2lkIGxvY2FsaXplV2ViTW9kdWxlcygpIHsKCQlMaXN0IG1vZHVsZXMgPSBnZXRXZWJNb2R1bGVzKCk7CgoJCWludCBzaXplID0gbW9kdWxlcy5zaXplKCk7CgkJZm9yIChpbnQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHsKCQkJV2ViTW9kdWxlIG1vZHVsZSA9IChXZWJNb2R1bGUpIG1vZHVsZXMuZ2V0KGkpOwoJCQlTdHJpbmcgbWVtZW50byA9IG1vZHVsZS5nZXRNZW1lbnRvKCk7CgkJCWlmIChtZW1lbnRvICE9IG51bGwgJiYgbWVtZW50by5sZW5ndGgoKSA+IDApIHsKCQkJCS8vIHVwZGF0ZSBkb2N1bWVudCBiYXNlIHRvIGEgcmVsYXRpdmUgcmVmCgkJCQlTdHJpbmcgZG9jQmFzZSA9IGdldFBhdGhQcmVmaXgoKSArIG1vZHVsZS5nZXRQYXRoKCk7CgkJCQlpZiAoZG9jQmFzZS5zdGFydHNXaXRoKCIvIikgfHwgZG9jQmFzZS5zdGFydHNXaXRoKCJcXCIpKQoJCQkJCWRvY0Jhc2UgPSBkb2NCYXNlLnN1YnN0cmluZygxKTsKCQkJCW1vZGlmeVdlYk1vZHVsZShpLCBkb2NCYXNlLCBtb2R1bGUuZ2V0UGF0aCgpLCBtb2R1bGUuaXNSZWxvYWRhYmxlKCkpOwoJCQl9CgkJfQoJfQoKCS8qKgoJICogQ2hhbmdlIHRoZSBleHRlbnNpb24gb2YgYSBtaW1lIG1hcHBpbmcuCgkgKiAKCSAqIEBwYXJhbSBpbmRleAoJICogQHBhcmFtIG1hcAoJICovCglwdWJsaWMgdm9pZCBtb2RpZnlNaW1lTWFwcGluZyhpbnQgaW5kZXgsIElNaW1lTWFwcGluZyBtYXApIHsKCQl3ZWJBcHBEb2N1bWVudC5tb2RpZnlNaW1lTWFwcGluZyhpbmRleCwgbWFwKTsKCQlmaXJlUHJvcGVydHlDaGFuZ2VFdmVudChNT0RJRllfTUFQUElOR19QUk9QRVJUWSwgbmV3IEludGVnZXIoaW5kZXgpLCBtYXApOwoJfQoJCgkvKioKCSAqIE1vZGlmeSB0aGUgcG9ydCB3aXRoIHRoZSBnaXZlbiBpZC4KCSAqCgkgKiBAcGFyYW0gaWQgamF2YS5sYW5nLlN0cmluZwoJICogQHBhcmFtIHBvcnQgaW50CgkgKi8KCXB1YmxpYyB2b2lkIG1vZGlmeVNlcnZlclBvcnQoU3RyaW5nIGlkLCBpbnQgcG9ydCkgewoJCXRyeSB7CgkJCWlmICgic2VydmVyIi5lcXVhbHMoaWQpKSB7CgkJCQlzZXJ2ZXIuc2V0UG9ydChwb3J0ICsgIiIpOwoJCQkJaXNTZXJ2ZXJEaXJ0eSA9IHRydWU7CgkJCQlmaXJlUHJvcGVydHlDaGFuZ2VFdmVudChNT0RJRllfUE9SVF9QUk9QRVJUWSwgaWQsIG5ldyBJbnRlZ2VyKHBvcnQpKTsKCQkJCXJldHVybjsKCQkJfQoJCgkJCWludCBpID0gaWQuaW5kZXhPZigiLyIpOwoJCQlpbnQgc2Vydk51bSA9IEludGVnZXIucGFyc2VJbnQoaWQuc3Vic3RyaW5nKDAsIGkpKTsKCQkJaW50IGNvbm5OdW0gPSBJbnRlZ2VyLnBhcnNlSW50KGlkLnN1YnN0cmluZyhpICsgMSkpOwoJCQkKCQkJU2VydmljZSBzZXJ2aWNlID0gc2VydmVyLmdldFNlcnZpY2Uoc2Vydk51bSk7CgkJCUNvbm5lY3RvciBjb25uZWN0b3IgPSBzZXJ2aWNlLmdldENvbm5lY3Rvcihjb25uTnVtKTsKCQkJY29ubmVjdG9yLnNldFBvcnQocG9ydCArICIiKTsKCQkJaXNTZXJ2ZXJEaXJ0eSA9IHRydWU7CgkJCWZpcmVQcm9wZXJ0eUNoYW5nZUV2ZW50KE1PRElGWV9QT1JUX1BST1BFUlRZLCBpZCwgbmV3IEludGVnZXIocG9ydCkpOwoJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCVRyYWNlLnRyYWNlKFRyYWNlLlNFVkVSRSwgIkVycm9yIG1vZGlmeWluZyBzZXJ2ZXIgcG9ydCAiICsgaWQsIGUpOwoJCX0KCX0KCS8qKgoJICogQ2hhbmdlIGEgd2ViIG1vZHVsZS4KCSAqIEBwYXJhbSBpbmRleCBpbnQKCSAqIEBwYXJhbSBkb2NCYXNlIGphdmEubGFuZy5TdHJpbmcKCSAqIEBwYXJhbSBwYXRoIGphdmEubGFuZy5TdHJpbmcKCSAqIEBwYXJhbSByZWxvYWRhYmxlIGJvb2xlYW4KCSAqLwoJcHVibGljIHZvaWQgbW9kaWZ5V2ViTW9kdWxlKGludCBpbmRleCwgU3RyaW5nIGRvY0Jhc2UsIFN0cmluZyBwYXRoLCBib29sZWFuIHJlbG9hZGFibGUpIHsKCQl0cnkgewoJCQlpbnQgc2l6ZSA9IHNlcnZlci5nZXRTZXJ2aWNlQ291bnQoKTsKCQkJZm9yIChpbnQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHsKCQkJCVNlcnZpY2Ugc2VydmljZSA9IHNlcnZlci5nZXRTZXJ2aWNlKGkpOwoJCQkJaWYgKHNlcnZpY2UuZ2V0TmFtZSgpLmVxdWFsc0lnbm9yZUNhc2UoREVGQVVMVF9TRVJWSUNFKSkgewoJCQkJCUVuZ2luZSBlbmdpbmUgPSBzZXJ2aWNlLmdldEVuZ2luZSgpOwoJCQkJCUhvc3QgaG9zdCA9IGVuZ2luZS5nZXRIb3N0KCk7CgkJCQkJQ29udGV4dCBjb250ZXh0ID0gaG9zdC5nZXRDb250ZXh0KGluZGV4KTsKCQkJCQljb250ZXh0LnNldFBhdGgocGF0aCk7CgkJCQkJY29udGV4dC5zZXREb2NCYXNlKGRvY0Jhc2UpOwoJCQkJCWNvbnRleHQuc2V0UmVsb2FkYWJsZShyZWxvYWRhYmxlID8gInRydWUiIDogImZhbHNlIik7CgkJCQkJaXNTZXJ2ZXJEaXJ0eSA9IHRydWU7CgkJCQkJV2ViTW9kdWxlIG1vZHVsZSA9IG5ldyBXZWJNb2R1bGUocGF0aCwgZG9jQmFzZSwgbnVsbCwgcmVsb2FkYWJsZSk7CgkJCQkJZmlyZVByb3BlcnR5Q2hhbmdlRXZlbnQoTU9ESUZZX1dFQl9NT0RVTEVfUFJPUEVSVFksIG5ldyBJbnRlZ2VyKGluZGV4KSwgbW9kdWxlKTsKCQkJCQlyZXR1cm47CgkJCQl9CgkJCX0KCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQlUcmFjZS50cmFjZShUcmFjZS5TRVZFUkUsICJFcnJvciBtb2RpZnlpbmcgd2ViIG1vZHVsZSAiICsgaW5kZXgsIGUpOwoJCX0KCX0KCgkvKioKCSAqIFJlbW92ZXMgYSBtaW1lIG1hcHBpbmcuCgkgKiBAcGFyYW0gaW5kZXggaW50CgkgKi8KCXB1YmxpYyB2b2lkIHJlbW92ZU1pbWVNYXBwaW5nKGludCBpbmRleCkgewoJCXdlYkFwcERvY3VtZW50LnJlbW92ZU1pbWVNYXBwaW5nKGluZGV4KTsKCQlmaXJlUHJvcGVydHlDaGFuZ2VFdmVudChSRU1PVkVfTUFQUElOR19QUk9QRVJUWSwgbnVsbCwgbmV3IEludGVnZXIoaW5kZXgpKTsKCX0KCgkvKioKCSAqIFJlbW92ZXMgYSB3ZWIgbW9kdWxlLgoJICogQHBhcmFtIGluZGV4IGludAoJICovCglwdWJsaWMgdm9pZCByZW1vdmVXZWJNb2R1bGUoaW50IGluZGV4KSB7CgkJdHJ5IHsKCQkJaW50IHNpemUgPSBzZXJ2ZXIuZ2V0U2VydmljZUNvdW50KCk7CgkJCWZvciAoaW50IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKSB7CgkJCQlTZXJ2aWNlIHNlcnZpY2UgPSBzZXJ2ZXIuZ2V0U2VydmljZShpKTsKCQkJCWlmIChzZXJ2aWNlLmdldE5hbWUoKS5lcXVhbHNJZ25vcmVDYXNlKERFRkFVTFRfU0VSVklDRSkpIHsKCQkJCQlFbmdpbmUgZW5naW5lID0gc2VydmljZS5nZXRFbmdpbmUoKTsKCQkJCQlIb3N0IGhvc3QgPSBlbmdpbmUuZ2V0SG9zdCgpOwoJCQkJCWhvc3QucmVtb3ZlRWxlbWVudCgiQ29udGV4dCIsIGluZGV4KTsKCQkJCQlpc1NlcnZlckRpcnR5ID0gdHJ1ZTsKCQkJCQlmaXJlUHJvcGVydHlDaGFuZ2VFdmVudChSRU1PVkVfV0VCX01PRFVMRV9QUk9QRVJUWSwgbnVsbCwgbmV3IEludGVnZXIoaW5kZXgpKTsKCQkJCQlyZXR1cm47CgkJCQl9CgkJCX0KCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQlUcmFjZS50cmFjZShUcmFjZS5TRVZFUkUsICJFcnJvciByZW1vdmluZyBtb2R1bGUgcmVmICIgKyBpbmRleCwgZSk7CgkJfQoJfQoKCXByb3RlY3RlZCBJU3RhdHVzIGJhY2t1cEFuZFB1Ymxpc2goSVBhdGggY29uZkRpciwgYm9vbGVhbiBkb0JhY2t1cCwgSVByb2dyZXNzTW9uaXRvciBtb25pdG9yKSB7CgkJTXVsdGlTdGF0dXMgbXMgPSBuZXcgTXVsdGlTdGF0dXMoVG9tY2F0UGx1Z2luLlBMVUdJTl9JRCwgMCwgVG9tY2F0UGx1Z2luLmdldFJlc291cmNlKCIlcHVibGlzaENvbmZpZ3VyYXRpb25UYXNrIiksIG51bGwpOwoJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVSLCAiQmFja3VwIGFuZCBwdWJsaXNoIik7CgkJbW9uaXRvciA9IFByb2dyZXNzVXRpbC5nZXRNb25pdG9yRm9yKG1vbml0b3IpOwoKCQliYWNrdXBBbmRQdWJsaXNoKGNvbmZEaXIsIGRvQmFja3VwLCBtcywgbW9uaXRvciwgMzAwKTsKCQkvLyBUT0RPIFJlZmFjdG9yIHN1Y2Nlc3MgZGV0ZWN0aW9uIG9uY2UgQnVnIDgxMDYwIGlzIGFkZHJlc3NlZAoJCS8vIFRoaXMgYXBwcm9hY2ggYXZvaWRzIHJlZmFjdG9yaW5nIFRvbWNhdENvbmZpZ3VyYXRpb24uYmFja3VwRm9sZGVyKCkKCQkvLyBhbmQgYmFja3VwUGF0aCgpIGZvciBub3cuCgkJaWYgKG1zLmlzT0soKSAmJiBtcy5nZXRDaGlsZHJlbigpLmxlbmd0aCA+IDApCgkJCXB1Ymxpc2hDb250ZXh0Q29uZmlnKGNvbmZEaXIsIG1zLCBtb25pdG9yKTsKCgkJbW9uaXRvci5kb25lKCk7CgkJcmV0dXJuIG1zOwoJfQoJCglwcm90ZWN0ZWQgdm9pZCBwdWJsaXNoQ29udGV4dENvbmZpZyhJUGF0aCBjb25mRGlyLCBNdWx0aVN0YXR1cyBtcywgSVByb2dyZXNzTW9uaXRvciBtb25pdG9yKSB7CgkJVHJhY2UudHJhY2UoVHJhY2UuRklORVIsICJBcHBseSBjb250ZXh0IGNvbmZpZ3VyYXRpb25zIik7CgkJdHJ5IHsKCQkJY29uZkRpciA9IGNvbmZEaXIuYXBwZW5kKCJjb25mIik7CgkJCQoJCQltb25pdG9yLnN1YlRhc2soVG9tY2F0UGx1Z2luLmdldFJlc291cmNlKCIlcHVibGlzaENvbnRleHRDb25maWdUYXNrIikpOwoJCQlGYWN0b3J5IGZhY3RvcnkgPSBuZXcgRmFjdG9yeSgpOwoJCQlmYWN0b3J5LnNldFBhY2thZ2VOYW1lKCJvcmcuZWNsaXBzZS5qc3Quc2VydmVyLnRvbWNhdC5jb3JlLmludGVybmFsLnhtbC5zZXJ2ZXI0MCIpOwoJCQlTZXJ2ZXIgcHVibGlzaGVkU2VydmVyID0gKFNlcnZlcikgZmFjdG9yeS5sb2FkRG9jdW1lbnQobmV3IEZpbGVJbnB1dFN0cmVhbShjb25mRGlyLmFwcGVuZCgic2VydmVyLnhtbCIpLnRvRmlsZSgpKSk7CgkJCW1vbml0b3Iud29ya2VkKDEwMCk7CgoJCQlib29sZWFuIG1vZGlmaWVkID0gZmFsc2U7CgoJCQlpbnQgc2l6ZSA9IHB1Ymxpc2hlZFNlcnZlci5nZXRTZXJ2aWNlQ291bnQoKTsKCQkJZm9yIChpbnQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHsKCQkJCVNlcnZpY2Ugc2VydmljZSA9IHB1Ymxpc2hlZFNlcnZlci5nZXRTZXJ2aWNlKGkpOwoJCQkJaWYgKHNlcnZpY2UuZ2V0TmFtZSgpLmVxdWFsc0lnbm9yZUNhc2UoREVGQVVMVF9TRVJWSUNFKSkgewoJCQkJCUVuZ2luZSBlbmdpbmUgPSBzZXJ2aWNlLmdldEVuZ2luZSgpOwoJCQkJCUhvc3QgaG9zdCA9IGVuZ2luZS5nZXRIb3N0KCk7CgkJCQkJaW50IHNpemUyID0gaG9zdC5nZXRDb250ZXh0Q291bnQoKTsKCQkJCQlmb3IgKGludCBqID0gMDsgaiA8IHNpemUyOyBqKyspIHsKCQkJCQkJQ29udGV4dCBjb250ZXh0ID0gaG9zdC5nZXRDb250ZXh0KGopOwoJCQkJCQltb25pdG9yLnN1YlRhc2soVG9tY2F0UGx1Z2luLmdldFJlc291cmNlKCIlY2hlY2tpbmdDb250ZXh0VGFzayIsCgkJCQkJCQkJbmV3IFN0cmluZ1tdIHtjb250ZXh0LmdldFBhdGgoKX0pKTsKCQkJCQkJaWYgKGFkZENvbnRleHRDb25maWcoY29udGV4dCkpIHsKCQkJCQkJCW1vZGlmaWVkID0gdHJ1ZTsKCQkJCQkJfQoJCQkJCX0KCQkJCX0KCQkJfQoJCQltb25pdG9yLndvcmtlZCgxMDApOwoJCQlpZiAobW9kaWZpZWQpIHsKCQkJCW1vbml0b3Iuc3ViVGFzayhUb21jYXRQbHVnaW4uZ2V0UmVzb3VyY2UoIiVzYXZpbmdDb250ZXh0Q29uZmlnVGFzayIpKTsKCQkJCWZhY3Rvcnkuc2F2ZShjb25mRGlyLmFwcGVuZCgic2VydmVyLnhtbCIpLnRvT1NTdHJpbmcoKSk7CgkJCX0KCQkJbW9uaXRvci53b3JrZWQoMTAwKTsKCQkJCgkJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVSLCAiU2VydmVyLnhtbCB1cGRhdGVkIHdpdGggY29udGV4dC54bWwgY29uZmlndXJhdGlvbnMiKTsKCQkJbXMuYWRkKG5ldyBTdGF0dXMoSVN0YXR1cy5PSywgVG9tY2F0UGx1Z2luLlBMVUdJTl9JRCwgMCwgVG9tY2F0UGx1Z2luLmdldFJlc291cmNlKCIlc2VydmVyUG9zdFByb2Nlc3NpbmdDb21wbGV0ZSIpLCBudWxsKSk7CgkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJVHJhY2UudHJhY2UoVHJhY2UuV0FSTklORywgIkNvdWxkIG5vdCBhcHBseSBjb250ZXh0IGNvbmZpZ3VyYXRpb25zIHB1Ymxpc2hlZCBUb21jYXQgdjUuMCBjb25maWd1cmF0aW9uIGZyb20gIiArIGNvbmZEaXIudG9PU1N0cmluZygpICsgIjogIiArIGUuZ2V0TWVzc2FnZSgpKTsKCQkJSVN0YXR1cyBzID0gbmV3IFN0YXR1cyhJU3RhdHVzLkVSUk9SLCBUb21jYXRQbHVnaW4uUExVR0lOX0lELCAwLCBUb21jYXRQbHVnaW4uZ2V0UmVzb3VyY2UoIiVlcnJvclB1Ymxpc2hDb25maWd1cmF0aW9uIiwgbmV3IFN0cmluZ1tdIHtlLmdldExvY2FsaXplZE1lc3NhZ2UoKX0pLCBlKTsKCQkJbXMuYWRkKHMpOwoJCX0KCX0KCQoJLyoqCgkgKiBJZiB0aGUgc3BlY2lmaWVkIENvbnRleHQgaXMgbGlua2VkIHRvIGEgcHJvamVjdCwgdHJ5IHRvCgkgKiB1cGRhdGUgYW55IGNvbmZpZ3VyYXRpb24gZm91bmQgYSBNRVRBLUlORi9jb250ZXh0LnhtbCBmb3VuZAoJICogcmVsYXRpdmUgdG8gdGhlIHNwZWNpZmllZCBkb2NCYXNlLgoJICogQHBhcmFtIGNvbnRleHQgQ29udGV4dCBvYmplY3QgdG8gcmVjZWl2ZSBjb250ZXh0LnhtbCBjb250ZW50cy4KCSAqIEByZXR1cm4gUmV0dXJucyB0cnVlIGlmIGNvbnRleHQgaXMgbW9kaWZpZWQuCgkgKi8KCXByb3RlY3RlZCBib29sZWFuIGFkZENvbnRleHRDb25maWcoQ29udGV4dCBjb250ZXh0KSB7CgkJYm9vbGVhbiBtb2RpZmllZCA9IGZhbHNlOwoJCVN0cmluZyBzb3VyY2UgPSBjb250ZXh0LmdldFNvdXJjZSgpOwoJCWlmIChzb3VyY2UgIT0gbnVsbCAmJiBzb3VyY2UubGVuZ3RoKCkgPiAwICkKCQl7CgkJCWlmIChjb250ZXh0Lmhhc0NoaWxkTm9kZXMoKSkgewoJCQkJY29udGV4dC5yZW1vdmVDaGlsZHJlbigpOwoJCQkJbW9kaWZpZWQgPSB0cnVlOwoJCQl9CgkJCVN0cmluZyBkb2NCYXNlID0gY29udGV4dC5nZXREb2NCYXNlKCk7CgkJCUNvbnRleHQgY29udGV4dENvbmZpZyA9IGxvYWRDb250ZXh0Q29uZmlnKGRvY0Jhc2UpOwoJCQlpZiAobnVsbCAhPSBjb250ZXh0Q29uZmlnKSB7CgkJCQljb250ZXh0Q29uZmlnLmNvcHlDaGlsZHJlblRvKGNvbnRleHQpOwoJCQkJbW9kaWZpZWQgPSB0cnVlOwoJCQl9CgkJfQoJCXJldHVybiBtb2RpZmllZDsKCX0KCQoJLyoqCgkgKiBUcmllcyB0byByZWFkIGEgTUVUQS1JTkYvY29udGV4dC54bWwgZmlsZSByZWxhdGl2ZSB0byB0aGUKCSAqIHNwZWNpZmllZCBkb2NCYXNlLiAgSWYgZm91bmQsIGl0IGNyZWF0ZXMgYSBDb250ZXh0IG9iamVjdAoJICogY29udGFpbmluZyB0aGUgY29udGV4dHMgb2YgdGhhdCBmaWxlLgoJICogQHBhcmFtIGRvY0Jhc2UKCSAqIEByZXR1cm4gQ29udGV4dCBlbGVtZW50IGNyZWF0ZWQgZnJvbSBjb250ZXh0LnhtbCwgb3IgbnVsbCBpZiBub3QgZm91bmQuCgkgKi8KCXByb3RlY3RlZCBDb250ZXh0IGxvYWRDb250ZXh0Q29uZmlnKFN0cmluZyBkb2NCYXNlKSB7CgkJRmlsZSBjb250ZXhYTUwgPSBuZXcgRmlsZShkb2NCYXNlICsgRmlsZS5zZXBhcmF0b3IgKyAiTUVUQS1JTkYiICsgRmlsZS5zZXBhcmF0b3IgKyAiY29udGV4dC54bWwiKTsKCQlpZiAoY29udGV4WE1MLmV4aXN0cygpKSB7CgkJCXRyeSB7CgkJCQlJbnB1dFN0cmVhbSBpcyA9IG5ldyBGaWxlSW5wdXRTdHJlYW0oY29udGV4WE1MKTsKCQkJCUZhY3RvcnkgY3R4RmFjdG9yeSA9IG5ldyBGYWN0b3J5KCk7CgkJCQljdHhGYWN0b3J5LnNldFBhY2thZ2VOYW1lKCJvcmcuZWNsaXBzZS5qc3Quc2VydmVyLnRvbWNhdC5jb3JlLmludGVybmFsLnhtbC5zZXJ2ZXI0MCIpOwoJCQkJQ29udGV4dCBjdHggPSAoQ29udGV4dCljdHhGYWN0b3J5LmxvYWREb2N1bWVudChpcyk7CgkJCQlpcy5jbG9zZSgpOwoJCQkJcmV0dXJuIGN0eDsKCQkJfSBjYXRjaCAoRmlsZU5vdEZvdW5kRXhjZXB0aW9uIGUpIHsKCQkJCS8vIElnbm9yZSwgc2hvdWxkIG5ldmVyIG9jY3VyCgkJCX0gY2F0Y2ggKElPRXhjZXB0aW9uIGUpIHsKCQkJCVRyYWNlLnRyYWNlKFRyYWNlLlNFVkVSRSwgIkVycm9yIHJlYWRpbmcgd2ViIG1vZHVsZSdzIGNvbnRleHQueG1sIGZpbGU6ICIgKyBkb2NCYXNlLCBlKTsKCQkJfQoJCX0KCQlyZXR1cm4gbnVsbDsKIAl9CgoJcHJvdGVjdGVkIElTdGF0dXMgY2xlYW51cFNlcnZlcihJUGF0aCBjb25mRGlyLCBJUGF0aCBpbnN0YWxsRGlyLCBJUHJvZ3Jlc3NNb25pdG9yIG1vbml0b3IpIHsKCQlNdWx0aVN0YXR1cyBtcyA9IG5ldyBNdWx0aVN0YXR1cyhUb21jYXRQbHVnaW4uUExVR0lOX0lELCAwLAoJCQkJVG9tY2F0UGx1Z2luLmdldFJlc291cmNlKCIlY2xlYW51cFNlcnZlclRhc2siKSwgbnVsbCk7CgkJbW9uaXRvciA9IFByb2dyZXNzVXRpbC5nZXRNb25pdG9yRm9yKG1vbml0b3IpOwoJCW1vbml0b3IuYmVnaW5UYXNrKFRvbWNhdFBsdWdpbi5nZXRSZXNvdXJjZSgiJWNsZWFudXBTZXJ2ZXJUYXNrIiksIDIwMCk7CgoJCXRyeSB7CgkJCW1vbml0b3Iuc3ViVGFzayhUb21jYXRQbHVnaW4uZ2V0UmVzb3VyY2UoIiVkZXRlY3RpbmdSZW1vdmVkUHJvamVjdHMiKSk7CgoJCQkvLyBUcnkgdG8gcmVhZCBvbGQgc2VydmVyIGNvbmZpZ3VyYXRpb24KCQkJRmFjdG9yeSBmYWN0b3J5ID0gbmV3IEZhY3RvcnkoKTsKCQkJZmFjdG9yeS5zZXRQYWNrYWdlTmFtZSgib3JnLmVjbGlwc2UuanN0LnNlcnZlci50b21jYXQuY29yZS5pbnRlcm5hbC54bWwuc2VydmVyNDAiKTsKCQkJRmlsZSBzZXJ2ZXJGaWxlID0gY29uZkRpci5hcHBlbmQoImNvbmYiKS5hcHBlbmQoInNlcnZlci54bWwiKS50b0ZpbGUoKTsKCQkJaWYgKHNlcnZlckZpbGUuZXhpc3RzKCkpIHsKCQkJCVNlcnZlciBvbGRTZXJ2ZXIgPSAoU2VydmVyKSBmYWN0b3J5LmxvYWREb2N1bWVudChuZXcgRmlsZUlucHV0U3RyZWFtKHNlcnZlckZpbGUpKTsKCQkJCQoJCQkJLy8gQmVnaW4gYnVpbGRpbmcgcGF0aCB0byBjb250ZXh0IGRpcmVjdG9yeQoJCQkJSVBhdGggY29udGV4dERpciA9IGluc3RhbGxEaXIuYXBwZW5kKCJjb25mIik7CgoJCQkJLy8gQ29sbGVjdCBwYXRocyBvZiBvbGQgd2ViIG1vZHVsZXMgbWFuYWdlZCBieSBXVFAKCQkJCVNldCBvbGRQYXRocyA9IG5ldyBIYXNoU2V0KCk7CgkJCQlpbnQgc2l6ZSA9IG9sZFNlcnZlci5nZXRTZXJ2aWNlQ291bnQoKTsKCQkJCWZvciAoaW50IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKSB7CgkJCQkJU2VydmljZSBzZXJ2aWNlID0gb2xkU2VydmVyLmdldFNlcnZpY2UoaSk7CgkJCQkJaWYgKHNlcnZpY2UuZ2V0TmFtZSgpLmVxdWFsc0lnbm9yZUNhc2UoREVGQVVMVF9TRVJWSUNFKSkgewoJCQkJCQlFbmdpbmUgZW5naW5lID0gc2VydmljZS5nZXRFbmdpbmUoKTsKCQkJCQkJSG9zdCBob3N0ID0gZW5naW5lLmdldEhvc3QoKTsKCQkJCQkJLy8gRmluaXNoIHBhdGggdG8gY29udGV4dCBkaXJlY3RvcnkKCQkJCQkJY29udGV4dERpciA9IGNvbnRleHREaXIuYXBwZW5kKGVuZ2luZS5nZXROYW1lKCkpLmFwcGVuZChob3N0LmdldE5hbWUoKSk7CgkJCQkJCWludCBzaXplMiA9IGhvc3QuZ2V0Q29udGV4dENvdW50KCk7CgkJCQkJCWZvciAoaW50IGogPSAwOyBqIDwgc2l6ZTI7IGorKykgewoJCQkJCQkJQ29udGV4dCBjb250ZXh0ID0gaG9zdC5nZXRDb250ZXh0KGopOwoJCQkJCQkJU3RyaW5nIHNvdXJjZSA9IGNvbnRleHQuZ2V0U291cmNlKCk7CgkJCQkJCQlpZiAoc291cmNlICE9IG51bGwgJiYgc291cmNlLmxlbmd0aCgpID4gMCApCXsKCQkJCQkJCQlvbGRQYXRocy5hZGQoY29udGV4dC5nZXRQYXRoKCkpOwoJCQkJCQkJfQoJCQkJCQl9CgkJCQkJfQoJCQkJfQoKCQkJCS8vIFJlbW92ZSBwYXRocyBmb3Igd2ViIG1vZHVsZXMgdGhhdCBhcmUgc3RheWluZyBhcm91bmQKCQkJCUxpc3QgbW9kdWxlcyA9IGdldFdlYk1vZHVsZXMoKTsKCQkJCXNpemUgPSBtb2R1bGVzLnNpemUoKTsKCQkJCWZvciAoaW50IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKSB7CgkJCQkJV2ViTW9kdWxlIG1vZHVsZSA9IChXZWJNb2R1bGUpIG1vZHVsZXMuZ2V0KGkpOwoJCQkJCW9sZFBhdGhzLnJlbW92ZShtb2R1bGUuZ2V0UGF0aCgpKTsKCQkJCX0KCQkJCW1vbml0b3Iud29ya2VkKDEwMCk7CgoJCQkJLy8gRGVsZXRlIGNvbnRleHQgZmlsZXMgZm9yIG1hbmFnZWQgd2ViIG1vZHVsZXMgdGhhdCBoYXZlIGdvbmUgYXdheQoJCQkJaWYgKG9sZFBhdGhzLnNpemUoKSA+IDAgKSB7CgkJCQkJSVByb2dyZXNzTW9uaXRvciBzdWJNb25pdG9yID0gUHJvZ3Jlc3NVdGlsLmdldFN1Yk1vbml0b3JGb3IobW9uaXRvciwgMTAwKTsKCQkJCQlzdWJNb25pdG9yLmJlZ2luVGFzayhUb21jYXRQbHVnaW4uZ2V0UmVzb3VyY2UoIiVkZWxldGluZ0NvbnRleHRGaWxlc1Rhc2siKSwgb2xkUGF0aHMuc2l6ZSgpICogMTAwKTsKCQkJCQkKCQkJCQlJdGVyYXRvciBpdGVyID0gb2xkUGF0aHMuaXRlcmF0b3IoKTsKCQkJCQl3aGlsZSAoaXRlci5oYXNOZXh0KCkpIHsKCQkJCQkJLy8gRGVyaXZlIHRoZSBjb250ZXh0IGZpbGUgbmFtZSBmcm9tIHRoZSBwYXRoICsgIi54bWwiLCBtaW51cyB0aGUgbGVhZGluZyAnLycKCQkJCQkJU3RyaW5nIGZpbGVOYW1lID0gKChTdHJpbmcpaXRlci5uZXh0KCkpLnN1YnN0cmluZygxKSArICIueG1sIjsKCQkJCQkJSVBhdGggY29udGV4dFBhdGggPSBjb250ZXh0RGlyLmFwcGVuZChmaWxlTmFtZSk7CgkJCQkJCUZpbGUgY29udGV4dEZpbGUgPSBjb250ZXh0UGF0aC50b0ZpbGUoKTsKCQkJCQkJaWYgKGNvbnRleHRGaWxlLmV4aXN0cygpKSB7CgkJCQkJCQlzdWJNb25pdG9yLnN1YlRhc2soVG9tY2F0UGx1Z2luLmdldFJlc291cmNlKCIlZGVsZXRpbmdDb250ZXh0RmlsZSIsIGZpbGVOYW1lKSk7CgkJCQkJCQlpZiAoY29udGV4dEZpbGUuZGVsZXRlKCkpIHsKCQkJCQkJCQlUcmFjZS50cmFjZShUcmFjZS5GSU5FUiwgIkxlZnRvdmVyIGNvbnRleHQgZmlsZSAiICsgZmlsZU5hbWUgKyAiIGRlbGV0ZWQuIik7CgkJCQkJCQkJbXMuYWRkKG5ldyBTdGF0dXMoSVN0YXR1cy5PSywgVG9tY2F0UGx1Z2luLlBMVUdJTl9JRCwgMCwKCQkJCQkJCQkJCVRvbWNhdFBsdWdpbi5nZXRSZXNvdXJjZSgiJWRlbGV0ZWRDb250ZXh0RmlsZSIsIGZpbGVOYW1lKSwgbnVsbCkpOwoJCQkJCQkJCQoJCQkJCQkJfSBlbHNlIHsKCQkJCQkJCQlUcmFjZS50cmFjZShUcmFjZS5TRVZFUkUsICJDb3VsZCBub3QgZGVsZXRlIG9ic29sZXRlIGNvbnRleHQgZmlsZSAiICsgY29udGV4dFBhdGgudG9PU1N0cmluZygpKTsKCQkJCQkJCQltcy5hZGQobmV3IFN0YXR1cyhJU3RhdHVzLkVSUk9SLCBUb21jYXRQbHVnaW4uUExVR0lOX0lELCAwLAoJCQkJCQkJCQkJVG9tY2F0UGx1Z2luLmdldFJlc291cmNlKCIlZXJyb3JDb3VsZE5vdERlbGV0ZUNvbnRleHRGaWxlIiwgY29udGV4dFBhdGgudG9PU1N0cmluZygpKSwgbnVsbCkpOwoJCQkJCQkJfQoJCQkJCQkJc3ViTW9uaXRvci53b3JrZWQoMTAwKTsKCQkJCQkJfQoJCQkJCX0KCQkJCQlzdWJNb25pdG9yLmRvbmUoKTsKCQkJCX0gZWxzZSB7CgkJCQkJbW9uaXRvci53b3JrZWQoMTAwKTsKCQkJCX0KCQkJfQoJCQkvLyBFbHNlIG5vIHNlcnZlci54bWwuICBBc3N1bWUgZmlyc3QgcHVibGlzaCB0byBuZXcgdGVtcCBkaXJlY3RvcnkKCQkJZWxzZSB7CgkJCQltb25pdG9yLndvcmtlZCgyMDApOwoJCQl9CgkJCVRyYWNlLnRyYWNlKFRyYWNlLkZJTkVSLCAiU2VydmVyIGNsZWFuZWQiKTsKCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQlUcmFjZS50cmFjZShUcmFjZS5TRVZFUkUsICJDb3VsZCBub3QgY2xlYW51cCBzZXJ2ZXIgYXQgIiArIGNvbmZEaXIudG9PU1N0cmluZygpICsgIjogIiArIGUuZ2V0TWVzc2FnZSgpKTsKCQkJbXMuYWRkKG5ldyBTdGF0dXMoSVN0YXR1cy5FUlJPUiwgVG9tY2F0UGx1Z2luLlBMVUdJTl9JRCwgMCwKCQkJCQlUb21jYXRQbHVnaW4uZ2V0UmVzb3VyY2UoIiVlcnJvckNsZWFudXBTZXJ2ZXIiLCBuZXcgU3RyaW5nW10ge2UuZ2V0TG9jYWxpemVkTWVzc2FnZSgpfSksIGUpKTsKCQl9CgkJCgkJbW9uaXRvci5kb25lKCk7CgkJcmV0dXJuIG1zOwoJfQp9