LyoKKiBUaGUgQXBhY2hlIFNvZnR3YXJlIExpY2Vuc2UsIFZlcnNpb24gMS4xCioKKgoqIENvcHlyaWdodCAoYykgMjAwMyBUaGUgQXBhY2hlIFNvZnR3YXJlIEZvdW5kYXRpb24uICBBbGwgcmlnaHRzIAoqIHJlc2VydmVkLgoqCiogUmVkaXN0cmlidXRpb24gYW5kIHVzZSBpbiBzb3VyY2UgYW5kIGJpbmFyeSBmb3Jtcywgd2l0aCBvciB3aXRob3V0CiogbW9kaWZpY2F0aW9uLCBhcmUgcGVybWl0dGVkIHByb3ZpZGVkIHRoYXQgdGhlIGZvbGxvd2luZyBjb25kaXRpb25zCiogYXJlIG1ldDoKKgoqIDEuIFJlZGlzdHJpYnV0aW9ucyBvZiBzb3VyY2UgY29kZSBtdXN0IHJldGFpbiB0aGUgYWJvdmUgY29weXJpZ2h0CiogICAgbm90aWNlLCB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyLiAKKgoqIDIuIFJlZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9ybSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUgY29weXJpZ2h0CiogICAgbm90aWNlLCB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyIGluCiogICAgdGhlIGRvY3VtZW50YXRpb24gYW5kL29yIG90aGVyIG1hdGVyaWFscyBwcm92aWRlZCB3aXRoIHRoZQoqICAgIGRpc3RyaWJ1dGlvbi4KKgoqIDMuIFRoZSBlbmQtdXNlciBkb2N1bWVudGF0aW9uIGluY2x1ZGVkIHdpdGggdGhlIHJlZGlzdHJpYnV0aW9uLAoqICAgIGlmIGFueSwgbXVzdCBpbmNsdWRlIHRoZSBmb2xsb3dpbmcgYWNrbm93bGVkZ21lbnQ6ICAKKiAgICAgICAiVGhpcyBwcm9kdWN0IGluY2x1ZGVzIHNvZnR3YXJlIGRldmVsb3BlZCBieSB0aGUKKiAgICAgICAgQXBhY2hlIFNvZnR3YXJlIEZvdW5kYXRpb24gKGh0dHA6Ly93d3cuYXBhY2hlLm9yZy8pLiIKKiAgICBBbHRlcm5hdGVseSwgdGhpcyBhY2tub3dsZWRnbWVudCBtYXkgYXBwZWFyIGluIHRoZSBzb2Z0d2FyZSBpdHNlbGYsCiogICAgaWYgYW5kIHdoZXJldmVyIHN1Y2ggdGhpcmQtcGFydHkgYWNrbm93bGVkZ21lbnRzIG5vcm1hbGx5IGFwcGVhci4KKgoqIDQuIFRoZSBuYW1lcyAiQXBhY2hlIiBhbmQgIkFwYWNoZSBTb2Z0d2FyZSBGb3VuZGF0aW9uIiBtdXN0IAoqICAgIG5vdCBiZSB1c2VkIHRvIGVuZG9yc2Ugb3IgcHJvbW90ZSBwcm9kdWN0cyBkZXJpdmVkIGZyb20gdGhpcwoqICAgIHNvZnR3YXJlIHdpdGhvdXQgcHJpb3Igd3JpdHRlbiBwZXJtaXNzaW9uLiBGb3Igd3JpdHRlbiAKKiAgICBwZXJtaXNzaW9uLCBwbGVhc2UgY29udGFjdCBhcGFjaGVAYXBhY2hlLm9yZy4KKgoqIDUuIFByb2R1Y3RzIGRlcml2ZWQgZnJvbSB0aGlzIHNvZnR3YXJlIG1heSBub3QgYmUgY2FsbGVkICJBcGFjaGUgCiogICAgWE1MQmVhbnMiLCBub3IgbWF5ICJBcGFjaGUiIGFwcGVhciBpbiB0aGVpciBuYW1lLCB3aXRob3V0IHByaW9yIAoqICAgIHdyaXR0ZW4gcGVybWlzc2lvbiBvZiB0aGUgQXBhY2hlIFNvZnR3YXJlIEZvdW5kYXRpb24uCioKKiBUSElTIFNPRlRXQVJFIElTIFBST1ZJREVEIGBgQVMgSVMnJyBBTkQgQU5ZIEVYUFJFU1NFRCBPUiBJTVBMSUVECiogV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRSBJTVBMSUVEIFdBUlJBTlRJRVMKKiBPRiBNRVJDSEFOVEFCSUxJVFkgQU5EIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFSRQoqIERJU0NMQUlNRUQuICBJTiBOTyBFVkVOVCBTSEFMTCBUSEUgQVBBQ0hFIFNPRlRXQVJFIEZPVU5EQVRJT04gT1IKKiBJVFMgQ09OVFJJQlVUT1JTIEJFIExJQUJMRSBGT1IgQU5ZIERJUkVDVCwgSU5ESVJFQ1QsIElOQ0lERU5UQUwsCiogU1BFQ0lBTCwgRVhFTVBMQVJZLCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVMgKElOQ0xVRElORywgQlVUIE5PVAoqIExJTUlURUQgVE8sIFBST0NVUkVNRU5UIE9GIFNVQlNUSVRVVEUgR09PRFMgT1IgU0VSVklDRVM7IExPU1MgT0YKKiBVU0UsIERBVEEsIE9SIFBST0ZJVFM7IE9SIEJVU0lORVNTIElOVEVSUlVQVElPTikgSE9XRVZFUiBDQVVTRUQgQU5ECiogT04gQU5ZIFRIRU9SWSBPRiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQ09OVFJBQ1QsIFNUUklDVCBMSUFCSUxJVFksCiogT1IgVE9SVCAoSU5DTFVESU5HIE5FR0xJR0VOQ0UgT1IgT1RIRVJXSVNFKSBBUklTSU5HIElOIEFOWSBXQVkgT1VUCiogT0YgVEhFIFVTRSBPRiBUSElTIFNPRlRXQVJFLCBFVkVOIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GCiogU1VDSCBEQU1BR0UuCiogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KKgoqIFRoaXMgc29mdHdhcmUgY29uc2lzdHMgb2Ygdm9sdW50YXJ5IGNvbnRyaWJ1dGlvbnMgbWFkZSBieSBtYW55CiogaW5kaXZpZHVhbHMgb24gYmVoYWxmIG9mIHRoZSBBcGFjaGUgU29mdHdhcmUgRm91bmRhdGlvbiBhbmQgd2FzCiogb3JpZ2luYWxseSBiYXNlZCBvbiBzb2Z0d2FyZSBjb3B5cmlnaHQgKGMpIDIwMDAtMjAwMyBCRUEgU3lzdGVtcyAKKiBJbmMuLCA8aHR0cDovL3d3dy5iZWEuY29tLz4uIEZvciBtb3JlIGluZm9ybWF0aW9uIG9uIHRoZSBBcGFjaGUgU29mdHdhcmUKKiBGb3VuZGF0aW9uLCBwbGVhc2Ugc2VlIDxodHRwOi8vd3d3LmFwYWNoZS5vcmcvPi4KKi8KCnBhY2thZ2Ugb3JnLmFwYWNoZS54bWxiZWFucy5pbXBsLnNjaGVtYTsKCmltcG9ydCBqYXZhLm1hdGguQmlnSW50ZWdlcjsKaW1wb3J0IGphdmEudXRpbC4qOwppbXBvcnQgamF2YS51dGlsLkxpc3Q7CgppbXBvcnQgb3JnLnczLngyMDAxLnhtbFNjaGVtYS4qOwppbXBvcnQgb3JnLnczLngyMDAxLnhtbFNjaGVtYS5TY2hlbWFEb2N1bWVudC5TY2hlbWE7CmltcG9ydCBvcmcudzMueDIwMDEueG1sU2NoZW1hLkFueURvY3VtZW50LkFueTsKaW1wb3J0IGphdmF4LnhtbC5uYW1lc3BhY2UuUU5hbWU7CmltcG9ydCBvcmcuYXBhY2hlLnhtbGJlYW5zLmltcGwuY29tbW9uLlhtbEVycm9yQ29udGV4dDsKaW1wb3J0IG9yZy5hcGFjaGUueG1sYmVhbnMuaW1wbC5jb21tb24uUU5hbWVIZWxwZXI7CmltcG9ydCBvcmcuYXBhY2hlLnhtbGJlYW5zLlhtbE9iamVjdDsKaW1wb3J0IG9yZy5hcGFjaGUueG1sYmVhbnMuUU5hbWVTZXRCdWlsZGVyOwppbXBvcnQgb3JnLmFwYWNoZS54bWxiZWFucy5YbWxJbnRlZ2VyOwppbXBvcnQgb3JnLmFwYWNoZS54bWxiZWFucy5TY2hlbWFGaWVsZDsKaW1wb3J0IG9yZy5hcGFjaGUueG1sYmVhbnMuU2NoZW1hVHlwZTsKaW1wb3J0IG9yZy5hcGFjaGUueG1sYmVhbnMuU2NoZW1hUGFydGljbGU7CmltcG9ydCBvcmcuYXBhY2hlLnhtbGJlYW5zLlhtbEN1cnNvcjsKaW1wb3J0IG9yZy5hcGFjaGUueG1sYmVhbnMuU2NoZW1hQXR0cmlidXRlTW9kZWw7CmltcG9ydCBvcmcuYXBhY2hlLnhtbGJlYW5zLlNjaGVtYVByb3BlcnR5OwppbXBvcnQgb3JnLmFwYWNoZS54bWxiZWFucy5RTmFtZVNldDsKaW1wb3J0IG9yZy5hcGFjaGUueG1sYmVhbnMuWG1sTm9uTmVnYXRpdmVJbnRlZ2VyOwppbXBvcnQgb3JnLmFwYWNoZS54bWxiZWFucy5TY2hlbWFMb2NhbEF0dHJpYnV0ZTsKaW1wb3J0IG9yZy5hcGFjaGUueG1sYmVhbnMuU2NoZW1hTG9jYWxFbGVtZW50OwppbXBvcnQgb3JnLmFwYWNoZS54bWxiZWFucy5RTmFtZVNldFNwZWNpZmljYXRpb247CgpwdWJsaWMgY2xhc3MgU3RzY0NvbXBsZXhUeXBlUmVzb2x2ZXIKewogICAgcHVibGljIHN0YXRpYyBHcm91cCBnZXRDb250ZW50TW9kZWwoQ29tcGxleFR5cGUgcGFyc2VDdCkKICAgIHsKICAgICAgICBpZiAocGFyc2VDdC5nZXRBbGwoKSAhPSBudWxsKQogICAgICAgICAgICByZXR1cm4gcGFyc2VDdC5nZXRBbGwoKTsKCiAgICAgICAgaWYgKHBhcnNlQ3QuZ2V0U2VxdWVuY2UoKSAhPSBudWxsKQogICAgICAgICAgICByZXR1cm4gcGFyc2VDdC5nZXRTZXF1ZW5jZSgpOwoKICAgICAgICBpZiAocGFyc2VDdC5nZXRDaG9pY2UoKSAhPSBudWxsKQogICAgICAgICAgICByZXR1cm4gcGFyc2VDdC5nZXRDaG9pY2UoKTsKCiAgICAgICAgaWYgKHBhcnNlQ3QuZ2V0R3JvdXAoKSAhPSBudWxsKQogICAgICAgICAgICByZXR1cm4gcGFyc2VDdC5nZXRHcm91cCgpOwoKICAgICAgICByZXR1cm4gbnVsbDsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIEdyb3VwIGdldENvbnRlbnRNb2RlbChDb21wbGV4UmVzdHJpY3Rpb25UeXBlIHBhcnNlUmVzdCkKICAgIHsKICAgICAgICBpZiAocGFyc2VSZXN0LmdldEFsbCgpICE9IG51bGwpCiAgICAgICAgICAgIHJldHVybiBwYXJzZVJlc3QuZ2V0QWxsKCk7CgogICAgICAgIGlmIChwYXJzZVJlc3QuZ2V0U2VxdWVuY2UoKSAhPSBudWxsKQogICAgICAgICAgICByZXR1cm4gcGFyc2VSZXN0LmdldFNlcXVlbmNlKCk7CgogICAgICAgIGlmIChwYXJzZVJlc3QuZ2V0Q2hvaWNlKCkgIT0gbnVsbCkKICAgICAgICAgICAgcmV0dXJuIHBhcnNlUmVzdC5nZXRDaG9pY2UoKTsKCiAgICAgICAgaWYgKHBhcnNlUmVzdC5nZXRHcm91cCgpICE9IG51bGwpCiAgICAgICAgICAgIHJldHVybiBwYXJzZVJlc3QuZ2V0R3JvdXAoKTsKCiAgICAgICAgcmV0dXJuIG51bGw7CgogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgR3JvdXAgZ2V0Q29udGVudE1vZGVsKEV4dGVuc2lvblR5cGUgcGFyc2VFeHQpCiAgICB7CiAgICAgICAgaWYgKHBhcnNlRXh0LmdldEFsbCgpICE9IG51bGwpCiAgICAgICAgICAgIHJldHVybiBwYXJzZUV4dC5nZXRBbGwoKTsKCiAgICAgICAgaWYgKHBhcnNlRXh0LmdldFNlcXVlbmNlKCkgIT0gbnVsbCkKICAgICAgICAgICAgcmV0dXJuIHBhcnNlRXh0LmdldFNlcXVlbmNlKCk7CgogICAgICAgIGlmIChwYXJzZUV4dC5nZXRDaG9pY2UoKSAhPSBudWxsKQogICAgICAgICAgICByZXR1cm4gcGFyc2VFeHQuZ2V0Q2hvaWNlKCk7CgogICAgICAgIGlmIChwYXJzZUV4dC5nZXRHcm91cCgpICE9IG51bGwpCiAgICAgICAgICAgIHJldHVybiBwYXJzZUV4dC5nZXRHcm91cCgpOwoKICAgICAgICByZXR1cm4gbnVsbDsKCiAgICB9CgogICAgcHJpdmF0ZSBzdGF0aWMgU2NoZW1hIGdldFNjaGVtYShYbWxPYmplY3QgbykKICAgIHsKICAgICAgICBYbWxDdXJzb3IgYyA9IG8ubmV3Q3Vyc29yKCk7CiAgICAgICAgCiAgICAgICAgdHJ5CiAgICAgICAgewogICAgICAgICAgICB3aGlsZSAoIGMudG9QYXJlbnQoKSApCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIG8gPSBjLmdldE9iamVjdCgpOwogICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICBpZiAoby5zY2hlbWFUeXBlKCkuZXF1YWxzKFNjaGVtYS50eXBlKSkKICAgICAgICAgICAgICAgICAgICByZXR1cm4gKFNjaGVtYSkgbzsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBmaW5hbGx5CiAgICAgICAgewogICAgICAgICAgICBjLmRpc3Bvc2UoKTsKICAgICAgICB9CiAgICAgICAgCiAgICAgICAgcmV0dXJuIG51bGw7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyB2b2lkIHJlc29sdmVDb21wbGV4VHlwZShTY2hlbWFUeXBlSW1wbCBzSW1wbCkKICAgIHsKICAgICAgICBDb21wbGV4VHlwZSBwYXJzZUN0ID0gKENvbXBsZXhUeXBlKXNJbXBsLmdldFBhcnNlT2JqZWN0KCk7CiAgICAgICAgU3RzY1N0YXRlIHN0YXRlID0gU3RzY1N0YXRlLmdldCgpOwogICAgICAgIFNjaGVtYSBzY2hlbWEgPSBnZXRTY2hlbWEocGFyc2VDdCk7CgogICAgICAgIC8vIFNldCBhYnN0cmFjdCAmIGZpbmFsIGZsYWdzCiAgICAgICAgYm9vbGVhbiBhYnMgPSBwYXJzZUN0LmlzU2V0QWJzdHJhY3QoKSA/IHBhcnNlQ3QuZ2V0QWJzdHJhY3QoKSA6IGZhbHNlOwogICAgICAgIGJvb2xlYW4gZmluYWxFeHQgPSBmYWxzZTsKICAgICAgICBib29sZWFuIGZpbmFsUmVzdCA9IGZhbHNlOwogICAgICAgIGJvb2xlYW4gZmluYWxMaXN0ID0gZmFsc2U7CiAgICAgICAgYm9vbGVhbiBmaW5hbFVuaW9uID0gZmFsc2U7CgogICAgICAgIE9iamVjdCBkcyA9IG51bGw7CiAgICAgICAgaWYgKHBhcnNlQ3QuaXNTZXRGaW5hbCgpKQogICAgICAgIHsKICAgICAgICAgICAgZHMgPSBwYXJzZUN0LmdldEZpbmFsKCk7CiAgICAgICAgfQogICAgICAgIC8vIEluc3BlY3QgdGhlIGZpbmFsIGRlZmF1bHQgYXR0cmlidXRlIG9uIHRoZSBzY2hlbWEKICAgICAgICBlbHNlIGlmIChzY2hlbWEgIT0gbnVsbCAmJiBzY2hlbWEuaXNTZXRGaW5hbERlZmF1bHQoKSkKICAgICAgICB7CiAgICAgICAgICAgIGRzID0gc2NoZW1hLmdldEZpbmFsRGVmYXVsdCgpOwogICAgICAgIH0KCiAgICAgICAgaWYgKGRzICE9IG51bGwpCiAgICAgICAgewogICAgICAgICAgICBpZiAoZHMgaW5zdGFuY2VvZiBTdHJpbmcgJiYgZHMuZXF1YWxzKCIjYWxsIikpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIC8vICNBTEwgdmFsdWUKICAgICAgICAgICAgICAgIGZpbmFsRXh0ID0gZmluYWxSZXN0ID0gZmluYWxMaXN0ID0gZmluYWxVbmlvbiA9IHRydWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSBpZiAoZHMgaW5zdGFuY2VvZiBMaXN0KQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBpZiAoKChMaXN0KWRzKS5jb250YWlucygiZXh0ZW5zaW9uIikpCiAgICAgICAgICAgICAgICAgICAgZmluYWxFeHQgPSB0cnVlOwogICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICBpZiAoKChMaXN0KWRzKS5jb250YWlucygicmVzdHJpY3Rpb24iKSkKICAgICAgICAgICAgICAgICAgICBmaW5hbFJlc3QgPSB0cnVlOwoKLy8gU2luY2UgY29tcGxleCB0eXBlcyBkb24ndCBwYXJ0aWNpcGF0ZSBpbiBsaXN0IGFuZCB1bmlvbnMsIHRoZXNlIGNhbiByZW1haW4KLy8gZmFsc2UuICBQZXJoYXBzIHdlIHNob3VsZCB0aHJvdyBhbiBlcnJvci4KCi8vICAgICAgICAgICAgICAgIGlmICgoKExpc3QpZHMpLmNvbnRhaW5zKCJsaXN0IikpCi8vICAgICAgICAgICAgICAgICAgICBmaW5hbExpc3QgPSB0cnVlOwovLyAgICAgICAgICAgICAgICAKLy8gICAgICAgICAgICAgICAgaWYgKCgoTGlzdClkcykuY29udGFpbnMoInVuaW9uIikpCi8vICAgICAgICAgICAgICAgICAgICBmaW5hbFVuaW9uID0gdHJ1ZTsKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgc0ltcGwuc2V0QWJzdHJhY3RGaW5hbChhYnMsIGZpbmFsRXh0LCBmaW5hbFJlc3QsIGZpbmFsTGlzdCwgZmluYWxVbmlvbik7CgogICAgICAgIC8vIFNldCBibG9jayBmbGFncwogICAgICAgIGJvb2xlYW4gYmxvY2tFeHQgPSBmYWxzZTsKICAgICAgICBib29sZWFuIGJsb2NrUmVzdCA9IGZhbHNlOwogICAgICAgIE9iamVjdCBibG9jayA9IG51bGw7CgogICAgICAgIGlmIChwYXJzZUN0LmlzU2V0QmxvY2soKSkKICAgICAgICAgICAgYmxvY2sgPSBwYXJzZUN0LmdldEJsb2NrKCk7CiAgICAgICAgZWxzZSBpZiAoc2NoZW1hICE9IG51bGwgJiYgc2NoZW1hLmlzU2V0QmxvY2tEZWZhdWx0KCkpCiAgICAgICAgICAgIGJsb2NrID0gc2NoZW1hLmdldEJsb2NrRGVmYXVsdCgpOwoKICAgICAgICBpZiAoYmxvY2sgIT0gbnVsbCkKICAgICAgICB7CiAgICAgICAgICAgIGlmIChibG9jayBpbnN0YW5jZW9mIFN0cmluZyAmJiBibG9jay5lcXVhbHMoIiNhbGwiKSkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgLy8gI0FMTCB2YWx1ZQogICAgICAgICAgICAgICAgYmxvY2tFeHQgPSBibG9ja1Jlc3QgPSB0cnVlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UgaWYgKGJsb2NrIGluc3RhbmNlb2YgTGlzdCkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgaWYgKCgoTGlzdClibG9jaykuY29udGFpbnMoImV4dGVuc2lvbiIpKQogICAgICAgICAgICAgICAgICAgIGJsb2NrRXh0ID0gdHJ1ZTsKICAgICAgICAgICAgICAgIGlmICgoKExpc3QpYmxvY2spLmNvbnRhaW5zKCJyZXN0cmljdGlvbiIpKQogICAgICAgICAgICAgICAgICAgIGJsb2NrUmVzdCA9IHRydWU7CiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIHNJbXBsLnNldEJsb2NrKGJsb2NrRXh0LCBibG9ja1Jlc3QpOwoKICAgICAgICAvLyBWZXJpZnk6IGhhdmUgc2ltcGxlQ29udGVudCwgY29tcGxleENvbnRlbnQsIG9yIGRpcmVjdCBzdHVmZgogICAgICAgIENvbXBsZXhDb250ZW50RG9jdW1lbnQuQ29tcGxleENvbnRlbnQgcGFyc2VDYyA9IHBhcnNlQ3QuZ2V0Q29tcGxleENvbnRlbnQoKTsKICAgICAgICBTaW1wbGVDb250ZW50RG9jdW1lbnQuU2ltcGxlQ29udGVudCBwYXJzZVNjID0gcGFyc2VDdC5nZXRTaW1wbGVDb250ZW50KCk7CiAgICAgICAgR3JvdXAgcGFyc2VHcm91cCA9IGdldENvbnRlbnRNb2RlbChwYXJzZUN0KTsKICAgICAgICBpbnQgY291bnQgPQogICAgICAgICAgICAgICAgKHBhcnNlQ2MgIT0gbnVsbCA/IDEgOiAwKSArCiAgICAgICAgICAgICAgICAocGFyc2VTYyAhPSBudWxsID8gMSA6IDApICsKICAgICAgICAgICAgICAgIChwYXJzZUdyb3VwICE9IG51bGwgPyAxIDogMCk7CiAgICAgICAgaWYgKGNvdW50ID4gMSkKICAgICAgICB7CiAgICAgICAgICAgIHN0YXRlLmVycm9yKCJBIGNvbXBsZXggdHlwZSBtdXN0IGRlZmluZSBlaXRoZXIgYSBjb250ZW50IG1vZGVsLCAiICsKICAgICAgICAgICAgICAgICAgICAgICJvciBhIHNpbXBsZUNvbnRlbnQgb3IgY29tcGxleENvbnRlbnQgZGVyaXZhdGlvbjogIiArCiAgICAgICAgICAgICAgICAgICAgICAibW9yZSB0aGFuIG9uZSBmb3VuZC4iLAogICAgICAgICAgICAgICAgICAgIFhtbEVycm9yQ29udGV4dC5SRURVTkRBTlRfQ09OVEVOVF9NT0RFTCwgcGFyc2VDdCk7CiAgICAgICAgICAgIC8vIHJlY292ZXJ5OiB0cmVhdCBpdCBhcyB0aGUgZmlyc3Qgb2YgY29tcGxleENvbnRlbnQsIHNpbXBsZUNvbnRlbnQsIG1vZGVsCiAgICAgICAgICAgIHBhcnNlR3JvdXAgPSBudWxsOwogICAgICAgICAgICBpZiAocGFyc2VDYyAhPSBudWxsICYmIHBhcnNlU2MgIT0gbnVsbCkKICAgICAgICAgICAgICAgIHBhcnNlU2MgPSBudWxsOwogICAgICAgIH0KICAgICAgICAKICAgICAgICBpZiAocGFyc2VDYyAhPSBudWxsKQogICAgICAgIHsKICAgICAgICAgICAgaWYgKHBhcnNlQ2MuZ2V0RXh0ZW5zaW9uKCkgIT0gbnVsbCAmJiBwYXJzZUNjLmdldFJlc3RyaWN0aW9uKCkgIT0gbnVsbCkKICAgICAgICAgICAgICAgIHN0YXRlLmVycm9yKCJSZXN0cmljdGlvbiBjb25mbGljdHMgd2l0aCBleHRlbnNpb24iLCBYbWxFcnJvckNvbnRleHQuUkVEVU5EQU5UX0NPTlRFTlRfTU9ERUwsIHBhcnNlQ2MuZ2V0UmVzdHJpY3Rpb24oKSk7CiAgICAgICAgICAgIAogICAgICAgICAgICAvLyBNaXhlZCBjYW4gYmUgc3BlY2lmaWVkIGluIHR3byBwbGFjZXM6IHRoZSBydWxlcyBhcmUgdGhhdCBDYyB3aW5zIG92ZXIgQ3QgaWYgcHJlc2VudAogICAgICAgICAgICAvLyBodHRwOi8vd3d3LnczLm9yZy9UUi94bWxzY2hlbWEtMS8jYy1tdmUKICAgICAgICAgICAgYm9vbGVhbiBtaXhlZCA9IHBhcnNlQ2MuaXNTZXRNaXhlZCgpID8gcGFyc2VDYy5nZXRNaXhlZCgpIDogcGFyc2VDdC5nZXRNaXhlZCgpOwogICAgICAgICAgICAKICAgICAgICAgICAgaWYgKHBhcnNlQ2MuZ2V0RXh0ZW5zaW9uKCkgIT0gbnVsbCkKICAgICAgICAgICAgICAgIHJlc29sdmVDY0V4dGVuc2lvbihzSW1wbCwgcGFyc2VDYy5nZXRFeHRlbnNpb24oKSwgbWl4ZWQpOwogICAgICAgICAgICBlbHNlIGlmIChwYXJzZUNjLmdldFJlc3RyaWN0aW9uKCkgIT0gbnVsbCkKICAgICAgICAgICAgICAgIHJlc29sdmVDY1Jlc3RyaWN0aW9uKHNJbXBsLCBwYXJzZUNjLmdldFJlc3RyaWN0aW9uKCksIG1peGVkKTsKICAgICAgICAgICAgZWxzZQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBzdGF0ZS5lcnJvcigiTWlzc2luZyByZXN0cmljdGlvbiBvciBleHRlbnNpb24iLCBYbWxFcnJvckNvbnRleHQuTUlTU0lOR19SRVNUUklDVElPTl9PUl9FWFRFTlNJT04sIHBhcnNlQ2MpOwogICAgICAgICAgICAgICAgcmVzb2x2ZUVycm9yVHlwZShzSW1wbCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KICAgICAgICBlbHNlIGlmIChwYXJzZVNjICE9IG51bGwpCiAgICAgICAgewogICAgICAgICAgICBpZiAocGFyc2VTYy5nZXRFeHRlbnNpb24oKSAhPSBudWxsICYmIHBhcnNlU2MuZ2V0UmVzdHJpY3Rpb24oKSAhPSBudWxsKQogICAgICAgICAgICAgICAgc3RhdGUuZXJyb3IoIlJlc3RyaWN0aW9uIGNvbmZsaWN0cyB3aXRoIGV4dGVuc2lvbiIsIFhtbEVycm9yQ29udGV4dC5SRURVTkRBTlRfQ09OVEVOVF9NT0RFTCwgcGFyc2VTYy5nZXRSZXN0cmljdGlvbigpKTsKCiAgICAgICAgICAgIGlmIChwYXJzZVNjLmdldEV4dGVuc2lvbigpICE9IG51bGwpCiAgICAgICAgICAgICAgICByZXNvbHZlU2NFeHRlbnNpb24oc0ltcGwsIHBhcnNlU2MuZ2V0RXh0ZW5zaW9uKCkpOwogICAgICAgICAgICBlbHNlIGlmIChwYXJzZVNjLmdldFJlc3RyaWN0aW9uKCkgIT0gbnVsbCkKICAgICAgICAgICAgICAgIHJlc29sdmVTY1Jlc3RyaWN0aW9uKHNJbXBsLCBwYXJzZVNjLmdldFJlc3RyaWN0aW9uKCkpOwogICAgICAgICAgICBlbHNlCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIHN0YXRlLmVycm9yKCJNaXNzaW5nIHJlc3RyaWN0aW9uIG9yIGV4dGVuc2lvbiIsIFhtbEVycm9yQ29udGV4dC5NSVNTSU5HX1JFU1RSSUNUSU9OX09SX0VYVEVOU0lPTiwgcGFyc2VTYyk7CiAgICAgICAgICAgICAgICByZXNvbHZlRXJyb3JUeXBlKHNJbXBsKTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm47CiAgICAgICAgfQogICAgICAgIGVsc2UKICAgICAgICAgICAgcmVzb2x2ZUJhc2ljQ29tcGxleFR5cGUoc0ltcGwpOwogICAgfQoKICAgIHN0YXRpYyB2b2lkIHJlc29sdmVFcnJvclR5cGUoU2NoZW1hVHlwZUltcGwgc0ltcGwpCiAgICB7CiAgICAgICAgdGhyb3cgbmV3IFJ1bnRpbWVFeGNlcHRpb24oIlRoaXMgdHlwZSBvZiBlcnJvciByZWNvdmVyeSBub3QgeWV0IGltcGxlbWVudGVkLiIpOwogICAgfQoKICAgIHByaXZhdGUgc3RhdGljIFNjaGVtYVR5cGUuUmVmW10gbWFrZVJlZkFycmF5KENvbGxlY3Rpb24gdHlwZUxpc3QpCiAgICB7CiAgICAgICAgU2NoZW1hVHlwZS5SZWZbXSByZXN1bHQgPSBuZXcgU2NoZW1hVHlwZS5SZWZbdHlwZUxpc3Quc2l6ZSgpXTsKICAgICAgICBpbnQgaiA9IDA7CiAgICAgICAgZm9yIChJdGVyYXRvciBpID0gdHlwZUxpc3QuaXRlcmF0b3IoKTsgaS5oYXNOZXh0KCk7IGorKykKICAgICAgICAgICAgcmVzdWx0W2pdID0gKChTY2hlbWFUeXBlKWkubmV4dCgpKS5nZXRSZWYoKTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgfQoKCiAgICBzdGF0aWMgdm9pZCByZXNvbHZlQmFzaWNDb21wbGV4VHlwZShTY2hlbWFUeXBlSW1wbCBzSW1wbCkKICAgIHsKICAgICAgICBMaXN0IGFub255bW91c1R5cGVzID0gbmV3IEFycmF5TGlzdCgpOwogICAgICAgIENvbXBsZXhUeXBlIHBhcnNlVHJlZSA9IChDb21wbGV4VHlwZSlzSW1wbC5nZXRQYXJzZU9iamVjdCgpOwogICAgICAgIFN0cmluZyB0YXJnZXROYW1lc3BhY2UgPSBzSW1wbC5nZXRUYXJnZXROYW1lc3BhY2UoKTsKICAgICAgICBib29sZWFuIGNoYW1lbGVvbiA9IChzSW1wbC5nZXRDaGFtZWxlb25OYW1lc3BhY2UoKSAhPSBudWxsKTsKICAgICAgICBHcm91cCBwYXJzZUdyb3VwID0gZ2V0Q29udGVudE1vZGVsKHBhcnNlVHJlZSk7CgogICAgICAgIGlmIChzSW1wbC5pc1JlZGVmaW5pdGlvbigpKQogICAgICAgIHsKICAgICAgICAgICAgU3RzY1N0YXRlLmdldCgpLmVycm9yKCJBIHR5cGUgcmVkZWZpbml0aW9uIG11c3QgZXh0ZW5kIG9yIHJlc3RyaWN0IHRoZSBvcmlnaW5hbCBkZWZpbml0aW9uIG9mIHRoZSB0eXBlLiIsIFhtbEVycm9yQ29udGV4dC5HRU5FUklDX0VSUk9SLCBwYXJzZVRyZWUpOwogICAgICAgICAgICAvLyByZWNvdmVyeTogb2ggd2VsbC4KICAgICAgICB9CgogICAgICAgIGludCBwYXJ0aWNsZUNvZGUgPSB0cmFuc2xhdGVQYXJ0aWNsZUNvZGUocGFyc2VHcm91cCk7CgogICAgICAgIC8vIHVzZWQgdG8gZW5zdXJlIGNvbnNpc3RlbmN5IChkb2Vzbid0IGJlY29tZSBwYXJ0IG9mIHRoZSByZXN1bHQpCiAgICAgICAgTWFwIGVsZW1lbnRNb2RlbCA9IG5ldyBMaW5rZWRIYXNoTWFwKCk7CgogICAgICAgIC8vIGJ1aWxkIGNvbnRlbnQgbW9kZWwgYW5kIGFub255bW91cyB0eXBlcwogICAgICAgIFNjaGVtYVBhcnRpY2xlIGNvbnRlbnRNb2RlbCA9IHRyYW5zbGF0ZUNvbnRlbnRNb2RlbChzSW1wbCwgcGFyc2VHcm91cCwgdGFyZ2V0TmFtZXNwYWNlLCBjaGFtZWxlb24sIHBhcnRpY2xlQ29kZSwgYW5vbnltb3VzVHlwZXMsIGVsZW1lbnRNb2RlbCwgZmFsc2UsIG51bGwpOwoKICAgICAgICAvLyBkZXRlY3QgdGhlIG5vbmVtcHR5ICJhbGwiIGNhc2UgKGVtcHR5IDxhbGw+IGRvZXNuJ3QgY291bnQgLSBpdCBuZWVkcyB0byBiZSBlbGltaW5hdGVkIHRvIG1hdGNoIFhTRCB0ZXN0IGNhc2VzKQogICAgICAgIGJvb2xlYW4gaXNBbGwgPSBjb250ZW50TW9kZWwgIT0gbnVsbCAmJiBjb250ZW50TW9kZWwuZ2V0UGFydGljbGVUeXBlKCkgPT0gU2NoZW1hUGFydGljbGUuQUxMOwogICAgICAgIAogICAgICAgIC8vIGJ1aWxkIGF0dHIgbW9kZWwgYW5kIGFub255bW91cyB0eXBlcwogICAgICAgIFNjaGVtYUF0dHJpYnV0ZU1vZGVsSW1wbCBhdHRyTW9kZWwgPSBuZXcgU2NoZW1hQXR0cmlidXRlTW9kZWxJbXBsKCk7CiAgICAgICAgdHJhbnNsYXRlQXR0cmlidXRlTW9kZWwocGFyc2VUcmVlLCB0YXJnZXROYW1lc3BhY2UsIGNoYW1lbGVvbiwgYW5vbnltb3VzVHlwZXMsIHNJbXBsLCBudWxsLCBhdHRyTW9kZWwsIG51bGwsIHRydWUsIG51bGwpOwoKICAgICAgICAvLyBzdW1tYXJpemUgd2lsZGNhcmQgaW5mb3JtYXRpb24KICAgICAgICBXaWxkY2FyZFJlc3VsdCB3Y0VsdCA9IHN1bW1hcml6ZUVsdFdpbGRjYXJkcyhjb250ZW50TW9kZWwpOwogICAgICAgIFdpbGRjYXJkUmVzdWx0IHdjQXR0ciA9IHN1bW1hcml6ZUF0dHJXaWxkY2FyZHMoYXR0ck1vZGVsKTsKCiAgICAgICAgLy8gYnVpbGQgc3RhdGUgbWFjaGluZSBhbmQgdmVyaWZ5IHRoYXQgY29udGVudCBtb2RlbCBpcyBkZXRlcm1pbmlzdGljCiAgICAgICAgaWYgKGNvbnRlbnRNb2RlbCAhPSBudWxsKQogICAgICAgIHsKICAgICAgICAgICAgYnVpbGRTdGF0ZU1hY2hpbmUoY29udGVudE1vZGVsKTsKICAgICAgICAgICAgaWYgKCFTdHNjU3RhdGUuZ2V0KCkubm9VcGEoKSAmJiAhKChTY2hlbWFQYXJ0aWNsZUltcGwpY29udGVudE1vZGVsKS5pc0RldGVybWluaXN0aWMoKSkKICAgICAgICAgICAgICAgIFN0c2NTdGF0ZS5nZXQoKS5lcnJvcigiQ29udGVudCBtb2RlbCB2aW9sYXRlcyB0aGUgdW5pcXVlIHBhcnRpY2xlIGF0dHJpYnV0aW9uIHJ1bGUiLCBYbWxFcnJvckNvbnRleHQuTk9OREVURVJNSU5JU1RJQ19NT0RFTCwgcGFyc2VHcm91cCk7CiAgICAgICAgfQoKICAgICAgICAvLyBidWlsZCBwcm9wZXJ0eSBtb2RlbAogICAgICAgIC8vIGVtaXREQkcoIkJ1aWxkaW5nIGNvbnRlbnQgTW9kZWwgZm9yICIgKyBzSW1wbCk7CiAgICAgICAgTWFwIGVsZW1lbnRQcm9wZXJ0eU1vZGVsID0gYnVpbGRDb250ZW50UHJvcGVydHlNb2RlbEJ5UU5hbWUoY29udGVudE1vZGVsLCBzSW1wbCk7CgogICAgICAgIC8vIGFkZCBhdHRyaWJ1dGUgcHJvcGVydHkgbW9kZWwKICAgICAgICBNYXAgYXR0cmlidXRlUHJvcGVydHlNb2RlbCA9IGJ1aWxkQXR0cmlidXRlUHJvcGVydHlNb2RlbEJ5UU5hbWUoYXR0ck1vZGVsLCBzSW1wbCk7CgogICAgICAgIC8vIGZpZ3VyZSBvdXQgY29udGVudCB0eXBlCiAgICAgICAgaW50IGNvbXBsZXhWYXJpZXR5ID0KICAgICAgICAgICAgcGFyc2VUcmVlLmdldE1peGVkKCkKICAgICAgICAgICAgICAgID8gU2NoZW1hVHlwZS5NSVhFRF9DT05URU5UCiAgICAgICAgICAgICAgICA6IGNvbnRlbnRNb2RlbCA9PSBudWxsCiAgICAgICAgICAgICAgICAgICAgPyBTY2hlbWFUeXBlLkVNUFRZX0NPTlRFTlQKICAgICAgICAgICAgICAgICAgICA6IFNjaGVtYVR5cGUuRUxFTUVOVF9DT05URU5UOwoKICAgICAgICAvLyBub3cgZmlsbCBpbiB0aGUgYWN0dWFsIHNjaGVtYSB0eXBlIGltcGxlbWVudGF0aW9uCiAgICAgICAgc0ltcGwuc2V0QmFzZVR5cGVSZWYoQnVpbHRpblNjaGVtYVR5cGVTeXN0ZW0uU1RfQU5ZX1RZUEUuZ2V0UmVmKCkpOwogICAgICAgIHNJbXBsLnNldEJhc2VEZXB0aChCdWlsdGluU2NoZW1hVHlwZVN5c3RlbS5TVF9BTllfVFlQRS5nZXRCYXNlRGVwdGgoKSArIDEpOwogICAgICAgIHNJbXBsLnNldERlcml2YXRpb25UeXBlKFNjaGVtYVR5cGUuRFRfRVhURU5TSU9OKTsKICAgICAgICBzSW1wbC5zZXRDb21wbGV4VHlwZVZhcmlldHkoY29tcGxleFZhcmlldHkpOwogICAgICAgIHNJbXBsLnNldENvbnRlbnRNb2RlbChjb250ZW50TW9kZWwsIGF0dHJNb2RlbCwgZWxlbWVudFByb3BlcnR5TW9kZWwsIGF0dHJpYnV0ZVByb3BlcnR5TW9kZWwsIGlzQWxsKTsKICAgICAgICBzSW1wbC5zZXRBbm9ueW1vdXNUeXBlUmVmcyhtYWtlUmVmQXJyYXkoYW5vbnltb3VzVHlwZXMpKTsKICAgICAgICBzSW1wbC5zZXRXaWxkY2FyZFN1bW1hcnkod2NFbHQudHlwZWRXaWxkY2FyZHMsIHdjRWx0Lmhhc1dpbGRjYXJkcywgd2NBdHRyLnR5cGVkV2lsZGNhcmRzLCB3Y0F0dHIuaGFzV2lsZGNhcmRzKTsKICAgIH0KCiAgICBzdGF0aWMgdm9pZCByZXNvbHZlQ2NSZXN0cmljdGlvbihTY2hlbWFUeXBlSW1wbCBzSW1wbCwgQ29tcGxleFJlc3RyaWN0aW9uVHlwZSBwYXJzZVRyZWUsIGJvb2xlYW4gbWl4ZWQpCiAgICB7CiAgICAgICAgU3RzY1N0YXRlIHN0YXRlID0gU3RzY1N0YXRlLmdldCgpOwogICAgICAgIFN0cmluZyB0YXJnZXROYW1lc3BhY2UgPSBzSW1wbC5nZXRUYXJnZXROYW1lc3BhY2UoKTsKICAgICAgICBib29sZWFuIGNoYW1lbGVvbiA9IChzSW1wbC5nZXRDaGFtZWxlb25OYW1lc3BhY2UoKSAhPSBudWxsKTsKCiAgICAgICAgLy8gQlVHQlVHOiBOT1QgWUVUIFJFQUxMWSBJTVBMRU1FTlRFRAogICAgICAgIC8vIHRocm93IG5ldyBSdW50aW1lRXhjZXB0aW9uKCJOb3QgeWV0IGltcGxlbWVudGVkLiIpOwoKICAgICAgICBTY2hlbWFUeXBlIGJhc2VUeXBlOwogICAgICAgIGlmIChwYXJzZVRyZWUuZ2V0QmFzZSgpID09IG51bGwpCiAgICAgICAgewogICAgICAgICAgICBzdGF0ZS5lcnJvcigiQSBjb21wbGV4Q29udGVudCBtdXN0IGRlZmluZSBhIGJhc2UgdHlwZSIsIFhtbEVycm9yQ29udGV4dC5NSVNTSU5HX0JBU0UsIHBhcnNlVHJlZSk7CiAgICAgICAgICAgIGJhc2VUeXBlID0gbnVsbDsgLy8gcmVjb3Zlcnk6IG5vIGluaGVyaXRhbmNlLgogICAgICAgIH0KICAgICAgICBlbHNlCiAgICAgICAgewogICAgICAgICAgICBpZiAoc0ltcGwuaXNSZWRlZmluaXRpb24oKSkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgYmFzZVR5cGUgPSBzdGF0ZS5maW5kUmVkZWZpbmVkR2xvYmFsVHlwZShwYXJzZVRyZWUuZ2V0QmFzZSgpLCBzSW1wbC5nZXRDaGFtZWxlb25OYW1lc3BhY2UoKSwgc0ltcGwuZ2V0TmFtZSgpKTsKICAgICAgICAgICAgICAgIGlmIChiYXNlVHlwZSAhPSBudWxsICYmICFiYXNlVHlwZS5nZXROYW1lKCkuZXF1YWxzKHNJbXBsLmdldE5hbWUoKSkpCiAgICAgICAgICAgICAgICAgICAgc3RhdGUuZXJyb3IoIkEgdHlwZSByZWRlZmluaXRpb24gbXVzdCBleHRlbmQgdGhlIG9yaWdpbmFsIHR5cGUgZGVmaW5pdGlvbiIsIFhtbEVycm9yQ29udGV4dC5HRU5FUklDX0VSUk9SLCBwYXJzZVRyZWUpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgYmFzZVR5cGUgPSBzdGF0ZS5maW5kR2xvYmFsVHlwZShwYXJzZVRyZWUuZ2V0QmFzZSgpLCBzSW1wbC5nZXRDaGFtZWxlb25OYW1lc3BhY2UoKSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgCiAgICAgICAgICAgIGlmIChiYXNlVHlwZSA9PSBudWxsKQogICAgICAgICAgICAgICAgc3RhdGUubm90Rm91bmRFcnJvcihwYXJzZVRyZWUuZ2V0QmFzZSgpLCBYbWxFcnJvckNvbnRleHQuVFlQRV9OT1RfRk9VTkQsIHBhcnNlVHJlZS54Z2V0QmFzZSgpKTsKICAgICAgICB9CgogICAgICAgIGlmIChiYXNlVHlwZSA9PSBudWxsKQogICAgICAgICAgICBiYXNlVHlwZSA9IEJ1aWx0aW5TY2hlbWFUeXBlU3lzdGVtLlNUX0FOWV9UWVBFOwoKICAgICAgICBpZiAoYmFzZVR5cGUgIT0gbnVsbCAmJiBiYXNlVHlwZS5maW5hbFJlc3RyaWN0aW9uKCkpCiAgICAgICAgewogICAgICAgICAgICBzdGF0ZS5lcnJvcigiQ2Fubm90IHJlc3RyaWN0IGEgZmluYWwgdHlwZSIsIFhtbEVycm9yQ29udGV4dC5DQU5OT1RfREVSSVZFX0ZJTkFMLCBwYXJzZVRyZWUueGdldEJhc2UoKSk7CiAgICAgICAgICAgIC8vIHJlY292ZXJ5OiBqdXN0IGtlZXAgZ29pbmcKICAgICAgICB9CgogICAgICAgIC8vIFJlY3Vyc2lvbgogICAgICAgIGlmIChiYXNlVHlwZSAhPSBudWxsKQogICAgICAgIHsKICAgICAgICAgICAgaWYgKCFTdHNjUmVzb2x2ZXIucmVzb2x2ZVR5cGUoKFNjaGVtYVR5cGVJbXBsKWJhc2VUeXBlKSkKICAgICAgICAgICAgICAgIGJhc2VUeXBlID0gbnVsbDsgLy8gY2lyY3VsYXIgZGVwZW5kZW5jeTogbm8gaW5oZXJpdGFuY2UKICAgICAgICB9CgogICAgICAgIExpc3QgYW5vbnltb3VzVHlwZXMgPSBuZXcgQXJyYXlMaXN0KCk7CiAgICAgICAgR3JvdXAgcGFyc2VFZyA9IGdldENvbnRlbnRNb2RlbChwYXJzZVRyZWUpOwoKICAgICAgICAvLyBkZXRlY3QgdGhlICJhbGwiIGNhc2UKICAgICAgICBpbnQgcGFydGljbGVDb2RlID0gdHJhbnNsYXRlUGFydGljbGVDb2RlKHBhcnNlRWcpOwoKICAgICAgICAvLyB1c2VkIHRvIGVuc3VyZSBjb25zaXN0ZW5jeSAoZG9lc24ndCBiZWNvbWUgcGFydCBvZiB0aGUgcmVzdWx0KQogICAgICAgIE1hcCBlbGVtZW50TW9kZWwgPSBuZXcgTGlua2VkSGFzaE1hcCgpOwoKICAgICAgICAvLyBidWlsZCBjb250ZW50IG1vZGVsIGFuZCBhbm9ueW1vdXMgdHlwZXMKICAgICAgICBTY2hlbWFQYXJ0aWNsZSBjb250ZW50TW9kZWwgPSB0cmFuc2xhdGVDb250ZW50TW9kZWwoCiAgICAgICAgICAgIHNJbXBsLCBwYXJzZUVnLCB0YXJnZXROYW1lc3BhY2UsIGNoYW1lbGVvbiwgcGFydGljbGVDb2RlLCBhbm9ueW1vdXNUeXBlcywgZWxlbWVudE1vZGVsLCBmYWxzZSwgbnVsbCk7CgogICAgICAgIC8vIGRldGVjdCB0aGUgbm9uZW1wdHkgImFsbCIgY2FzZSAoZW1wdHkgPGFsbD4gZG9lc24ndCBjb3VudCAtIGl0IG5lZWRzIHRvIGJlIGVsaW1pbmF0ZWQgdG8gbWF0Y2ggWFNEIHRlc3QgY2FzZXMpCiAgICAgICAgYm9vbGVhbiBpc0FsbCA9IGNvbnRlbnRNb2RlbCAhPSBudWxsICYmIGNvbnRlbnRNb2RlbC5nZXRQYXJ0aWNsZVR5cGUoKSA9PSBTY2hlbWFQYXJ0aWNsZS5BTEw7CiAgICAgICAgCiAgICAgICAgLy8gYnVpbGQgYXR0ciBtb2RlbCBhbmQgYW5vbnltb3VzIHR5cGVzCiAgICAgICAgU2NoZW1hQXR0cmlidXRlTW9kZWxJbXBsIGF0dHJNb2RlbDsKICAgICAgICBpZiAoYmFzZVR5cGUgPT0gbnVsbCkKICAgICAgICAgICAgYXR0ck1vZGVsID0gbmV3IFNjaGVtYUF0dHJpYnV0ZU1vZGVsSW1wbCgpOwogICAgICAgIGVsc2UKICAgICAgICAgICAgYXR0ck1vZGVsID0gbmV3IFNjaGVtYUF0dHJpYnV0ZU1vZGVsSW1wbChiYXNlVHlwZS5nZXRBdHRyaWJ1dGVNb2RlbCgpKTsKICAgICAgICB0cmFuc2xhdGVBdHRyaWJ1dGVNb2RlbChwYXJzZVRyZWUsIHRhcmdldE5hbWVzcGFjZSwgY2hhbWVsZW9uLCBhbm9ueW1vdXNUeXBlcywgc0ltcGwsIG51bGwsIGF0dHJNb2RlbCwgYmFzZVR5cGUsIGZhbHNlLCBudWxsKTsKCiAgICAgICAgLy8gc3VtbWFyaXplIHdpbGRjYXJkIGluZm9ybWF0aW9uCiAgICAgICAgV2lsZGNhcmRSZXN1bHQgd2NFbHQgPSBzdW1tYXJpemVFbHRXaWxkY2FyZHMoY29udGVudE1vZGVsKTsKICAgICAgICBXaWxkY2FyZFJlc3VsdCB3Y0F0dHIgPSBzdW1tYXJpemVBdHRyV2lsZGNhcmRzKGF0dHJNb2RlbCk7CgogICAgICAgIC8vIGJ1aWxkIHN0YXRlIG1hY2hpbmUgYW5kIHZlcmlmeSB0aGF0IGNvbnRlbnQgbW9kZWwgaXMgZGV0ZXJtaW5pc3RpYwogICAgICAgIGlmIChjb250ZW50TW9kZWwgIT0gbnVsbCkKICAgICAgICB7CiAgICAgICAgICAgIGJ1aWxkU3RhdGVNYWNoaW5lKGNvbnRlbnRNb2RlbCk7CiAgICAgICAgICAgIGlmICghU3RzY1N0YXRlLmdldCgpLm5vVXBhKCkgJiYgISgoU2NoZW1hUGFydGljbGVJbXBsKWNvbnRlbnRNb2RlbCkuaXNEZXRlcm1pbmlzdGljKCkpCiAgICAgICAgICAgICAgICBTdHNjU3RhdGUuZ2V0KCkuZXJyb3IoIkNvbnRlbnQgbW9kZWwgdmlvbGF0ZXMgdGhlIHVuaXF1ZSBwYXJ0aWNsZSBhdHRyaWJ1dGlvbiBydWxlIiwgWG1sRXJyb3JDb250ZXh0Lk5PTkRFVEVSTUlOSVNUSUNfTU9ERUwsIHBhcnNlRWcpOwogICAgICAgIH0KCiAgICAgICAgLy8gYnVpbGQgcHJvcGVydHkgbW9kZWwKICAgICAgICAvLyBlbWl0REJHKCJCdWlsZGluZyBjb250ZW50IE1vZGVsIGZvciAiICsgc0ltcGwpOwogICAgICAgIE1hcCBlbGVtZW50UHJvcGVydHlNb2RlbCA9IGJ1aWxkQ29udGVudFByb3BlcnR5TW9kZWxCeVFOYW1lKGNvbnRlbnRNb2RlbCwgc0ltcGwpOwoKICAgICAgICAvLyBhZGQgYXR0cmlidXRlIHByb3BlcnR5IG1vZGVsCiAgICAgICAgTWFwIGF0dHJpYnV0ZVByb3BlcnR5TW9kZWwgPSBidWlsZEF0dHJpYnV0ZVByb3BlcnR5TW9kZWxCeVFOYW1lKGF0dHJNb2RlbCwgc0ltcGwpOwoKICAgICAgICAvLyBjb21wdXRlIGVtcHR5L2VsZW1lbnQvbWl4ZWQKICAgICAgICBpbnQgY29tcGxleFZhcmlldHkgPSAoY29udGVudE1vZGVsID09IG51bGwgPyBTY2hlbWFUeXBlLkVNUFRZX0NPTlRFTlQgOgogICAgICAgICAgICAobWl4ZWQgPyBTY2hlbWFUeXBlLk1JWEVEX0NPTlRFTlQgOiBTY2hlbWFUeXBlLkVMRU1FTlRfQ09OVEVOVCkpOwoKICAgICAgICAvLyBub3cgZmlsbCBpbiB0aGUgYWN0dWFsIHNjaGVtYSB0eXBlIGltcGxlbWVudGF0aW9uCiAgICAgICAgc0ltcGwuc2V0QmFzZVR5cGVSZWYoYmFzZVR5cGUuZ2V0UmVmKCkpOwogICAgICAgIHNJbXBsLnNldEJhc2VEZXB0aCgoKFNjaGVtYVR5cGVJbXBsKWJhc2VUeXBlKS5nZXRCYXNlRGVwdGgoKSArIDEpOwogICAgICAgIHNJbXBsLnNldERlcml2YXRpb25UeXBlKFNjaGVtYVR5cGUuRFRfUkVTVFJJQ1RJT04pOwogICAgICAgIHNJbXBsLnNldENvbXBsZXhUeXBlVmFyaWV0eShjb21wbGV4VmFyaWV0eSk7CiAgICAgICAgc0ltcGwuc2V0Q29udGVudE1vZGVsKGNvbnRlbnRNb2RlbCwgYXR0ck1vZGVsLCBlbGVtZW50UHJvcGVydHlNb2RlbCwgYXR0cmlidXRlUHJvcGVydHlNb2RlbCwgaXNBbGwpOwogICAgICAgIHNJbXBsLnNldEFub255bW91c1R5cGVSZWZzKG1ha2VSZWZBcnJheShhbm9ueW1vdXNUeXBlcykpOwogICAgICAgIHNJbXBsLnNldFdpbGRjYXJkU3VtbWFyeSh3Y0VsdC50eXBlZFdpbGRjYXJkcywgd2NFbHQuaGFzV2lsZGNhcmRzLCB3Y0F0dHIudHlwZWRXaWxkY2FyZHMsIHdjQXR0ci5oYXNXaWxkY2FyZHMpOwogICAgfQoKICAgIHN0YXRpYyBNYXAgZXh0cmFjdEVsZW1lbnRNb2RlbChTY2hlbWFUeXBlIHNUeXBlKQogICAgewogICAgICAgIE1hcCBlbGVtZW50TW9kZWwgPSBuZXcgSGFzaE1hcCgpOwogICAgICAgIGlmIChzVHlwZSAhPSBudWxsKQogICAgICAgIHsKICAgICAgICAgICAgU2NoZW1hUHJvcGVydHlbXSBzUHJvcHMgPSBzVHlwZS5nZXRQcm9wZXJ0aWVzKCk7CiAgICAgICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgc1Byb3BzLmxlbmd0aDsgaSsrKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBpZiAoc1Byb3BzW2ldLmlzQXR0cmlidXRlKCkpCiAgICAgICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgICAgICBlbGVtZW50TW9kZWwucHV0KHNQcm9wc1tpXS5nZXROYW1lKCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNQcm9wc1tpXS5nZXRUeXBlKCkpOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHJldHVybiBlbGVtZW50TW9kZWw7CiAgICB9CgogICAgc3RhdGljIHZvaWQgcmVzb2x2ZUNjRXh0ZW5zaW9uKFNjaGVtYVR5cGVJbXBsIHNJbXBsLCBFeHRlbnNpb25UeXBlIHBhcnNlVHJlZSwgYm9vbGVhbiBtaXhlZCkKICAgIHsKICAgICAgICBTY2hlbWFUeXBlIGJhc2VUeXBlOwogICAgICAgIFN0c2NTdGF0ZSBzdGF0ZSA9IFN0c2NTdGF0ZS5nZXQoKTsKICAgICAgICBTdHJpbmcgdGFyZ2V0TmFtZXNwYWNlID0gc0ltcGwuZ2V0VGFyZ2V0TmFtZXNwYWNlKCk7CiAgICAgICAgYm9vbGVhbiBjaGFtZWxlb24gPSAoc0ltcGwuZ2V0Q2hhbWVsZW9uTmFtZXNwYWNlKCkgIT0gbnVsbCk7CgogICAgICAgIGlmIChwYXJzZVRyZWUuZ2V0QmFzZSgpID09IG51bGwpCiAgICAgICAgewogICAgICAgICAgICBzdGF0ZS5lcnJvcigiQSBjb21wbGV4Q29udGVudCBtdXN0IGRlZmluZSBhIGJhc2UgdHlwZSIsIFhtbEVycm9yQ29udGV4dC5NSVNTSU5HX0JBU0UsIHBhcnNlVHJlZSk7CiAgICAgICAgICAgIGJhc2VUeXBlID0gbnVsbDsgLy8gcmVjb3Zlcnk6IG5vIGluaGVyaXRhbmNlLgogICAgICAgIH0KICAgICAgICBlbHNlCiAgICAgICAgewogICAgICAgICAgICBpZiAoc0ltcGwuaXNSZWRlZmluaXRpb24oKSkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgYmFzZVR5cGUgPSBzdGF0ZS5maW5kUmVkZWZpbmVkR2xvYmFsVHlwZShwYXJzZVRyZWUuZ2V0QmFzZSgpLCBzSW1wbC5nZXRDaGFtZWxlb25OYW1lc3BhY2UoKSwgc0ltcGwuZ2V0TmFtZSgpKTsKICAgICAgICAgICAgICAgIGlmIChiYXNlVHlwZSAhPSBudWxsICYmICFiYXNlVHlwZS5nZXROYW1lKCkuZXF1YWxzKHNJbXBsLmdldE5hbWUoKSkpCiAgICAgICAgICAgICAgICAgICAgc3RhdGUuZXJyb3IoIkEgdHlwZSByZWRlZmluaXRpb24gbXVzdCBleHRlbmQgdGhlIG9yaWdpbmFsIHR5cGUgZGVmaW5pdGlvbiIsIFhtbEVycm9yQ29udGV4dC5HRU5FUklDX0VSUk9SLCBwYXJzZVRyZWUpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgYmFzZVR5cGUgPSBzdGF0ZS5maW5kR2xvYmFsVHlwZShwYXJzZVRyZWUuZ2V0QmFzZSgpLCBzSW1wbC5nZXRDaGFtZWxlb25OYW1lc3BhY2UoKSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKGJhc2VUeXBlID09IG51bGwpCiAgICAgICAgICAgICAgICBzdGF0ZS5ub3RGb3VuZEVycm9yKHBhcnNlVHJlZS5nZXRCYXNlKCksIFhtbEVycm9yQ29udGV4dC5UWVBFX05PVF9GT1VORCwgcGFyc2VUcmVlLnhnZXRCYXNlKCkpOwogICAgICAgIH0KCiAgICAgICAgLy8gUmVjdXJzaW9uCiAgICAgICAgaWYgKGJhc2VUeXBlICE9IG51bGwpCiAgICAgICAgewogICAgICAgICAgICBpZiAoIVN0c2NSZXNvbHZlci5yZXNvbHZlVHlwZSgoU2NoZW1hVHlwZUltcGwpYmFzZVR5cGUpKQogICAgICAgICAgICAgICAgYmFzZVR5cGUgPSBudWxsOyAvLyBjaXJjdWxhciBkZXBlbmRlbmN5OiBubyBpbmhlcml0YW5jZQogICAgICAgIH0KCiAgICAgICAgaWYgKGJhc2VUeXBlICE9IG51bGwgJiYgKGJhc2VUeXBlLmlzU2ltcGxlVHlwZSgpIHx8IGJhc2VUeXBlLmdldENvbnRlbnRUeXBlKCkgPT0gU2NoZW1hVHlwZS5TSU1QTEVfQ09OVEVOVCkpCiAgICAgICAgewogICAgICAgICAgICBzdGF0ZS5lcnJvcigiVGhlIHNwZWNpZmllZCBiYXNlIHR5cGUgaXMgbm90IGEgY29tcGxleCB0eXBlIHdpdGggY29tcGxleCBjb250ZW50LiIsIFhtbEVycm9yQ29udGV4dC5DT01QTEVYX0JBU0VfTk9UX0NPTVBMRVgsIHBhcnNlVHJlZS54Z2V0QmFzZSgpKTsKICAgICAgICAgICAgYmFzZVR5cGUgPSBudWxsOyAvLyByZWNvdmVyeTogbm8gaW5oZXJpdGFuY2UuCiAgICAgICAgfQoKICAgICAgICBpZiAoYmFzZVR5cGUgIT0gbnVsbCAmJiBiYXNlVHlwZS5maW5hbEV4dGVuc2lvbigpKQogICAgICAgIHsKICAgICAgICAgICAgc3RhdGUuZXJyb3IoIkNhbm5vdCBleHRlbmQgYSBmaW5hbCB0eXBlIiwgWG1sRXJyb3JDb250ZXh0LkNBTk5PVF9ERVJJVkVfRklOQUwsIHBhcnNlVHJlZS54Z2V0QmFzZSgpKTsKICAgICAgICAgICAgLy8gcmVjb3Zlcnk6IGp1c3Qga2VlcCBnb2luZwogICAgICAgIH0KICAgICAgICAKICAgICAgICAvLyBnZXQgYmFzZSBjb250ZW50IG1vZGVsCiAgICAgICAgU2NoZW1hUGFydGljbGUgYmFzZUNvbnRlbnRNb2RlbCA9IChiYXNlVHlwZSA9PSBudWxsID8gbnVsbCA6IGJhc2VUeXBlLmdldENvbnRlbnRNb2RlbCgpKTsKICAgICAgICAvLyBUT0RPOiBhdHRyaWJ1dGUgbW9kZWwgYWxzbwoKICAgICAgICBMaXN0IGFub255bW91c1R5cGVzID0gbmV3IEFycmF5TGlzdCgpOwogICAgICAgIE1hcCBiYXNlRWxlbWVudE1vZGVsID0gZXh0cmFjdEVsZW1lbnRNb2RlbChiYXNlVHlwZSk7CiAgICAgICAgR3JvdXAgcGFyc2VFZyA9IGdldENvbnRlbnRNb2RlbChwYXJzZVRyZWUpOwogICAgICAgIAogICAgICAgIC8vIGJ1aWxkIGV4dGVuc2lvbiBtb2RlbAogICAgICAgIFNjaGVtYVBhcnRpY2xlIGV4dGVuc2lvbk1vZGVsID0gdHJhbnNsYXRlQ29udGVudE1vZGVsKAogICAgICAgICAgICAgICAgc0ltcGwsIHBhcnNlRWcsIHRhcmdldE5hbWVzcGFjZSwgY2hhbWVsZW9uLCB0cmFuc2xhdGVQYXJ0aWNsZUNvZGUocGFyc2VFZyksCiAgICAgICAgICAgICAgICBhbm9ueW1vdXNUeXBlcywgYmFzZUVsZW1lbnRNb2RlbCwgZmFsc2UsIG51bGwpOwogICAgICAgIAogICAgICAgIC8vIGFwcGx5IHJ1bGUgIzIgbmVhciBodHRwOi8vd3d3LnczLm9yZy9UUi94bWxzY2hlbWEtMS8jYy1tdmU6IGVtcHR5IGV4dCBtb2RlbCAtPiBtaXhlZCB0YWtlbiBmcm9tIGJhc2UKICAgICAgICBpZiAoZXh0ZW5zaW9uTW9kZWwgPT0gbnVsbCAmJiAhbWl4ZWQpCiAgICAgICAgICAgIG1peGVkID0gKGJhc2VUeXBlLmdldENvbnRlbnRUeXBlKCkgPT0gU2NoZW1hVHlwZS5NSVhFRF9DT05URU5UKTsKICAgICAgICAKICAgICAgICAvLyBhcHBseSBEZXJpdmF0aW9uIFZhbGlkIChFeHRlbnNpb24pIHJ1bGUgMS40LjIuMgogICAgICAgIGlmIChiYXNlVHlwZSAhPSBudWxsICYmIChiYXNlVHlwZS5nZXRDb250ZW50VHlwZSgpICE9IFNjaGVtYVR5cGUuRU1QVFlfQ09OVEVOVCkgJiYKICAgICAgICAgICAgICAgICgoYmFzZVR5cGUuZ2V0Q29udGVudFR5cGUoKSA9PSBTY2hlbWFUeXBlLk1JWEVEX0NPTlRFTlQpICE9IG1peGVkKSkKICAgICAgICB7CiAgICAgICAgICAgIHN0YXRlLmVycm9yKCJDYW5ub3QgZXh0ZW5kIGFuIGVsZW1lbnQtb25seSB0eXBlIHdpdGggYSBtaXhlZCB0eXBlIG9yIHZpY2UtdmVyc2EiLCBYbWxFcnJvckNvbnRleHQuSU5DT05TSVNURU5UX1RZUEUsIHBhcnNlVHJlZS54Z2V0QmFzZSgpKTsKICAgICAgICAgICAgLy8gcmVjb3Zlcnk6IGp1c3Qga2VlcCBnb2luZwogICAgICAgIH0KCiAgICAgICAgLy8gZGV0ZWN0IHRoZSAiYWxsIiBiYXNlIGNhc2UKICAgICAgICBpZiAoYmFzZVR5cGUgIT0gbnVsbCAmJiBiYXNlVHlwZS5oYXNBbGxDb250ZW50KCkgJiYgZXh0ZW5zaW9uTW9kZWwgIT0gbnVsbCkKICAgICAgICB7CiAgICAgICAgICAgIHN0YXRlLmVycm9yKCJDYW5ub3QgZXh0ZW5kIGEgdHlwZSB3aXRoICdhbGwnIGNvbnRlbnQgbW9kZWwiLCBYbWxFcnJvckNvbnRleHQuQ0FOTk9UX0VYVEVORF9BTEwsIHBhcnNlVHJlZS54Z2V0QmFzZSgpKTsKICAgICAgICAgICAgZXh0ZW5zaW9uTW9kZWwgPSBudWxsOyAvLyByZWNvdmVyeTogZHJvcCBleHRlbnNpb24KICAgICAgICB9CgogICAgICAgIC8vIGJ1aWxkIGNvbnRlbnQgbW9kZWwgYW5kIGFub255bW91cyB0eXBlcwogICAgICAgIFNjaGVtYVBhcnRpY2xlIGNvbnRlbnRNb2RlbCA9IGV4dGVuZENvbnRlbnRNb2RlbChiYXNlQ29udGVudE1vZGVsLCBleHRlbnNpb25Nb2RlbCwgcGFyc2VUcmVlKTsKCiAgICAgICAgLy8gZGV0ZWN0IHRoZSBub25lbXB0eSAiYWxsIiBjYXNlIChlbXB0eSA8YWxsPiBkb2Vzbid0IGNvdW50IC0gaXQgbmVlZHMgdG8gYmUgZWxpbWluYXRlZCB0byBtYXRjaCBYU0QgdGVzdCBjYXNlcykKICAgICAgICBib29sZWFuIGlzQWxsID0gY29udGVudE1vZGVsICE9IG51bGwgJiYgY29udGVudE1vZGVsLmdldFBhcnRpY2xlVHlwZSgpID09IFNjaGVtYVBhcnRpY2xlLkFMTDsKICAgICAgICAKICAgICAgICAvLyBidWlsZCBhdHRyIG1vZGVsIGFuZCBhbm9ueW1vdXMgdHlwZXMKICAgICAgICBTY2hlbWFBdHRyaWJ1dGVNb2RlbEltcGwgYXR0ck1vZGVsOwogICAgICAgIGlmIChiYXNlVHlwZSA9PSBudWxsKQogICAgICAgICAgICBhdHRyTW9kZWwgPSBuZXcgU2NoZW1hQXR0cmlidXRlTW9kZWxJbXBsKCk7CiAgICAgICAgZWxzZQogICAgICAgICAgICBhdHRyTW9kZWwgPSBuZXcgU2NoZW1hQXR0cmlidXRlTW9kZWxJbXBsKGJhc2VUeXBlLmdldEF0dHJpYnV0ZU1vZGVsKCkpOwogICAgICAgIHRyYW5zbGF0ZUF0dHJpYnV0ZU1vZGVsKHBhcnNlVHJlZSwgdGFyZ2V0TmFtZXNwYWNlLCBjaGFtZWxlb24sIGFub255bW91c1R5cGVzLCBzSW1wbCwgbnVsbCwgYXR0ck1vZGVsLCBiYXNlVHlwZSwgdHJ1ZSwgbnVsbCk7CgogICAgICAgIC8vIHN1bW1hcml6ZSB3aWxkY2FyZCBpbmZvcm1hdGlvbgogICAgICAgIFdpbGRjYXJkUmVzdWx0IHdjRWx0ID0gc3VtbWFyaXplRWx0V2lsZGNhcmRzKGNvbnRlbnRNb2RlbCk7CiAgICAgICAgV2lsZGNhcmRSZXN1bHQgd2NBdHRyID0gc3VtbWFyaXplQXR0cldpbGRjYXJkcyhhdHRyTW9kZWwpOwoKICAgICAgICAvLyBidWlsZCBzdGF0ZSBtYWNoaW5lIGFuZCB2ZXJpZnkgdGhhdCBjb250ZW50IG1vZGVsIGlzIGRldGVybWluaXN0aWMKICAgICAgICBpZiAoY29udGVudE1vZGVsICE9IG51bGwpCiAgICAgICAgewogICAgICAgICAgICBidWlsZFN0YXRlTWFjaGluZShjb250ZW50TW9kZWwpOwogICAgICAgICAgICBpZiAoIVN0c2NTdGF0ZS5nZXQoKS5ub1VwYSgpICYmICEoKFNjaGVtYVBhcnRpY2xlSW1wbCljb250ZW50TW9kZWwpLmlzRGV0ZXJtaW5pc3RpYygpKQogICAgICAgICAgICAgICAgU3RzY1N0YXRlLmdldCgpLmVycm9yKCJDb250ZW50IG1vZGVsIHZpb2xhdGVzIHRoZSB1bmlxdWUgcGFydGljbGUgYXR0cmlidXRpb24gcnVsZSIsIFhtbEVycm9yQ29udGV4dC5OT05ERVRFUk1JTklTVElDX01PREVMLCBwYXJzZUVnKTsKICAgICAgICB9CgogICAgICAgIC8vIGJ1aWxkIHByb3BlcnR5IG1vZGVsCiAgICAgICAgLy8gZW1pdERCRygiQnVpbGRpbmcgY29udGVudCBNb2RlbCBmb3IgIiArIHNJbXBsKTsKICAgICAgICBNYXAgZWxlbWVudFByb3BlcnR5TW9kZWwgPSBidWlsZENvbnRlbnRQcm9wZXJ0eU1vZGVsQnlRTmFtZShjb250ZW50TW9kZWwsIHNJbXBsKTsKCiAgICAgICAgLy8gYWRkIGF0dHJpYnV0ZSBwcm9wZXJ0eSBtb2RlbAogICAgICAgIE1hcCBhdHRyaWJ1dGVQcm9wZXJ0eU1vZGVsID0gYnVpbGRBdHRyaWJ1dGVQcm9wZXJ0eU1vZGVsQnlRTmFtZShhdHRyTW9kZWwsIHNJbXBsKTsKCiAgICAgICAgLy8gY29tcHV0ZSBlbXB0eS9lbGVtZW50L21peGVkCiAgICAgICAgaW50IGNvbXBsZXhWYXJpZXR5ID0gICggbWl4ZWQgPyBTY2hlbWFUeXBlLk1JWEVEX0NPTlRFTlQgOgogICAgICAgICAgICAoY29udGVudE1vZGVsID09IG51bGwgPyBTY2hlbWFUeXBlLkVNUFRZX0NPTlRFTlQgOiBTY2hlbWFUeXBlLkVMRU1FTlRfQ09OVEVOVCkpOwoKICAgICAgICAvLyBub3cgZmlsbCBpbiB0aGUgYWN0dWFsIHNjaGVtYSB0eXBlIGltcGxlbWVudGF0aW9uCiAgICAgICAgaWYgKGJhc2VUeXBlID09IG51bGwpCiAgICAgICAgICAgIGJhc2VUeXBlID0gWG1sT2JqZWN0LnR5cGU7CiAgICAgICAgc0ltcGwuc2V0QmFzZVR5cGVSZWYoYmFzZVR5cGUuZ2V0UmVmKCkpOwogICAgICAgIHNJbXBsLnNldEJhc2VEZXB0aCgoKFNjaGVtYVR5cGVJbXBsKWJhc2VUeXBlKS5nZXRCYXNlRGVwdGgoKSArIDEpOwogICAgICAgIHNJbXBsLnNldERlcml2YXRpb25UeXBlKFNjaGVtYVR5cGUuRFRfRVhURU5TSU9OKTsKICAgICAgICBzSW1wbC5zZXRDb21wbGV4VHlwZVZhcmlldHkoY29tcGxleFZhcmlldHkpOwogICAgICAgIHNJbXBsLnNldENvbnRlbnRNb2RlbChjb250ZW50TW9kZWwsIGF0dHJNb2RlbCwgZWxlbWVudFByb3BlcnR5TW9kZWwsIGF0dHJpYnV0ZVByb3BlcnR5TW9kZWwsIGlzQWxsKTsKICAgICAgICBzSW1wbC5zZXRBbm9ueW1vdXNUeXBlUmVmcyhtYWtlUmVmQXJyYXkoYW5vbnltb3VzVHlwZXMpKTsKICAgICAgICBzSW1wbC5zZXRXaWxkY2FyZFN1bW1hcnkod2NFbHQudHlwZWRXaWxkY2FyZHMsIHdjRWx0Lmhhc1dpbGRjYXJkcywgd2NBdHRyLnR5cGVkV2lsZGNhcmRzLCB3Y0F0dHIuaGFzV2lsZGNhcmRzKTsKICAgIH0KCiAgICBzdGF0aWMgdm9pZCByZXNvbHZlU2NSZXN0cmljdGlvbihTY2hlbWFUeXBlSW1wbCBzSW1wbCwgU2ltcGxlUmVzdHJpY3Rpb25UeXBlIHBhcnNlVHJlZSkKICAgIHsKICAgICAgICBTY2hlbWFUeXBlIGJhc2VUeXBlOwogICAgICAgIFN0c2NTdGF0ZSBzdGF0ZSA9IFN0c2NTdGF0ZS5nZXQoKTsKICAgICAgICBTdHJpbmcgdGFyZ2V0TmFtZXNwYWNlID0gc0ltcGwuZ2V0VGFyZ2V0TmFtZXNwYWNlKCk7CiAgICAgICAgYm9vbGVhbiBjaGFtZWxlb24gPSAoc0ltcGwuZ2V0Q2hhbWVsZW9uTmFtZXNwYWNlKCkgIT0gbnVsbCk7CiAgICAgICAgaWYgKHBhcnNlVHJlZS5nZXRTaW1wbGVUeXBlKCkgIT0gbnVsbCkKICAgICAgICB7CiAgICAgICAgICAgIHN0YXRlLndhcm5pbmcoIk5lc3RlZCBzaW1wbGUgdHlwZXMgaW5zaWRlIHNpbXBsZSBjb250ZW50IHJlc3RyaWN0aW9ucyBhcmUgdW5zdXBwb3J0ZWQgLSBpZ25vcmluZyIsIFhtbEVycm9yQ29udGV4dC5JTExFR0FMX1JFU1RSSUNUSU9OLCBwYXJzZVRyZWUpOwogICAgICAgICAgICAvLyByZWNvdmVyeTogaWdub3JlIHRoZSBuZXN0ZWQgc2ltcGxlIHR5cGUgZWxlbWVudC4KICAgICAgICB9CiAgICAgICAgaWYgKHBhcnNlVHJlZS5nZXRCYXNlKCkgPT0gbnVsbCkKICAgICAgICB7CiAgICAgICAgICAgIHN0YXRlLmVycm9yKCJBIHNpbXBsZUNvbnRlbnQgcmVzdHJpY3Rpb24gbXVzdCBkZWZpbmUgYSBiYXNlIHR5cGUiLCBYbWxFcnJvckNvbnRleHQuTUlTU0lOR19CQVNFLCBwYXJzZVRyZWUpOwogICAgICAgICAgICAvLyByZWNvdmVyeTogZXh0ZW5kcyBBTllfU0lNUExFIHR5cGUKICAgICAgICAgICAgYmFzZVR5cGUgPSBCdWlsdGluU2NoZW1hVHlwZVN5c3RlbS5TVF9BTllfU0lNUExFOwogICAgICAgIH0KICAgICAgICBlbHNlCiAgICAgICAgewogICAgICAgICAgICBpZiAoc0ltcGwuaXNSZWRlZmluaXRpb24oKSkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgYmFzZVR5cGUgPSBzdGF0ZS5maW5kUmVkZWZpbmVkR2xvYmFsVHlwZShwYXJzZVRyZWUuZ2V0QmFzZSgpLCBzSW1wbC5nZXRDaGFtZWxlb25OYW1lc3BhY2UoKSwgc0ltcGwuZ2V0TmFtZSgpKTsKICAgICAgICAgICAgICAgIGlmIChiYXNlVHlwZSAhPSBudWxsICYmICFiYXNlVHlwZS5nZXROYW1lKCkuZXF1YWxzKHNJbXBsLmdldE5hbWUoKSkpCiAgICAgICAgICAgICAgICAgICAgc3RhdGUuZXJyb3IoIkEgdHlwZSByZWRlZmluaXRpb24gbXVzdCByZXN0cmljdCB0aGUgb3JpZ2luYWwgdHlwZSBkZWZpbml0aW9uIiwgWG1sRXJyb3JDb250ZXh0LkdFTkVSSUNfRVJST1IsIHBhcnNlVHJlZSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBiYXNlVHlwZSA9IHN0YXRlLmZpbmRHbG9iYWxUeXBlKHBhcnNlVHJlZS5nZXRCYXNlKCksIHNJbXBsLmdldENoYW1lbGVvbk5hbWVzcGFjZSgpKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAoYmFzZVR5cGUgPT0gbnVsbCkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgc3RhdGUubm90Rm91bmRFcnJvcihwYXJzZVRyZWUuZ2V0QmFzZSgpLCBYbWxFcnJvckNvbnRleHQuVFlQRV9OT1RfRk9VTkQsIHBhcnNlVHJlZS54Z2V0QmFzZSgpKTsKICAgICAgICAgICAgICAgIC8vIHJlY292ZXJ5OiBleHRlbmRzIEFOWV9TSU1QTEUgdHlwZQogICAgICAgICAgICAgICAgYmFzZVR5cGUgPSBCdWlsdGluU2NoZW1hVHlwZVN5c3RlbS5TVF9BTllfU0lNUExFOwogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICAvLyBSZWN1cnNpb24KICAgICAgICBTdHNjUmVzb2x2ZXIucmVzb2x2ZVR5cGUoKFNjaGVtYVR5cGVJbXBsKWJhc2VUeXBlKTsKCiAgICAgICAgaWYgKGJhc2VUeXBlLmlzU2ltcGxlVHlwZSgpKQogICAgICAgIHsKICAgICAgICAgICAgc3RhdGUuZXJyb3IoIlNpbXBsZSB0eXBlICciICsgYmFzZVR5cGUuZ2V0TmFtZSgpICsgIicgY2Fubm90IGJlIHVzZWQgYXMgdGhlIGJhc2UgdHlwZSBvZiBhIHNpbXBsZSBjb250ZW50IHJlc3RyaWN0aW9uLiAoVXNlIGV4dGVuc2lvbiBpbnN0ZWFkLikiLCBYbWxFcnJvckNvbnRleHQuU0lNUExFX0JBU0VfTk9UX1NJTVBMRSwgcGFyc2VUcmVlKTsKICAgICAgICAgICAgLy8gcmVjb3Zlcnk6IGV4dGVuZHMgQU5ZX1NJTVBMRSB0eXBlCiAgICAgICAgICAgIGJhc2VUeXBlID0gQnVpbHRpblNjaGVtYVR5cGVTeXN0ZW0uU1RfQU5ZX1NJTVBMRTsKICAgICAgICB9CiAgICAgICAgLy8gQlVHQlVHOiBjYW4gcmVzdHJpY3QgbWl4ZWQgY29udGVudCBhcyBsb25nIGFzIGFsbCBjaGlsZCBlbGVtZW50cyBhcmUgb3B0aW9uYWwKICAgICAgICBlbHNlIGlmIChiYXNlVHlwZS5nZXRDb250ZW50VHlwZSgpICE9IFNjaGVtYVR5cGUuU0lNUExFX0NPTlRFTlQpCiAgICAgICAgewogICAgICAgICAgICBzdGF0ZS5lcnJvcigiVGhlIHNwZWNpZmllZCBiYXNlIHR5cGUgIiArIGJhc2VUeXBlLnRvU3RyaW5nKCkgKyAiIGRvZXMgbm90IGhhdmUgc2ltcGxlIGNvbnRlbnQuIiwgWG1sRXJyb3JDb250ZXh0LlNJTVBMRV9CQVNFX05PVF9TSU1QTEUsIHBhcnNlVHJlZSk7CiAgICAgICAgICAgIC8vIHJlY292ZXJ5OiBleHRlbmRzIEFOWV9TSU1QTEUgdHlwZQogICAgICAgICAgICBiYXNlVHlwZSA9IEJ1aWx0aW5TY2hlbWFUeXBlU3lzdGVtLlNUX0FOWV9TSU1QTEU7CiAgICAgICAgfQoKICAgICAgICBpZiAoYmFzZVR5cGUgIT0gbnVsbCAmJiBiYXNlVHlwZS5maW5hbFJlc3RyaWN0aW9uKCkpCiAgICAgICAgewogICAgICAgICAgICBzdGF0ZS5lcnJvcigiQ2Fubm90IHJlc3RyaWN0IGEgZmluYWwgdHlwZSIsIFhtbEVycm9yQ29udGV4dC5DQU5OT1RfREVSSVZFX0ZJTkFMLCBwYXJzZVRyZWUueGdldEJhc2UoKSk7CiAgICAgICAgICAgIC8vIHJlY292ZXJ5OiBqdXN0IGtlZXAgZ29pbmcKICAgICAgICB9CgogICAgICAgIC8vIGJ1aWxkIGF0dHIgbW9kZWwgYW5kIGFub255bW91cyB0eXBlcwogICAgICAgIExpc3QgYW5vbnltb3VzVHlwZXMgPSBuZXcgQXJyYXlMaXN0KCk7CiAgICAgICAgU2NoZW1hQXR0cmlidXRlTW9kZWxJbXBsIGF0dHJNb2RlbDsKICAgICAgICBpZiAoYmFzZVR5cGUgPT0gbnVsbCkKICAgICAgICAgICAgYXR0ck1vZGVsID0gbmV3IFNjaGVtYUF0dHJpYnV0ZU1vZGVsSW1wbCgpOwogICAgICAgIGVsc2UKICAgICAgICAgICAgYXR0ck1vZGVsID0gbmV3IFNjaGVtYUF0dHJpYnV0ZU1vZGVsSW1wbChiYXNlVHlwZS5nZXRBdHRyaWJ1dGVNb2RlbCgpKTsKICAgICAgICB0cmFuc2xhdGVBdHRyaWJ1dGVNb2RlbChwYXJzZVRyZWUsIHRhcmdldE5hbWVzcGFjZSwgY2hhbWVsZW9uLCBhbm9ueW1vdXNUeXBlcywgc0ltcGwsIG51bGwsIGF0dHJNb2RlbCwgYmFzZVR5cGUsIGZhbHNlLCBudWxsKTsKCiAgICAgICAgLy8gc3VtbWFyaXplIHdpbGRjYXJkIGluZm9ybWF0aW9uCiAgICAgICAgV2lsZGNhcmRSZXN1bHQgd2NBdHRyID0gc3VtbWFyaXplQXR0cldpbGRjYXJkcyhhdHRyTW9kZWwpOwoKICAgICAgICAvLyBhZGQgYXR0cmlidXRlIHByb3BlcnR5IG1vZGVsCiAgICAgICAgTWFwIGF0dHJpYnV0ZVByb3BlcnR5TW9kZWwgPSBidWlsZEF0dHJpYnV0ZVByb3BlcnR5TW9kZWxCeVFOYW1lKGF0dHJNb2RlbCwgc0ltcGwpOwoKICAgICAgICAvLyBub3cgZmlsbCBpbiB0aGUgYWN0dWFsIHNjaGVtYSB0eXBlIGltcGxlbWVudGF0aW9uCiAgICAgICAgc0ltcGwuc2V0QmFzZVR5cGVSZWYoYmFzZVR5cGUuZ2V0UmVmKCkpOwogICAgICAgIHNJbXBsLnNldEJhc2VEZXB0aCgoKFNjaGVtYVR5cGVJbXBsKWJhc2VUeXBlKS5nZXRCYXNlRGVwdGgoKSArIDEpOwogICAgICAgIHNJbXBsLnNldERlcml2YXRpb25UeXBlKFNjaGVtYVR5cGUuRFRfUkVTVFJJQ1RJT04pOwogICAgICAgIHNJbXBsLnNldEFub255bW91c1R5cGVSZWZzKG1ha2VSZWZBcnJheShhbm9ueW1vdXNUeXBlcykpOwogICAgICAgIHNJbXBsLnNldFdpbGRjYXJkU3VtbWFyeShRTmFtZVNldC5FTVBUWSwgZmFsc2UsIHdjQXR0ci50eXBlZFdpbGRjYXJkcywgd2NBdHRyLmhhc1dpbGRjYXJkcyk7CiAgICAgICAgc0ltcGwuc2V0Q29tcGxleFR5cGVWYXJpZXR5KFNjaGVtYVR5cGUuU0lNUExFX0NPTlRFTlQpOwogICAgICAgIHNJbXBsLnNldENvbnRlbnRNb2RlbChudWxsLCBhdHRyTW9kZWwsIG51bGwsIGF0dHJpYnV0ZVByb3BlcnR5TW9kZWwsIGZhbHNlKTsKICAgICAgICBzSW1wbC5zZXRTaW1wbGVUeXBlVmFyaWV0eShiYXNlVHlwZS5nZXRTaW1wbGVWYXJpZXR5KCkpOwogICAgICAgIHNJbXBsLnNldFByaW1pdGl2ZVR5cGVSZWYoYmFzZVR5cGUuZ2V0UHJpbWl0aXZlVHlwZSgpID09IG51bGwgPyBudWxsIDogYmFzZVR5cGUuZ2V0UHJpbWl0aXZlVHlwZSgpLmdldFJlZigpKTsKICAgICAgICBzd2l0Y2ggKHNJbXBsLmdldFNpbXBsZVZhcmlldHkoKSkKICAgICAgICB7CiAgICAgICAgICAgIGNhc2UgU2NoZW1hVHlwZS5MSVNUOgogICAgICAgICAgICAgICAgc0ltcGwuc2V0TGlzdEl0ZW1UeXBlUmVmKGJhc2VUeXBlLmdldExpc3RJdGVtVHlwZSgpLmdldFJlZigpKTsKICAgICAgICAgICAgICAgIGJyZWFrOwoKICAgICAgICAgICAgY2FzZSBTY2hlbWFUeXBlLlVOSU9OOgogICAgICAgICAgICAgICAgc0ltcGwuc2V0VW5pb25NZW1iZXJUeXBlUmVmcyhtYWtlUmVmQXJyYXkoQXJyYXlzLmFzTGlzdChiYXNlVHlwZS5nZXRVbmlvbk1lbWJlclR5cGVzKCkpKSk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICB9CgogICAgICAgIC8vIGRlYWwgd2l0aCBmYWNldHMKICAgICAgICBTdHNjU2ltcGxlVHlwZVJlc29sdmVyLnJlc29sdmVGYWNldHMoc0ltcGwsIHBhcnNlVHJlZSwgKFNjaGVtYVR5cGVJbXBsKWJhc2VUeXBlKTsKCiAgICAgICAgLy8gbm93IGNvbXB1dGUgb3VyIGludHJpbnNpYyBwcm9wZXJ0aWVzCiAgICAgICAgU3RzY1NpbXBsZVR5cGVSZXNvbHZlci5yZXNvbHZlRnVuZGFtZW50YWxGYWNldHMoc0ltcGwpOwogICAgfQoKICAgIHN0YXRpYyB2b2lkIHJlc29sdmVTY0V4dGVuc2lvbihTY2hlbWFUeXBlSW1wbCBzSW1wbCwgU2ltcGxlRXh0ZW5zaW9uVHlwZSBwYXJzZVRyZWUpCiAgICB7CiAgICAgICAgU2NoZW1hVHlwZSBiYXNlVHlwZTsKICAgICAgICBTdHNjU3RhdGUgc3RhdGUgPSBTdHNjU3RhdGUuZ2V0KCk7CiAgICAgICAgU3RyaW5nIHRhcmdldE5hbWVzcGFjZSA9IHNJbXBsLmdldFRhcmdldE5hbWVzcGFjZSgpOwogICAgICAgIGJvb2xlYW4gY2hhbWVsZW9uID0gKHNJbXBsLmdldENoYW1lbGVvbk5hbWVzcGFjZSgpICE9IG51bGwpOwogICAgICAgIGlmIChwYXJzZVRyZWUuZ2V0QmFzZSgpID09IG51bGwpCiAgICAgICAgewogICAgICAgICAgICBzdGF0ZS5lcnJvcigiQSBzaW1wbGVDb250ZW50IGV4dGVuc2lvbiBtdXN0IGRlZmluZSBhIGJhc2UgdHlwZSIsIFhtbEVycm9yQ29udGV4dC5NSVNTSU5HX0JBU0UsIHBhcnNlVHJlZSk7CiAgICAgICAgICAgIC8vIHJlY292ZXJ5OiBleHRlbmRzIEFOWV9TSU1QTEUgdHlwZQogICAgICAgICAgICBiYXNlVHlwZSA9IEJ1aWx0aW5TY2hlbWFUeXBlU3lzdGVtLlNUX0FOWV9TSU1QTEU7CiAgICAgICAgfQogICAgICAgIGVsc2UKICAgICAgICB7CiAgICAgICAgICAgIGlmIChzSW1wbC5pc1JlZGVmaW5pdGlvbigpKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBiYXNlVHlwZSA9IHN0YXRlLmZpbmRSZWRlZmluZWRHbG9iYWxUeXBlKHBhcnNlVHJlZS5nZXRCYXNlKCksIHNJbXBsLmdldENoYW1lbGVvbk5hbWVzcGFjZSgpLCBzSW1wbC5nZXROYW1lKCkpOwogICAgICAgICAgICAgICAgaWYgKGJhc2VUeXBlICE9IG51bGwgJiYgIWJhc2VUeXBlLmdldE5hbWUoKS5lcXVhbHMoc0ltcGwuZ2V0TmFtZSgpKSkKICAgICAgICAgICAgICAgICAgICBzdGF0ZS5lcnJvcigiQSB0eXBlIHJlZGVmaW5pdGlvbiBtdXN0IGV4dGVuZCB0aGUgb3JpZ2luYWwgdHlwZSBkZWZpbml0aW9uIiwgWG1sRXJyb3JDb250ZXh0LkdFTkVSSUNfRVJST1IsIHBhcnNlVHJlZSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBiYXNlVHlwZSA9IHN0YXRlLmZpbmRHbG9iYWxUeXBlKHBhcnNlVHJlZS5nZXRCYXNlKCksIHNJbXBsLmdldENoYW1lbGVvbk5hbWVzcGFjZSgpKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAoYmFzZVR5cGUgPT0gbnVsbCkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgc3RhdGUubm90Rm91bmRFcnJvcihwYXJzZVRyZWUuZ2V0QmFzZSgpLCBYbWxFcnJvckNvbnRleHQuVFlQRV9OT1RfRk9VTkQsIHBhcnNlVHJlZS54Z2V0QmFzZSgpKTsKICAgICAgICAgICAgICAgIC8vIHJlY292ZXJ5OiBleHRlbmRzIEFOWV9TSU1QTEUgdHlwZQogICAgICAgICAgICAgICAgYmFzZVR5cGUgPSBCdWlsdGluU2NoZW1hVHlwZVN5c3RlbS5TVF9BTllfU0lNUExFOwogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICAvLyBSZWN1cnNpb24KICAgICAgICBTdHNjUmVzb2x2ZXIucmVzb2x2ZVR5cGUoKFNjaGVtYVR5cGVJbXBsKWJhc2VUeXBlKTsKCiAgICAgICAgaWYgKCFiYXNlVHlwZS5pc1NpbXBsZVR5cGUoKSAmJiBiYXNlVHlwZS5nZXRDb250ZW50VHlwZSgpICE9IFNjaGVtYVR5cGUuU0lNUExFX0NPTlRFTlQpCiAgICAgICAgewogICAgICAgICAgICBzdGF0ZS5lcnJvcigiVGhlIHNwZWNpZmllZCBiYXNlIHR5cGUgIiArIGJhc2VUeXBlLnRvU3RyaW5nKCkgKyAiIGRvZXMgbm90IGhhdmUgc2ltcGxlIGNvbnRlbnQuIiwgWG1sRXJyb3JDb250ZXh0LlNJTVBMRV9CQVNFX05PVF9TSU1QTEUsIHBhcnNlVHJlZSk7CiAgICAgICAgICAgIC8vIHJlY292ZXJ5OiBleHRlbmRzIEFOWV9TSU1QTEUgdHlwZQogICAgICAgICAgICBiYXNlVHlwZSA9IEJ1aWx0aW5TY2hlbWFUeXBlU3lzdGVtLlNUX0FOWV9TSU1QTEU7CiAgICAgICAgfQoKICAgICAgICBpZiAoYmFzZVR5cGUgIT0gbnVsbCAmJiBiYXNlVHlwZS5maW5hbEV4dGVuc2lvbigpKQogICAgICAgIHsKICAgICAgICAgICAgc3RhdGUuZXJyb3IoIkNhbm5vdCBleHRlbmQgYSBmaW5hbCB0eXBlIiwgWG1sRXJyb3JDb250ZXh0LkNBTk5PVF9ERVJJVkVfRklOQUwsIHBhcnNlVHJlZS54Z2V0QmFzZSgpKTsKICAgICAgICAgICAgLy8gcmVjb3Zlcnk6IGp1c3Qga2VlcCBnb2luZwogICAgICAgIH0KCiAgICAgICAgLy8gYnVpbGQgYXR0ciBtb2RlbCBhbmQgYW5vbnltb3VzIHR5cGVzCiAgICAgICAgTGlzdCBhbm9ueW1vdXNUeXBlcyA9IG5ldyBBcnJheUxpc3QoKTsKICAgICAgICBTY2hlbWFBdHRyaWJ1dGVNb2RlbEltcGwgYXR0ck1vZGVsOwogICAgICAgIGF0dHJNb2RlbCA9IG5ldyBTY2hlbWFBdHRyaWJ1dGVNb2RlbEltcGwoYmFzZVR5cGUuZ2V0QXR0cmlidXRlTW9kZWwoKSk7CiAgICAgICAgdHJhbnNsYXRlQXR0cmlidXRlTW9kZWwocGFyc2VUcmVlLCB0YXJnZXROYW1lc3BhY2UsIGNoYW1lbGVvbiwgYW5vbnltb3VzVHlwZXMsIHNJbXBsLCBudWxsLCBhdHRyTW9kZWwsIGJhc2VUeXBlLCB0cnVlLCBudWxsKTsKCiAgICAgICAgLy8gc3VtbWFyaXplIHdpbGRjYXJkIGluZm9ybWF0aW9uCiAgICAgICAgV2lsZGNhcmRSZXN1bHQgd2NBdHRyID0gc3VtbWFyaXplQXR0cldpbGRjYXJkcyhhdHRyTW9kZWwpOwoKICAgICAgICAvLyBhZGQgYXR0cmlidXRlIHByb3BlcnR5IG1vZGVsCiAgICAgICAgTWFwIGF0dHJpYnV0ZVByb3BlcnR5TW9kZWwgPSBidWlsZEF0dHJpYnV0ZVByb3BlcnR5TW9kZWxCeVFOYW1lKGF0dHJNb2RlbCwgc0ltcGwpOwoKICAgICAgICAvLyBub3cgZmlsbCBpbiB0aGUgYWN0dWFsIHNjaGVtYSB0eXBlIGltcGxlbWVudGF0aW9uCiAgICAgICAgc0ltcGwuc2V0QmFzZVR5cGVSZWYoYmFzZVR5cGUuZ2V0UmVmKCkpOwogICAgICAgIHNJbXBsLnNldEJhc2VEZXB0aCgoKFNjaGVtYVR5cGVJbXBsKWJhc2VUeXBlKS5nZXRCYXNlRGVwdGgoKSArIDEpOwogICAgICAgIHNJbXBsLnNldERlcml2YXRpb25UeXBlKFNjaGVtYVR5cGUuRFRfRVhURU5TSU9OKTsKICAgICAgICBzSW1wbC5zZXRBbm9ueW1vdXNUeXBlUmVmcyhtYWtlUmVmQXJyYXkoYW5vbnltb3VzVHlwZXMpKTsKICAgICAgICBzSW1wbC5zZXRXaWxkY2FyZFN1bW1hcnkoUU5hbWVTZXQuRU1QVFksIGZhbHNlLCB3Y0F0dHIudHlwZWRXaWxkY2FyZHMsIHdjQXR0ci5oYXNXaWxkY2FyZHMpOwogICAgICAgIHNJbXBsLnNldENvbXBsZXhUeXBlVmFyaWV0eShTY2hlbWFUeXBlLlNJTVBMRV9DT05URU5UKTsKICAgICAgICBzSW1wbC5zZXRDb250ZW50TW9kZWwobnVsbCwgYXR0ck1vZGVsLCBudWxsLCBhdHRyaWJ1dGVQcm9wZXJ0eU1vZGVsLCBmYWxzZSk7CiAgICAgICAgc0ltcGwuc2V0U2ltcGxlVHlwZVZhcmlldHkoYmFzZVR5cGUuZ2V0U2ltcGxlVmFyaWV0eSgpKTsKICAgICAgICBzSW1wbC5zZXRQcmltaXRpdmVUeXBlUmVmKGJhc2VUeXBlLmdldFByaW1pdGl2ZVR5cGUoKSA9PSBudWxsID8gbnVsbCA6IGJhc2VUeXBlLmdldFByaW1pdGl2ZVR5cGUoKS5nZXRSZWYoKSk7CiAgICAgICAgc3dpdGNoIChzSW1wbC5nZXRTaW1wbGVWYXJpZXR5KCkpCiAgICAgICAgewogICAgICAgICAgICBjYXNlIFNjaGVtYVR5cGUuTElTVDoKICAgICAgICAgICAgICAgIHNJbXBsLnNldExpc3RJdGVtVHlwZVJlZihiYXNlVHlwZS5nZXRMaXN0SXRlbVR5cGUoKS5nZXRSZWYoKSk7CiAgICAgICAgICAgICAgICBicmVhazsKCiAgICAgICAgICAgIGNhc2UgU2NoZW1hVHlwZS5VTklPTjoKICAgICAgICAgICAgICAgIHNJbXBsLnNldFVuaW9uTWVtYmVyVHlwZVJlZnMobWFrZVJlZkFycmF5KEFycmF5cy5hc0xpc3QoYmFzZVR5cGUuZ2V0VW5pb25NZW1iZXJUeXBlcygpKSkpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgfQoKICAgICAgICAvLyBkZWFsIHdpdGggZmFjZXRzCiAgICAgICAgU3RzY1NpbXBsZVR5cGVSZXNvbHZlci5yZXNvbHZlRmFjZXRzKHNJbXBsLCBudWxsLCAoU2NoZW1hVHlwZUltcGwpYmFzZVR5cGUpOwoKICAgICAgICAvLyBub3cgY29tcHV0ZSBvdXIgaW50cmluc2ljIHByb3BlcnRpZXMKICAgICAgICBTdHNjU2ltcGxlVHlwZVJlc29sdmVyLnJlc29sdmVGdW5kYW1lbnRhbEZhY2V0cyhzSW1wbCk7CiAgICB9CgogICAgc3RhdGljIGNsYXNzIFdpbGRjYXJkUmVzdWx0CiAgICB7CiAgICAgICAgV2lsZGNhcmRSZXN1bHQoUU5hbWVTZXQgdHlwZWRXaWxkY2FyZHMsIGJvb2xlYW4gaGFzV2lsZGNhcmRzKQogICAgICAgIHsKICAgICAgICAgICAgdGhpcy50eXBlZFdpbGRjYXJkcyA9IHR5cGVkV2lsZGNhcmRzOwogICAgICAgICAgICB0aGlzLmhhc1dpbGRjYXJkcyA9IGhhc1dpbGRjYXJkczsKICAgICAgICB9CiAgICAgICAgUU5hbWVTZXQgdHlwZWRXaWxkY2FyZHM7CiAgICAgICAgYm9vbGVhbiBoYXNXaWxkY2FyZHM7CiAgICB9CgogICAgc3RhdGljIFdpbGRjYXJkUmVzdWx0IHN1bW1hcml6ZUF0dHJXaWxkY2FyZHMoU2NoZW1hQXR0cmlidXRlTW9kZWwgYXR0ck1vZGVsKQogICAgewogICAgICAgIGlmIChhdHRyTW9kZWwuZ2V0V2lsZGNhcmRQcm9jZXNzKCkgPT0gU2NoZW1hQXR0cmlidXRlTW9kZWwuTk9ORSkKICAgICAgICAgICAgcmV0dXJuIG5ldyBXaWxkY2FyZFJlc3VsdChRTmFtZVNldC5FTVBUWSwgZmFsc2UpOwogICAgICAgIGlmIChhdHRyTW9kZWwuZ2V0V2lsZGNhcmRQcm9jZXNzKCkgPT0gU2NoZW1hQXR0cmlidXRlTW9kZWwuU0tJUCkKICAgICAgICAgICAgcmV0dXJuIG5ldyBXaWxkY2FyZFJlc3VsdChRTmFtZVNldC5FTVBUWSwgdHJ1ZSk7CiAgICAgICAgcmV0dXJuIG5ldyBXaWxkY2FyZFJlc3VsdChhdHRyTW9kZWwuZ2V0V2lsZGNhcmRTZXQoKSwgdHJ1ZSk7CiAgICB9CgogICAgc3RhdGljIFdpbGRjYXJkUmVzdWx0IHN1bW1hcml6ZUVsdFdpbGRjYXJkcyhTY2hlbWFQYXJ0aWNsZSBjb250ZW50TW9kZWwpCiAgICB7CiAgICAgICAgaWYgKGNvbnRlbnRNb2RlbCA9PSBudWxsKQogICAgICAgIHsKICAgICAgICAgICAgcmV0dXJuIG5ldyBXaWxkY2FyZFJlc3VsdChRTmFtZVNldC5FTVBUWSwgZmFsc2UpOwogICAgICAgIH0KCiAgICAgICAgc3dpdGNoIChjb250ZW50TW9kZWwuZ2V0UGFydGljbGVUeXBlKCkpCiAgICAgICAgewogICAgICAgICAgICBjYXNlIFNjaGVtYVBhcnRpY2xlLkFMTDoKICAgICAgICAgICAgY2FzZSBTY2hlbWFQYXJ0aWNsZS5TRVFVRU5DRToKICAgICAgICAgICAgY2FzZSBTY2hlbWFQYXJ0aWNsZS5DSE9JQ0U6CiAgICAgICAgICAgICAgICBRTmFtZVNldEJ1aWxkZXIgc2V0ID0gbmV3IFFOYW1lU2V0QnVpbGRlcigpOwogICAgICAgICAgICAgICAgYm9vbGVhbiBoYXNXaWxkY2FyZHMgPSBmYWxzZTsKICAgICAgICAgICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgY29udGVudE1vZGVsLmNvdW50T2ZQYXJ0aWNsZUNoaWxkKCk7IGkrKykKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBXaWxkY2FyZFJlc3VsdCBpbm5lciA9IHN1bW1hcml6ZUVsdFdpbGRjYXJkcyhjb250ZW50TW9kZWwuZ2V0UGFydGljbGVDaGlsZChpKSk7CiAgICAgICAgICAgICAgICAgICAgc2V0LmFkZEFsbChpbm5lci50eXBlZFdpbGRjYXJkcyk7CiAgICAgICAgICAgICAgICAgICAgaGFzV2lsZGNhcmRzIHw9IGlubmVyLmhhc1dpbGRjYXJkczsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHJldHVybiBuZXcgV2lsZGNhcmRSZXN1bHQoc2V0LnRvUU5hbWVTZXQoKSwgaGFzV2lsZGNhcmRzKTsKICAgICAgICAgICAgY2FzZSBTY2hlbWFQYXJ0aWNsZS5XSUxEQ0FSRDoKICAgICAgICAgICAgICAgIHJldHVybiBuZXcgV2lsZGNhcmRSZXN1bHQoCiAgICAgICAgICAgICAgICAgICAgKGNvbnRlbnRNb2RlbC5nZXRXaWxkY2FyZFByb2Nlc3MoKSA9PSBTY2hlbWFQYXJ0aWNsZS5TS0lQKSA/CiAgICAgICAgICAgICAgICAgICAgUU5hbWVTZXQuRU1QVFkgOiBjb250ZW50TW9kZWwuZ2V0V2lsZGNhcmRTZXQoKSwgdHJ1ZSk7CiAgICAgICAgICAgICAgICAvLyBvdGhlcndpc2UgZmFsbHRocm91Z2gKCiAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFdpbGRjYXJkUmVzdWx0KFFOYW1lU2V0LkVNUFRZLCBmYWxzZSk7CiAgICAgICAgfQogICAgfQoKICAgIHN0YXRpYyB2b2lkIHRyYW5zbGF0ZUF0dHJpYnV0ZU1vZGVsKAogICAgICAgICAgICBYbWxPYmplY3QgcGFyc2VUcmVlLCBTdHJpbmcgdGFyZ2V0TmFtZXNwYWNlLCBib29sZWFuIGNoYW1lbGVvbiwKICAgICAgICAgICAgTGlzdCBhbm9ueW1vdXNUeXBlcywgU2NoZW1hVHlwZSBvdXRlclR5cGUsCiAgICAgICAgICAgIFNldCBzZWVuQXR0cmlidXRlcywgU2NoZW1hQXR0cmlidXRlTW9kZWxJbXBsIHJlc3VsdCwgU2NoZW1hVHlwZSBiYXNlVHlwZSwgYm9vbGVhbiBleHRlbnNpb24sIFFOYW1lIHJlZGVmaW5pdGlvbkZvcikKICAgIHsKICAgICAgICBTdHNjU3RhdGUgc3RhdGUgPSBTdHNjU3RhdGUuZ2V0KCk7CiAgICAgICAgaWYgKHNlZW5BdHRyaWJ1dGVzID09IG51bGwpCiAgICAgICAgICAgIHNlZW5BdHRyaWJ1dGVzID0gbmV3IEhhc2hTZXQoKTsKICAgICAgICBib29sZWFuIHNlZW5XaWxkY2FyZCA9IGZhbHNlOwogICAgICAgIGJvb2xlYW4gc2VlblJlZGVmaW5pdGlvbiA9IGZhbHNlOwogICAgICAgIFNjaGVtYUF0dHJpYnV0ZU1vZGVsIGJhc2VNb2RlbCA9IG51bGw7CiAgICAgICAgaWYgKGJhc2VUeXBlICE9IG51bGwpCiAgICAgICAgICAgIGJhc2VNb2RlbCA9IGJhc2VUeXBlLmdldEF0dHJpYnV0ZU1vZGVsKCk7CgogICAgICAgIFhtbEN1cnNvciBjdXIgPSBwYXJzZVRyZWUubmV3Q3Vyc29yKCk7CgogICAgICAgIGZvciAoYm9vbGVhbiBtb3JlID0gY3VyLnRvRmlyc3RDaGlsZCgpOyBtb3JlOyBtb3JlID0gY3VyLnRvTmV4dFNpYmxpbmcoKSkKICAgICAgICB7CiAgICAgICAgICAgIHN3aXRjaCAodHJhbnNsYXRlQXR0cmlidXRlQ29kZShjdXIuZ2V0TmFtZSgpKSkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgY2FzZSBBVFRSSUJVVEVfQ09ERToKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBBdHRyaWJ1dGUgeHNkYXR0ciA9IChBdHRyaWJ1dGUpY3VyLmdldE9iamVjdCgpOwoKICAgICAgICAgICAgICAgICAgICBTY2hlbWFMb2NhbEF0dHJpYnV0ZSBzQXR0ciA9IFN0c2NUcmFuc2xhdG9yLnRyYW5zbGF0ZUF0dHJpYnV0ZSh4c2RhdHRyLCB0YXJnZXROYW1lc3BhY2UsIGNoYW1lbGVvbiwgYW5vbnltb3VzVHlwZXMsIG91dGVyVHlwZSwgYmFzZU1vZGVsLCB0cnVlKTsKICAgICAgICAgICAgICAgICAgICBpZiAoc0F0dHIgPT0gbnVsbCkKICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7CgogICAgICAgICAgICAgICAgICAgIGlmIChzZWVuQXR0cmlidXRlcy5jb250YWlucyhzQXR0ci5nZXROYW1lKCkpKQogICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGUuZXJyb3IoIkF0dHJpYnV0ZSB3aXRoIHRoZSBzYW1lIG5hbWUgYWxyZWFkeSBkZWZpbmVkICIsIFhtbEVycm9yQ29udGV4dC5EVVBMSUNBVEVfQVRUUklCVVRFX05BTUUsIHhzZGF0dHIueGdldE5hbWUoKSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlOyAvLyBpZ25vcmUgdGhlIGR1cGxpY2F0ZSBhdHRyCiAgICAgICAgICAgICAgICAgICAgfQoKICAgICAgICAgICAgICAgICAgICBzZWVuQXR0cmlidXRlcy5hZGQoc0F0dHIuZ2V0TmFtZSgpKTsKICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICBpZiAoYmFzZU1vZGVsICE9IG51bGwpCiAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICBTY2hlbWFMb2NhbEF0dHJpYnV0ZSBiYXNlQXR0ciA9IGJhc2VNb2RlbC5nZXRBdHRyaWJ1dGUoc0F0dHIuZ2V0TmFtZSgpKTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJhc2VBdHRyID09IG51bGwpCiAgICAgICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghZXh0ZW5zaW9uKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghYmFzZU1vZGVsLmdldFdpbGRjYXJkU2V0KCkuY29udGFpbnMoc0F0dHIuZ2V0TmFtZSgpKSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGUuZXJyb3IoIkEgcmVzdHJpY3Rpb24gY2Fubm90IGludHJvZHVjZSBhIG5ldyBhdHRyaWJ1dGUgdGhhdCB3b3VsZCBub3QgYmUgYWxsb3dlZCBpbiB0aGUgYmFzZSB0eXBlLiIsIFhtbEVycm9yQ29udGV4dC5EVVBMSUNBVEVfQVRUUklCVVRFX05BTUUsIHhzZGF0dHIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UKICAgICAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGV4dGVuc2lvbikKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc0F0dHIuZ2V0VXNlKCkgPT0gU2NoZW1hTG9jYWxBdHRyaWJ1dGUuUFJPSElCSVRFRCkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGUuZXJyb3IoIkFuIGV4dGVuc2lvbiBjYW5ub3QgcHJvaGliaXQgYW4gYXR0cmlidXRlIGZyb20gdGhlIGJhc2UgdHlwZTsgdXNlIHJlc3RyaWN0aW9uIGluc3RlYWQuIiwgWG1sRXJyb3JDb250ZXh0LkRVUExJQ0FURV9BVFRSSUJVVEVfTkFNRSwgeHNkYXR0ci54Z2V0VXNlKCkpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzQXR0ci5nZXRVc2UoKSAhPSBTY2hlbWFMb2NhbEF0dHJpYnV0ZS5SRVFVSVJFRCkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChiYXNlQXR0ci5nZXRVc2UoKSA9PSBTY2hlbWFMb2NhbEF0dHJpYnV0ZS5SRVFVSVJFRCkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRlLmVycm9yKCJBIHJlc3RyaWN0aW9uIGNhbm5vdCBtb2RpZnkgYW4gYXR0cmlidXRlIHRoYXQgaXMgcmVxdWlyZWQgaW4gdGhlIGJhc2UgdHlwZSB0byBiZSBwcm9oaWJpdGVkIG9yIG9wdGlvbmFsLiIsIFhtbEVycm9yQ29udGV4dC5EVVBMSUNBVEVfQVRUUklCVVRFX05BTUUsIHhzZGF0dHIueGdldFVzZSgpKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzQXR0ci5nZXRVc2UoKSA9PSBTY2hlbWFMb2NhbEF0dHJpYnV0ZS5QUk9ISUJJVEVEKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LnJlbW92ZVByb2hpYml0ZWRBdHRyaWJ1dGUoc0F0dHIuZ2V0TmFtZSgpKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CgogICAgICAgICAgICAgICAgICAgIGlmIChzQXR0ci5nZXRVc2UoKSAhPSBTY2hlbWFMb2NhbEF0dHJpYnV0ZS5QUk9ISUJJVEVEKQogICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuYWRkQXR0cmlidXRlKHNBdHRyKTsKICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgaWYgKHNBdHRyLmdldERlZmF1bHRUZXh0KCkgIT0gbnVsbCAmJiAhc0F0dHIuaXNGaXhlZCgpKQogICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNBdHRyLmdldFVzZSgpICE9IFNjaGVtYUxvY2FsQXR0cmlidXRlLk9QVElPTkFMKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGUuZXJyb3IoIkFuIGF0dHJpYnV0ZSBkZWNsYXJhdGlvbiBtdXN0IGJlIG9wdGlvbmFsIGluIG9yZGVyIHRvIHNwZWNpZnkgYSBkZWZhdWx0IiwgWG1sRXJyb3JDb250ZXh0LkdFTkVSSUNfRVJST1IsIHhzZGF0dHIpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgCgogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgY2FzZSBBTllfQVRUUklCVVRFX0NPREU6CiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgV2lsZGNhcmQgeHNkd2MgPSAoV2lsZGNhcmQpY3VyLmdldE9iamVjdCgpOwogICAgICAgICAgICAgICAgICAgIGlmIChzZWVuV2lsZGNhcmQpCiAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZS5lcnJvcigiT25seSBvbmUgYXR0cmlidXRlIHdpbGRjYXJkIGFsbG93ZWQiLCBYbWxFcnJvckNvbnRleHQuRFVQTElDQVRFX0FOWV9BVFRSSUJVVEUsIHhzZHdjKTsKICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7IC8vIGlnbm9yZSB0aGUgZXh0cmEgd2lsZGNhcmQKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgc2VlbldpbGRjYXJkID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICBOYW1lc3BhY2VMaXN0IG5zTGlzdCA9IHhzZHdjLnhnZXROYW1lc3BhY2UoKTsKICAgICAgICAgICAgICAgICAgICBTdHJpbmcgbnNUZXh0OwogICAgICAgICAgICAgICAgICAgIGlmIChuc0xpc3QgPT0gbnVsbCkKICAgICAgICAgICAgICAgICAgICAgICAgbnNUZXh0ID0gIiMjYW55IjsKICAgICAgICAgICAgICAgICAgICBlbHNlCiAgICAgICAgICAgICAgICAgICAgICAgIG5zVGV4dCA9IG5zTGlzdC5nZXRTdHJpbmdWYWx1ZSgpOwogICAgICAgICAgICAgICAgICAgIFFOYW1lU2V0IHdjc2V0ID0gUU5hbWVTZXQuZm9yV2lsZGNhcmROYW1lc3BhY2VTdHJpbmcobnNUZXh0LCB0YXJnZXROYW1lc3BhY2UpOwogICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgIGlmIChiYXNlTW9kZWwgIT0gbnVsbCAmJiAhZXh0ZW5zaW9uKQogICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJhc2VNb2RlbC5nZXRXaWxkY2FyZFNldCgpID09IG51bGwpCiAgICAgICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRlLmVycm9yKCJBIHJlc3RyaWN0aW9uIGNhbm5vdCBhZGQgYW55QXR0cmlidXRlIHdoZW4gdGhlIGJhc2UgdHlwZSBkb2VzIG5vdCBoYXZlIGFueUF0dHJpYnV0ZSIsIFhtbEVycm9yQ29udGV4dC5EVVBMSUNBVEVfQU5ZX0FUVFJJQlVURSwgeHNkd2MpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7IC8vIGlnbm9yZSB0aGUgZXh0cmEgd2lsZGNhcmQKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBlbHNlIGlmICghYmFzZU1vZGVsLmdldFdpbGRjYXJkU2V0KCkuY29udGFpbnNBbGwod2NzZXQpKQogICAgICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZS5lcnJvcigiVGhlIGFueUF0dHJpYnV0ZSBuYW1lc3BhY2U9JyIgKyBuc1RleHQgKyAiJyBpcyBub3QgYSBzdWJzZXQgb2YgdGhlIGJhc2UgdHlwZSBhbnlBdHRyaWJ1dGUiLCBYbWxFcnJvckNvbnRleHQuRFVQTElDQVRFX0FOWV9BVFRSSUJVVEUsIHhzZHdjKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlOyAvLyBpZ25vcmUgdGhlIHJlc3RyaWN0aW9uCiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgaW50IHdjcHJvY2VzcyA9IHRyYW5zbGF0ZVdpbGRjYXJkUHJvY2Vzcyh4c2R3Yy54Z2V0UHJvY2Vzc0NvbnRlbnRzKCkpOwogICAgICAgICAgICAgICAgICAgIGlmIChyZXN1bHQuZ2V0V2lsZGNhcmRQcm9jZXNzKCkgPT0gU2NoZW1hQXR0cmlidXRlTW9kZWwuTk9ORSkKICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5zZXRXaWxkY2FyZFNldCh3Y3NldCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5zZXRXaWxkY2FyZFByb2Nlc3Mod2Nwcm9jZXNzKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZWxzZQogICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGV4dGVuc2lvbikKICAgICAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LnNldFdpbGRjYXJkU2V0KHdjc2V0LnVuaW9uKHJlc3VsdC5nZXRXaWxkY2FyZFNldCgpKSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuc2V0V2lsZGNhcmRQcm9jZXNzKHdjcHJvY2Vzcyk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgZWxzZQogICAgICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuc2V0V2lsZGNhcmRTZXQod2NzZXQuaW50ZXJzZWN0KHJlc3VsdC5nZXRXaWxkY2FyZFNldCgpKSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBrZWVwIG9sZCBwcm9jZXNzCiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBjYXNlIEFUVFJJQlVURV9HUk9VUF9DT0RFOgogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIEF0dHJpYnV0ZUdyb3VwUmVmIHhzZGFnID0gKEF0dHJpYnV0ZUdyb3VwUmVmKWN1ci5nZXRPYmplY3QoKTsKICAgICAgICAgICAgICAgICAgICBRTmFtZSByZWYgPSB4c2RhZy5nZXRSZWYoKTsKICAgICAgICAgICAgICAgICAgICBpZiAocmVmID09IG51bGwpCiAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZS5lcnJvcigiQXR0cmlidXRlIGdyb3VwIHJlZmVyZW5jZSBtdXN0IGhhdmUgYSByZWYgYXR0cmlidXRlIiwgWG1sRXJyb3JDb250ZXh0LkFUVFJJQlVURV9HUk9VUF9NSVNTSU5HX1JFRiwgeHNkYWcpOwogICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgU2NoZW1hQXR0cmlidXRlR3JvdXBJbXBsIGdyb3VwOwogICAgICAgICAgICAgICAgICAgIGlmIChyZWRlZmluaXRpb25Gb3IgIT0gbnVsbCkKICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwID0gc3RhdGUuZmluZFJlZGVmaW5lZEF0dHJpYnV0ZUdyb3VwKHJlZiwgY2hhbWVsZW9uID8gdGFyZ2V0TmFtZXNwYWNlIDogbnVsbCwgcmVkZWZpbml0aW9uRm9yKTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGdyb3VwICE9IG51bGwgJiYgcmVkZWZpbml0aW9uRm9yLmVxdWFscyhncm91cC5nZXROYW1lKCkpKQogICAgICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2VlblJlZGVmaW5pdGlvbikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZS5lcnJvcigiQW4gYXR0cmlidXRlIGdyb3VwIHJlZGVmaW5pdGlvbiBtdXN0IGluY2x1ZGUgYXQgbW9zdCBvbmUgcmVmZXJlbmNlIHRvIHRoZSBvcmlnaW5hbCBkZWZpbml0aW9uLiIsIFhtbEVycm9yQ29udGV4dC5HRU5FUklDX0VSUk9SLCB4c2RhZyk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWVuUmVkZWZpbml0aW9uID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBlbHNlCiAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICBncm91cCA9IHN0YXRlLmZpbmRBdHRyaWJ1dGVHcm91cChyZWYsIGNoYW1lbGVvbiA/IHRhcmdldE5hbWVzcGFjZSA6IG51bGwpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBpZiAoZ3JvdXAgPT0gbnVsbCkKICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRlLm5vdEZvdW5kRXJyb3IocmVmLCBYbWxFcnJvckNvbnRleHQuQVRUUklCVVRFX0dST1VQX05PVF9GT1VORCwgeHNkYWcueGdldFJlZigpKTsKICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGlmIChzdGF0ZS5pc1Byb2Nlc3NpbmcoZ3JvdXApKQogICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGUuZXJyb3IoIkF0dHJpYnV0ZSBncm91cCAiICsgUU5hbWVIZWxwZXIucHJldHR5KGdyb3VwLmdldE5hbWUoKSkgKyAiIHJlZmVyZW5jZXMgaXRzZWxmIiwgWG1sRXJyb3JDb250ZXh0LkNZQ0xJQ19ERVBFTkRFTkNZLCBncm91cC5nZXRQYXJzZU9iamVjdCgpKTsKICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIFN0cmluZyBzdWJUYXJnZXROYW1lc3BhY2UgPSB0YXJnZXROYW1lc3BhY2U7CiAgICAgICAgICAgICAgICAgICAgaWYgKGdyb3VwLmdldFRhcmdldE5hbWVzcGFjZSgpICE9IG51bGwpCiAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICBzdWJUYXJnZXROYW1lc3BhY2UgPSBncm91cC5nZXRUYXJnZXROYW1lc3BhY2UoKTsKICAgICAgICAgICAgICAgICAgICAgICAgY2hhbWVsZW9uID0gZ3JvdXAuZ2V0Q2hhbWVsZW9uTmFtZXNwYWNlKCkgIT0gbnVsbDsKICAgICAgICAgICAgICAgICAgICB9CgogICAgICAgICAgICAgICAgICAgIHN0YXRlLnN0YXJ0UHJvY2Vzc2luZyhncm91cCk7CiAgICAgICAgICAgICAgICAgICAgUU5hbWUgbmVzdGVkUmVkZWZpbml0aW9uRm9yID0gbnVsbDsKICAgICAgICAgICAgICAgICAgICBpZiAoZ3JvdXAuaXNSZWRlZmluaXRpb24oKSkKICAgICAgICAgICAgICAgICAgICAgICAgbmVzdGVkUmVkZWZpbml0aW9uRm9yID0gZ3JvdXAuZ2V0TmFtZSgpOwogICAgICAgICAgICAgICAgICAgIHRyYW5zbGF0ZUF0dHJpYnV0ZU1vZGVsKGdyb3VwLmdldFBhcnNlT2JqZWN0KCksIHN1YlRhcmdldE5hbWVzcGFjZSwgY2hhbWVsZW9uLCBhbm9ueW1vdXNUeXBlcywgb3V0ZXJUeXBlLCBzZWVuQXR0cmlidXRlcywgcmVzdWx0LCBiYXNlVHlwZSwgZXh0ZW5zaW9uLCBuZXN0ZWRSZWRlZmluaXRpb25Gb3IpOwogICAgICAgICAgICAgICAgICAgIHN0YXRlLmZpbmlzaFByb2Nlc3NpbmcoZ3JvdXApOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBjb250aW51ZTsgLy8gc2tpcCB0aGluZ3MgdGhhdCBhcmUgbm90IHBhcnQgb2YgdGhlIGF0dHJpYnV0ZSBtb2RlbC4KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KCiAgICBzdGF0aWMgU2NoZW1hUGFydGljbGUgZXh0ZW5kQ29udGVudE1vZGVsKFNjaGVtYVBhcnRpY2xlIGJhc2VDb250ZW50TW9kZWwsIFNjaGVtYVBhcnRpY2xlIGV4dGVuZGVkQ29udGVudE1vZGVsLCBYbWxPYmplY3QgcGFyc2VUcmVlKQogICAgewogICAgICAgIC8vIGh0dHA6Ly93d3cudzMub3JnL1RSL3htbHNjaGVtYS0xLyNlbGVtZW50LWNvbXBsZXhDb250ZW50OjpleHRlbnNpb24KICAgICAgICAKICAgICAgICAvLyAyLjEgSWYgdGhlILdleHBsaWNpdCBjb250ZW50tyBpcyBlbXB0eSwgdGhlbiB0aGUge2NvbnRlbnQgdHlwZX0gb2YgdGhlIHR5cGUgZGVmaW5pdGlvbiC3cmVzb2x2ZWS3IHRvIGJ5IHRoZSC3YWN0dWFsIHZhbHVltyBvZiB0aGUgYmFzZSBbYXR0cmlidXRlXSAKICAgICAgICBpZiAoZXh0ZW5kZWRDb250ZW50TW9kZWwgPT0gbnVsbCkKICAgICAgICAgICAgcmV0dXJuIGJhc2VDb250ZW50TW9kZWw7CiAgICAgICAgCiAgICAgICAgLy8gMi4yIElmIHRoZSB0eXBlIGRlZmluaXRpb24gt3Jlc29sdmVktyB0byBieSB0aGUgt2FjdHVhbCB2YWx1Zbcgb2YgdGhlIGJhc2UgW2F0dHJpYnV0ZV0gaGFzIGEge2NvbnRlbnQgdHlwZX0gb2YgZW1wdHksIHRoZW4gYSBwYWlyIG9mIG1peGVkIG9yIGVsZW1lbnRPbmx5IChkZXRlcm1pbmVkIGFzIHBlciBjbGF1c2UgMS4yLjEgYWJvdmUpIGFuZCB0aGUgt2V4cGxpY2l0IGNvbnRlbnS3IGl0c2VsZjsKICAgICAgICBpZiAoYmFzZUNvbnRlbnRNb2RlbCA9PSBudWxsKQogICAgICAgICAgICByZXR1cm4gZXh0ZW5kZWRDb250ZW50TW9kZWw7CiAgICAgICAgCiAgICAgICAgLy8gMi4zIG90aGVyd2lzZSBhIHBhaXIgb2YgbWl4ZWQgb3IgZWxlbWVudE9ubHkgKGRldGVybWluZWQgYXMgcGVyIGNsYXVzZSAxLjIuMSBhYm92ZSkgYW5kIGEgcGFydGljbGUgd2hvc2UgcHJvcGVydGllcyBhcmUgYXMgZm9sbG93czogIAogICAgICAgIFNjaGVtYVBhcnRpY2xlSW1wbCBzUGFydCA9IG5ldyBTY2hlbWFQYXJ0aWNsZUltcGwoKTsKICAgICAgICBzUGFydC5zZXRQYXJ0aWNsZVR5cGUoU2NoZW1hUGFydGljbGUuU0VRVUVOQ0UpOwoKICAgICAgICBMaXN0IGFjY3VtdWxhdGUgPSBuZXcgQXJyYXlMaXN0KCk7CiAgICAgICAgYWRkTWludXNQb2ludGxlc3NQYXJ0aWNsZXMoYWNjdW11bGF0ZSwgYmFzZUNvbnRlbnRNb2RlbCwgU2NoZW1hUGFydGljbGUuU0VRVUVOQ0UpOwogICAgICAgIGFkZE1pbnVzUG9pbnRsZXNzUGFydGljbGVzKGFjY3VtdWxhdGUsIGV4dGVuZGVkQ29udGVudE1vZGVsLCBTY2hlbWFQYXJ0aWNsZS5TRVFVRU5DRSk7CiAgICAgICAgc1BhcnQuc2V0TWluT2NjdXJzKEJpZ0ludGVnZXIuT05FKTsKICAgICAgICBzUGFydC5zZXRNYXhPY2N1cnMoQmlnSW50ZWdlci5PTkUpOwogICAgICAgIHNQYXJ0LnNldFBhcnRpY2xlQ2hpbGRyZW4oKFNjaGVtYVBhcnRpY2xlW10pCiAgICAgICAgICAgICAgICBhY2N1bXVsYXRlLnRvQXJyYXkobmV3IFNjaGVtYVBhcnRpY2xlW2FjY3VtdWxhdGUuc2l6ZSgpXSkpOwoKICAgICAgICByZXR1cm4gZmlsdGVyUG9pbnRsZXNzUGFydGljbGVzQW5kVmVyaWZ5QWxsUGFydGljbGVzKHNQYXJ0LCBwYXJzZVRyZWUpOwogICAgfQoKICAgIHN0YXRpYyBCaWdJbnRlZ2VyIGV4dHJhY3RNaW5PY2N1cnMoWG1sTm9uTmVnYXRpdmVJbnRlZ2VyIG5uaSkKICAgIHsKICAgICAgICBpZiAobm5pID09IG51bGwpCiAgICAgICAgICAgIHJldHVybiBCaWdJbnRlZ2VyLk9ORTsKICAgICAgICBCaWdJbnRlZ2VyIHJlc3VsdCA9IG5uaS5nZXRCaWdJbnRlZ2VyVmFsdWUoKTsKICAgICAgICBpZiAocmVzdWx0ID09IG51bGwpCiAgICAgICAgICAgIHJldHVybiBCaWdJbnRlZ2VyLk9ORTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgfQoKICAgIHN0YXRpYyBCaWdJbnRlZ2VyIGV4dHJhY3RNYXhPY2N1cnMoQWxsTk5JIGFsbE5OSSkKICAgIHsKICAgICAgICBpZiAoYWxsTk5JID09IG51bGwpCiAgICAgICAgICAgIHJldHVybiBCaWdJbnRlZ2VyLk9ORTsKCiAgICAgICAgaWYgKGFsbE5OSS5pbnN0YW5jZVR5cGUoKS5nZXRQcmltaXRpdmVUeXBlKCkuZ2V0QnVpbHRpblR5cGVDb2RlKCkgPT0gU2NoZW1hVHlwZS5CVENfREVDSU1BTCkKICAgICAgICAgICAgcmV0dXJuICgoWG1sSW50ZWdlcilhbGxOTkkpLmdldEJpZ0ludGVnZXJWYWx1ZSgpOwogICAgICAgIGVsc2UKICAgICAgICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICAKICAgIHByaXZhdGUgc3RhdGljIGNsYXNzIFJlZGVmaW5pdGlvbkZvckdyb3VwCiAgICB7CiAgICAgICAgcHJpdmF0ZSBRTmFtZSBncm91cE5hbWU7CiAgICAgICAgcHJpdmF0ZSBib29sZWFuIHNlZW5SZWRlZmluaXRpb24gPSBmYWxzZTsKCiAgICAgICAgcHVibGljIFJlZGVmaW5pdGlvbkZvckdyb3VwKFFOYW1lIGdyb3VwTmFtZSkKICAgICAgICB7CiAgICAgICAgICAgIHRoaXMuZ3JvdXBOYW1lID0gZ3JvdXBOYW1lOwogICAgICAgIH0KCiAgICAgICAgcHVibGljIFFOYW1lIGdldEdyb3VwTmFtZSgpCiAgICAgICAgewogICAgICAgICAgICByZXR1cm4gZ3JvdXBOYW1lOwogICAgICAgIH0KCiAgICAgICAgcHVibGljIGJvb2xlYW4gaXNTZWVuUmVkZWZpbml0aW9uKCkKICAgICAgICB7CiAgICAgICAgICAgIHJldHVybiBzZWVuUmVkZWZpbml0aW9uOwogICAgICAgIH0KCiAgICAgICAgcHVibGljIHZvaWQgc2V0U2VlblJlZGVmaW5pdGlvbihib29sZWFuIHNlZW5SZWRlZmluaXRpb24pCiAgICAgICAgewogICAgICAgICAgICB0aGlzLnNlZW5SZWRlZmluaXRpb24gPSBzZWVuUmVkZWZpbml0aW9uOwogICAgICAgIH0KICAgIH0KCiAgICBzdGF0aWMgU2NoZW1hUGFydGljbGUgdHJhbnNsYXRlQ29udGVudE1vZGVsKAogICAgICAgICAgICBTY2hlbWFUeXBlIG91dGVyVHlwZSwKICAgICAgICAgICAgWG1sT2JqZWN0IHBhcnNlVHJlZSwgU3RyaW5nIHRhcmdldE5hbWVzcGFjZSwgYm9vbGVhbiBjaGFtZWxlb24sCiAgICAgICAgICAgIGludCBwYXJ0aWNsZUNvZGUsCiAgICAgICAgICAgIExpc3QgYW5vbnltb3VzVHlwZXMsIE1hcCBlbGVtZW50TW9kZWwsCiAgICAgICAgICAgIGJvb2xlYW4gYWxsb3dFbHQsIFJlZGVmaW5pdGlvbkZvckdyb3VwIHJlZGVmaW5pdGlvbkZvcikKICAgIHsKICAgICAgICBpZiAocGFyc2VUcmVlID09IG51bGwgfHwgcGFydGljbGVDb2RlID09IDApCiAgICAgICAgICAgIHJldHVybiBudWxsOwoKICAgICAgICBTdHNjU3RhdGUgc3RhdGUgPSBTdHNjU3RhdGUuZ2V0KCk7CgogICAgICAgIC8vIGVtaXREQkcoIlRyYW5zbGF0aW5nIGNvbnRlbnQgbW9kZWwgZm9yICIgKyBvdXRlclR5cGUpOwogICAgICAgIC8vIGluZGVudERCRygpOwogICAgICAgIGFzc2VydChwYXJ0aWNsZUNvZGUgIT0gMCk7CgogICAgICAgIGJvb2xlYW4gaGFzQ2hpbGRyZW4gPSBmYWxzZTsKICAgICAgICBCaWdJbnRlZ2VyIG1pbk9jY3VyczsKICAgICAgICBCaWdJbnRlZ2VyIG1heE9jY3VyczsKICAgICAgICBTY2hlbWFNb2RlbEdyb3VwSW1wbCBncm91cCA9IG51bGw7CgogICAgICAgIFNjaGVtYVBhcnRpY2xlSW1wbCBzUGFydDsKCiAgICAgICAgaWYgKHBhcnRpY2xlQ29kZSA9PSBTY2hlbWFQYXJ0aWNsZS5FTEVNRU5UKQogICAgICAgIHsKICAgICAgICAgICAgaWYgKCFhbGxvd0VsdCkKICAgICAgICAgICAgICAgIHN0YXRlLmVycm9yKCJNdXN0IGJlIGEgc2VxdWVuY2UsIGNob2ljZSBvciBhbGwgaGVyZSIsIFhtbEVycm9yQ29udGV4dC5FWFBMSUNJVF9HUk9VUF9ORUVERUQsIHBhcnNlVHJlZSk7CgogICAgICAgICAgICAvLyBUT0RPOiBkZXRlY3Qgc3Vic3RpdHV0aW9uIGdyb3VwIGZvciB0aGlzIGVsZW1lbnQgYW5kIGNvbnN0cnVjdCBhIGNob2ljZQoKICAgICAgICAgICAgTG9jYWxFbGVtZW50IHBhcnNlRWx0ID0gKExvY2FsRWxlbWVudClwYXJzZVRyZWU7CiAgICAgICAgICAgIHNQYXJ0ID0gU3RzY1RyYW5zbGF0b3IudHJhbnNsYXRlRWxlbWVudChwYXJzZUVsdCwgdGFyZ2V0TmFtZXNwYWNlLCBjaGFtZWxlb24sIGFub255bW91c1R5cGVzLCBvdXRlclR5cGUpOwogICAgICAgICAgICBpZiAoc1BhcnQgPT0gbnVsbCkKICAgICAgICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgICAgICBtaW5PY2N1cnMgPSBleHRyYWN0TWluT2NjdXJzKHBhcnNlRWx0LnhnZXRNaW5PY2N1cnMoKSk7CiAgICAgICAgICAgIG1heE9jY3VycyA9IGV4dHJhY3RNYXhPY2N1cnMocGFyc2VFbHQueGdldE1heE9jY3VycygpKTsKCiAgICAgICAgICAgIFNjaGVtYVR5cGUgb2xkVHlwZSA9IChTY2hlbWFUeXBlKWVsZW1lbnRNb2RlbC5nZXQoc1BhcnQuZ2V0TmFtZSgpKTsKICAgICAgICAgICAgaWYgKG9sZFR5cGUgPT0gbnVsbCkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgZWxlbWVudE1vZGVsLnB1dChzUGFydC5nZXROYW1lKCksIHNQYXJ0LmdldFR5cGUoKSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSBpZiAoIXNQYXJ0LmdldFR5cGUoKS5lcXVhbHMob2xkVHlwZSkpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIHN0YXRlLmVycm9yKCJUeXBlIG9mICIgKyBRTmFtZUhlbHBlci5wcmV0dHkoc1BhcnQuZ2V0TmFtZSgpKSArICIgaXMgaW5jb25zaXN0ZW50IHdpdGggYW5vdGhlciBlbGVtZW50IHdpdGggdGhlIHNhbWUgbmFtZSBpbiB0aGlzIGNvbnRlbnQgbW9kZWwiLCBYbWxFcnJvckNvbnRleHQuSU5DT05TSVNURU5UX1RZUEUsIHBhcnNlVHJlZSk7CiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBlbHNlIGlmIChwYXJ0aWNsZUNvZGUgPT0gU2NoZW1hUGFydGljbGUuV0lMRENBUkQpCiAgICAgICAgewogICAgICAgICAgICBpZiAoIWFsbG93RWx0KQogICAgICAgICAgICAgICAgc3RhdGUuZXJyb3IoIk11c3QgYmUgYSBzZXF1ZW5jZSwgY2hvaWNlIG9yIGFsbCBoZXJlIiwgWG1sRXJyb3JDb250ZXh0LkVYUExJQ0lUX0dST1VQX05FRURFRCwgcGFyc2VUcmVlKTsKICAgICAgICAgICAgQW55IHBhcnNlQW55ID0gKEFueSlwYXJzZVRyZWU7CiAgICAgICAgICAgIHNQYXJ0ID0gbmV3IFNjaGVtYVBhcnRpY2xlSW1wbCgpOwogICAgICAgICAgICBzUGFydC5zZXRQYXJ0aWNsZVR5cGUoU2NoZW1hUGFydGljbGUuV0lMRENBUkQpOwogICAgICAgICAgICBRTmFtZVNldCB3Y3NldDsKICAgICAgICAgICAgTmFtZXNwYWNlTGlzdCBuc2xpc3QgPSBwYXJzZUFueS54Z2V0TmFtZXNwYWNlKCk7CiAgICAgICAgICAgIGlmIChuc2xpc3QgPT0gbnVsbCkKICAgICAgICAgICAgICAgIHdjc2V0ID0gUU5hbWVTZXQuQUxMOwogICAgICAgICAgICBlbHNlCiAgICAgICAgICAgICAgICB3Y3NldCA9IFFOYW1lU2V0LmZvcldpbGRjYXJkTmFtZXNwYWNlU3RyaW5nKG5zbGlzdC5nZXRTdHJpbmdWYWx1ZSgpLCB0YXJnZXROYW1lc3BhY2UpOwogICAgICAgICAgICBzUGFydC5zZXRXaWxkY2FyZFNldCh3Y3NldCk7CiAgICAgICAgICAgIHNQYXJ0LnNldFdpbGRjYXJkUHJvY2Vzcyh0cmFuc2xhdGVXaWxkY2FyZFByb2Nlc3MocGFyc2VBbnkueGdldFByb2Nlc3NDb250ZW50cygpKSk7CiAgICAgICAgICAgIG1pbk9jY3VycyA9IGV4dHJhY3RNaW5PY2N1cnMocGFyc2VBbnkueGdldE1pbk9jY3VycygpKTsKICAgICAgICAgICAgbWF4T2NjdXJzID0gZXh0cmFjdE1heE9jY3VycyhwYXJzZUFueS54Z2V0TWF4T2NjdXJzKCkpOwogICAgICAgIH0KICAgICAgICBlbHNlCiAgICAgICAgewogICAgICAgICAgICBHcm91cCBwYXJzZUdyb3VwID0gKEdyb3VwKXBhcnNlVHJlZTsKICAgICAgICAgICAgc1BhcnQgPSBuZXcgU2NoZW1hUGFydGljbGVJbXBsKCk7CgogICAgICAgICAgICAvLyBncmFiIG1pbi9tYXhPY2N1cnMgYmVmb3JlIGRlcmVmZXJlbmNpZ24gZ3JvdXAgcmVmCiAgICAgICAgICAgIG1pbk9jY3VycyA9IGV4dHJhY3RNaW5PY2N1cnMocGFyc2VHcm91cC54Z2V0TWluT2NjdXJzKCkpOwogICAgICAgICAgICBtYXhPY2N1cnMgPSBleHRyYWN0TWF4T2NjdXJzKHBhcnNlR3JvdXAueGdldE1heE9jY3VycygpKTsKICAgICAgICAgICAgCiAgICAgICAgICAgIGlmIChwYXJ0aWNsZUNvZGUgPT0gTU9ERUxfR1JPVVBfQ09ERSkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgUU5hbWUgcmVmID0gcGFyc2VHcm91cC5nZXRSZWYoKTsKICAgICAgICAgICAgICAgIGlmIChyZWYgPT0gbnVsbCkKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBzdGF0ZS5lcnJvcigiR3JvdXAgcmVmZXJlbmNlIG11c3QgaGF2ZSBhIHJlZiBhdHRyaWJ1dGUiLCBYbWxFcnJvckNvbnRleHQuR1JPVVBfTUlTU0lOR19SRUYsIHBhcnNlVHJlZSk7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgIGlmIChyZWRlZmluaXRpb25Gb3IgIT0gbnVsbCkKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBncm91cCA9IHN0YXRlLmZpbmRSZWRlZmluZWRNb2RlbEdyb3VwKHJlZiwgY2hhbWVsZW9uID8gdGFyZ2V0TmFtZXNwYWNlIDogbnVsbCwgcmVkZWZpbml0aW9uRm9yLmdldEdyb3VwTmFtZSgpKTsKICAgICAgICAgICAgICAgICAgICBpZiAoZ3JvdXAgIT0gbnVsbCAmJiBncm91cC5nZXROYW1lKCkuZXF1YWxzKHJlZGVmaW5pdGlvbkZvci5nZXRHcm91cE5hbWUoKSkpCiAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVkZWZpbml0aW9uRm9yLmlzU2VlblJlZGVmaW5pdGlvbigpKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGUuZXJyb3IoIkdyb3VwIHJlZGVmaW5pdGlvbiBtdXN0IHJlZmVyIHRvIHRoZSBvcmlnaW5hbCBkZWZpbml0aW9uIGF0IG1vc3Qgb25jZSIsIFhtbEVycm9yQ29udGV4dC5HRU5FUklDX0VSUk9SLCBwYXJzZVRyZWUpOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIUJpZ0ludGVnZXIuT05FLmVxdWFscyhtYXhPY2N1cnMpIHx8ICFCaWdJbnRlZ2VyLk9ORS5lcXVhbHMobWluT2NjdXJzKSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRlLmVycm9yKCJXaGVuIHJlZmVyZW5jaW5nIHRoZSBvcmlnaW5hbCBncm91cCBkZWZpbml0aW9uIGluIGEgcmVkZWZpbml0aW9uLCBtYXhPY2N1cnMgYW5kIG1pbk9jY3VycyBtdXN0IGJlIDEiLCBYbWxFcnJvckNvbnRleHQuR0VORVJJQ19FUlJPUiwgcGFyc2VUcmVlKTsKICAgICAgICAgICAgICAgICAgICAgICAgcmVkZWZpbml0aW9uRm9yLnNldFNlZW5SZWRlZmluaXRpb24odHJ1ZSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZWxzZQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGdyb3VwID0gc3RhdGUuZmluZE1vZGVsR3JvdXAocmVmLCBjaGFtZWxlb24gPyB0YXJnZXROYW1lc3BhY2UgOiBudWxsKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlmIChncm91cCA9PSBudWxsKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIHN0YXRlLm5vdEZvdW5kRXJyb3IocmVmLCBYbWxFcnJvckNvbnRleHQuTU9ERUxfR1JPVVBfTk9UX0ZPVU5ELCAoKEdyb3VwKXBhcnNlVHJlZSkueGdldFJlZigpKTsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlmIChzdGF0ZS5pc1Byb2Nlc3NpbmcoZ3JvdXApKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIHN0YXRlLmVycm9yKCJNb2RlbCBncm91cCAiICsgUU5hbWVIZWxwZXIucHJldHR5KGdyb3VwLmdldE5hbWUoKSkgKyAiIHJlZmVyZW5jZXMgaXRzZWxmIiwgWG1sRXJyb3JDb250ZXh0LkNZQ0xJQ19ERVBFTkRFTkNZLCBncm91cC5nZXRQYXJzZU9iamVjdCgpKTsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgLy8gbm8gZ28gdG8gdGhlIGNoaWxkLgogICAgICAgICAgICAgICAgWG1sQ3Vyc29yIGN1ciA9IGdyb3VwLmdldFBhcnNlT2JqZWN0KCkubmV3Q3Vyc29yKCk7CiAgICAgICAgICAgICAgICBmb3IgKGJvb2xlYW4gbW9yZSA9IGN1ci50b0ZpcnN0Q2hpbGQoKTsgbW9yZTsgbW9yZSA9IGN1ci50b05leHRTaWJsaW5nKCkpCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgcGFydGljbGVDb2RlID0gdHJhbnNsYXRlUGFydGljbGVDb2RlKGN1ci5nZXROYW1lKCkpOwogICAgICAgICAgICAgICAgICAgIGlmIChwYXJ0aWNsZUNvZGUgIT0gMCkKICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgIHBhcnNlVHJlZSA9IHBhcnNlR3JvdXAgPSAoR3JvdXApY3VyLmdldE9iamVjdCgpOwogICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpZiAocGFydGljbGVDb2RlID09IDApCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgc3RhdGUuZXJyb3IoIk1vZGVsIGdyb3VwICIgKyBRTmFtZUhlbHBlci5wcmV0dHkoZ3JvdXAuZ2V0TmFtZSgpKSArICIgaXMgZW1wdHkiLCBYbWxFcnJvckNvbnRleHQuRVhQTElDSVRfR1JPVVBfTkVFREVELCBncm91cC5nZXRQYXJzZU9iamVjdCgpKTsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlmIChwYXJ0aWNsZUNvZGUgIT0gU2NoZW1hUGFydGljbGUuQUxMICYmIHBhcnRpY2xlQ29kZSAhPSBTY2hlbWFQYXJ0aWNsZS5TRVFVRU5DRSAmJiBwYXJ0aWNsZUNvZGUgIT0gU2NoZW1hUGFydGljbGUuQ0hPSUNFKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIHN0YXRlLmVycm9yKCJNb2RlbCBncm91cCAiICsgUU5hbWVIZWxwZXIucHJldHR5KGdyb3VwLmdldE5hbWUoKSkgKyAiIGlzIG5vdCBhIHNlcXVlbmNlLCBhbGwsIG9yIGNob2ljZSIsIFhtbEVycm9yQ29udGV4dC5FWFBMSUNJVF9HUk9VUF9ORUVERUQsIGdyb3VwLmdldFBhcnNlT2JqZWN0KCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICBTdHJpbmcgbmV3VGFyZ2V0TmFtZXNwYWNlID0gZ3JvdXAuZ2V0VGFyZ2V0TmFtZXNwYWNlKCk7CiAgICAgICAgICAgICAgICBpZiAobmV3VGFyZ2V0TmFtZXNwYWNlICE9IG51bGwpCiAgICAgICAgICAgICAgICAgICAgdGFyZ2V0TmFtZXNwYWNlID0gbmV3VGFyZ2V0TmFtZXNwYWNlOwogICAgICAgICAgICB9CgogICAgICAgICAgICBzd2l0Y2ggKHBhcnRpY2xlQ29kZSkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgY2FzZSBTY2hlbWFQYXJ0aWNsZS5BTEw6CiAgICAgICAgICAgICAgICBjYXNlIFNjaGVtYVBhcnRpY2xlLlNFUVVFTkNFOgogICAgICAgICAgICAgICAgY2FzZSBTY2hlbWFQYXJ0aWNsZS5DSE9JQ0U6CiAgICAgICAgICAgICAgICAgICAgc1BhcnQuc2V0UGFydGljbGVUeXBlKHBhcnRpY2xlQ29kZSk7CiAgICAgICAgICAgICAgICAgICAgaGFzQ2hpbGRyZW4gPSB0cnVlOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwoKICAgICAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICAgICAgYXNzZXJ0KGZhbHNlKTsKICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbFN0YXRlRXhjZXB0aW9uKCk7CiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIGlmIChtYXhPY2N1cnMgIT0gbnVsbCAmJiBtaW5PY2N1cnMuY29tcGFyZVRvKG1heE9jY3VycykgPiAwKQogICAgICAgIHsKICAgICAgICAgICAgc3RhdGUuZXJyb3IoIm1heE9jY3VycyBtdXN0IG5vdCBiZSBsZXNzIHRoYW4gbWluT2NjdXJzIiwgWG1sRXJyb3JDb250ZXh0Lk1JTl9NQVhfT0NDVVJTLCBwYXJzZVRyZWUpOwogICAgICAgICAgICBtYXhPY2N1cnMgPSBtaW5PY2N1cnM7IC8vIHJlbWVkeTogcGluIG1heCB1cCB0byBtaW4KICAgICAgICB9CgogICAgICAgIGlmIChtYXhPY2N1cnMgIT0gbnVsbCAmJiBtYXhPY2N1cnMuY29tcGFyZVRvKEJpZ0ludGVnZXIuT05FKSA8IDApCiAgICAgICAgewogICAgICAgICAgICByZXR1cm4gbnVsbDsgLy8gbWF4T2NjdXJzID09IG1pbk9jY3VycyA9PSAwLCBzYW1lIGFzIG5vIHBhcnRpY2xlIGF0IGFsbC4KICAgICAgICB9CgogICAgICAgIHNQYXJ0LnNldE1pbk9jY3VycyhtaW5PY2N1cnMpOwogICAgICAgIHNQYXJ0LnNldE1heE9jY3VycyhtYXhPY2N1cnMpOwogICAgICAgIAogICAgICAgIGlmIChncm91cCAhPSBudWxsKQogICAgICAgIHsKICAgICAgICAgICAgc3RhdGUuc3RhcnRQcm9jZXNzaW5nKGdyb3VwKTsKICAgICAgICAgICAgcmVkZWZpbml0aW9uRm9yID0gbnVsbDsKICAgICAgICAgICAgaWYgKGdyb3VwLmlzUmVkZWZpbml0aW9uKCkpCiAgICAgICAgICAgICAgICByZWRlZmluaXRpb25Gb3IgPSBuZXcgUmVkZWZpbml0aW9uRm9yR3JvdXAoZ3JvdXAuZ2V0TmFtZSgpKTsKICAgICAgICB9CgogICAgICAgIGlmIChoYXNDaGlsZHJlbikKICAgICAgICB7CiAgICAgICAgICAgIFhtbEN1cnNvciBjdXIgPSBwYXJzZVRyZWUubmV3Q3Vyc29yKCk7CiAgICAgICAgICAgIExpc3QgYWNjdW11bGF0ZSA9IG5ldyBBcnJheUxpc3QoKTsKICAgICAgICAgICAgZm9yIChib29sZWFuIG1vcmUgPSBjdXIudG9GaXJzdENoaWxkKCk7IG1vcmU7IG1vcmUgPSBjdXIudG9OZXh0U2libGluZygpKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBpbnQgY29kZSA9IHRyYW5zbGF0ZVBhcnRpY2xlQ29kZShjdXIuZ2V0TmFtZSgpKTsKICAgICAgICAgICAgICAgIGlmIChjb2RlID09IDApCiAgICAgICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgICAgICBhZGRNaW51c1BvaW50bGVzc1BhcnRpY2xlcyhhY2N1bXVsYXRlLAogICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2xhdGVDb250ZW50TW9kZWwob3V0ZXJUeXBlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1ci5nZXRPYmplY3QoKSwgdGFyZ2V0TmFtZXNwYWNlLCBjaGFtZWxlb24sIGNvZGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYW5vbnltb3VzVHlwZXMsIGVsZW1lbnRNb2RlbCwgdHJ1ZSwgcmVkZWZpbml0aW9uRm9yKSwKICAgICAgICAgICAgICAgICAgICAgICAgc1BhcnQuZ2V0UGFydGljbGVUeXBlKCkpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHNQYXJ0LnNldFBhcnRpY2xlQ2hpbGRyZW4oKFNjaGVtYVBhcnRpY2xlW10pCiAgICAgICAgICAgICAgICAgICAgYWNjdW11bGF0ZS50b0FycmF5KG5ldyBTY2hlbWFQYXJ0aWNsZVthY2N1bXVsYXRlLnNpemUoKV0pKTsKICAgICAgICAgICAgY3VyLmRpc3Bvc2UoKTsKICAgICAgICB9CiAgICAgICAgCgogICAgICAgIFNjaGVtYVBhcnRpY2xlIHJlc3VsdCA9IGZpbHRlclBvaW50bGVzc1BhcnRpY2xlc0FuZFZlcmlmeUFsbFBhcnRpY2xlcyhzUGFydCwgcGFyc2VUcmVlKTsKCiAgICAgICAgaWYgKGdyb3VwICE9IG51bGwpCiAgICAgICAgewogICAgICAgICAgICBzdGF0ZS5maW5pc2hQcm9jZXNzaW5nKGdyb3VwKTsKICAgICAgICB9CiAgICAgICAgLy8gb3V0ZGVudERCRygpOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICB9CiAgICAKICAgIHN0YXRpYyBpbnQgdHJhbnNsYXRlV2lsZGNhcmRQcm9jZXNzKEFueS5Qcm9jZXNzQ29udGVudHMgcHJvY2VzcykKICAgIHsKICAgICAgICBpZiAocHJvY2VzcyA9PSBudWxsKQogICAgICAgICAgICByZXR1cm4gU2NoZW1hUGFydGljbGUuU1RSSUNUOwoKICAgICAgICBTdHJpbmcgcHJvY2Vzc1ZhbHVlID0gcHJvY2Vzcy5nZXRTdHJpbmdWYWx1ZSgpOwoKICAgICAgICBpZiAoImxheCIuZXF1YWxzKHByb2Nlc3NWYWx1ZSkpCiAgICAgICAgICAgIHJldHVybiBTY2hlbWFQYXJ0aWNsZS5MQVg7CgogICAgICAgIGlmICgic2tpcCIuZXF1YWxzKHByb2Nlc3NWYWx1ZSkpCiAgICAgICAgICAgIHJldHVybiBTY2hlbWFQYXJ0aWNsZS5TS0lQOwoKICAgICAgICByZXR1cm4gU2NoZW1hUGFydGljbGUuU1RSSUNUOwogICAgfQoKICAgIHN0YXRpYyBTY2hlbWFQYXJ0aWNsZSBmaWx0ZXJQb2ludGxlc3NQYXJ0aWNsZXNBbmRWZXJpZnlBbGxQYXJ0aWNsZXMoU2NoZW1hUGFydGljbGUgcGFydCwgWG1sT2JqZWN0IHBhcnNlVHJlZSkKICAgIHsKICAgICAgICBpZiAocGFydC5nZXRNYXhPY2N1cnMoKSAhPSBudWxsICYmIHBhcnQuZ2V0TWF4T2NjdXJzKCkuc2lnbnVtKCkgPT0gMCkKICAgICAgICAgICAgcmV0dXJuIG51bGw7CgogICAgICAgIHN3aXRjaCAocGFydC5nZXRQYXJ0aWNsZVR5cGUoKSkKICAgICAgICB7CiAgICAgICAgICAgIGNhc2UgU2NoZW1hUGFydGljbGUuU0VRVUVOQ0U6CiAgICAgICAgICAgIGNhc2UgU2NoZW1hUGFydGljbGUuQUxMOgogICAgICAgICAgICAgICAgaWYgKHBhcnQuZ2V0UGFydGljbGVDaGlsZHJlbigpLmxlbmd0aCA9PSAwKQogICAgICAgICAgICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgICAgICAgICAgaWYgKHBhcnQuaXNTaW5nbGV0b24oKSAmJiBwYXJ0LmNvdW50T2ZQYXJ0aWNsZUNoaWxkKCkgPT0gMSkKICAgICAgICAgICAgICAgICAgICByZXR1cm4gcGFydC5nZXRQYXJ0aWNsZUNoaWxkKDApOwogICAgICAgICAgICAgICAgYnJlYWs7CgogICAgICAgICAgICBjYXNlIFNjaGVtYVBhcnRpY2xlLkNIT0lDRToKICAgICAgICAgICAgICAgIGlmIChwYXJ0LmdldFBhcnRpY2xlQ2hpbGRyZW4oKS5sZW5ndGggPT0gMCAmJgogICAgICAgICAgICAgICAgICAgIHBhcnQuZ2V0TWluT2NjdXJzKCkuY29tcGFyZVRvKEJpZ0ludGVnZXIuWkVSTykgPT0gMCkKICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgICAgICAgICAgIGlmIChwYXJ0LmlzU2luZ2xldG9uKCkgJiYgcGFydC5jb3VudE9mUGFydGljbGVDaGlsZCgpID09IDEpCiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHBhcnQuZ2V0UGFydGljbGVDaGlsZCgwKTsKICAgICAgICAgICAgICAgIGJyZWFrOwoKICAgICAgICAgICAgY2FzZSBTY2hlbWFQYXJ0aWNsZS5FTEVNRU5UOgogICAgICAgICAgICBjYXNlIFNjaGVtYVBhcnRpY2xlLldJTERDQVJEOgogICAgICAgICAgICAgICAgcmV0dXJuIHBhcnQ7CgogICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgYXNzZXJ0KGZhbHNlKTsKICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsU3RhdGVFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgCiAgICAgICAgYm9vbGVhbiBpc0FsbCA9IHBhcnQuZ2V0UGFydGljbGVUeXBlKCkgPT0gU2NoZW1hUGFydGljbGUuQUxMOwogICAgICAgIAogICAgICAgIGlmIChpc0FsbCkKICAgICAgICB7CiAgICAgICAgICAgIC8vIGh0dHA6Ly93d3cudzMub3JnL1RSL3htbHNjaGVtYS0xLyNjb3MtYWxsLWxpbWl0ZWQKICAgICAgICAgICAgaWYgKHBhcnQuZ2V0TWF4T2NjdXJzKCkgPT0gbnVsbCB8fCBwYXJ0LmdldE1heE9jY3VycygpLmNvbXBhcmVUbyhCaWdJbnRlZ2VyLk9ORSkgPiAwKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBTdHNjU3RhdGUuZ2V0KCkuZXJyb3IoIkFuIGFsbCBncm91cCBtdXN0IGhhdmUgbWF4T2NjdXJzIDw9IDEiLCBYbWxFcnJvckNvbnRleHQuQUxMX0NPTlRFTlRTLCBwYXJzZVRyZWUpOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIAogICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcGFydC5jb3VudE9mUGFydGljbGVDaGlsZCgpOyBpKyspCiAgICAgICAgewogICAgICAgICAgICBTY2hlbWFQYXJ0aWNsZSBjaGlsZCA9IHBhcnQuZ2V0UGFydGljbGVDaGlsZChpKTsKICAgICAgICAgICAgaWYgKGNoaWxkLmdldFBhcnRpY2xlVHlwZSgpID09IFNjaGVtYVBhcnRpY2xlLkFMTCkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgU3RzY1N0YXRlLmdldCgpLmVycm9yKCJBbiBhbGwgZ3JvdXAgaXMgb25seSBhbGxvd2VkIGF0IHRoZSB0b3AgbGV2ZWwgb2YgdGhlIGNvbnRlbnQgbW9kZWwiLCBYbWxFcnJvckNvbnRleHQuQ0FOTk9UX0VYVEVORF9BTEwsIHBhcnNlVHJlZSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSBpZiAoaXNBbGwgJiYgKGNoaWxkLmdldFBhcnRpY2xlVHlwZSgpICE9IFNjaGVtYVBhcnRpY2xlLkVMRU1FTlQgfHwgY2hpbGQuZ2V0TWF4T2NjdXJzKCkgPT0gbnVsbCB8fCBjaGlsZC5nZXRNYXhPY2N1cnMoKS5jb21wYXJlVG8oQmlnSW50ZWdlci5PTkUpID4gMCkpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIFN0c2NTdGF0ZS5nZXQoKS5lcnJvcigiQW4gYWxsIGdyb3VwIGNhbiBjb250YWluIG9ubHkgZWxlbWVudCBwYXJ0aWNsZXMgd2l0aCBtYXhPY2N1cnMgPD0gMSIsIFhtbEVycm9yQ29udGV4dC5BTExfQ09OVEVOVFMsIHBhcnNlVHJlZSk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgCiAgICAgICAgcmV0dXJuIHBhcnQ7CiAgICB9CgogICAgc3RhdGljIHZvaWQgYWRkTWludXNQb2ludGxlc3NQYXJ0aWNsZXMoCiAgICAgICAgICAgIExpc3QgbGlzdCwgU2NoZW1hUGFydGljbGUgcGFydCwgaW50IHBhcmVudFBhcnRpY2xlVHlwZSkKICAgIHsKICAgICAgICBpZiAocGFydCA9PSBudWxsKQogICAgICAgICAgICByZXR1cm47CgogICAgICAgIHN3aXRjaCAocGFydC5nZXRQYXJ0aWNsZVR5cGUoKSkKICAgICAgICB7CiAgICAgICAgICAgIGNhc2UgU2NoZW1hUGFydGljbGUuU0VRVUVOQ0U6CiAgICAgICAgICAgICAgICBpZiAocGFyZW50UGFydGljbGVUeXBlID09IFNjaGVtYVBhcnRpY2xlLlNFUVVFTkNFICYmIHBhcnQuaXNTaW5nbGV0b24oKSkKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAvLyBlbWl0REJHKCJkcm9wcGluZyByZWR1bmRhbnQgc2VxdWVuY2UiKTsKICAgICAgICAgICAgICAgICAgICBsaXN0LmFkZEFsbChBcnJheXMuYXNMaXN0KHBhcnQuZ2V0UGFydGljbGVDaGlsZHJlbigpKSk7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CgogICAgICAgICAgICBjYXNlIFNjaGVtYVBhcnRpY2xlLkNIT0lDRToKICAgICAgICAgICAgICAgIGlmIChwYXJlbnRQYXJ0aWNsZVR5cGUgPT0gU2NoZW1hUGFydGljbGUuQ0hPSUNFICYmIHBhcnQuaXNTaW5nbGV0b24oKSkKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAvLyBlbWl0REJHKCJkcm9wcGluZyByZWR1bmRhbnQgY2hvaWNlIik7CiAgICAgICAgICAgICAgICAgICAgbGlzdC5hZGRBbGwoQXJyYXlzLmFzTGlzdChwYXJ0LmdldFBhcnRpY2xlQ2hpbGRyZW4oKSkpOwogICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgCiAgICAgICAgICAgIGNhc2UgU2NoZW1hUGFydGljbGUuQUxMOgogICAgICAgICAgICBkZWZhdWx0OiAgICAgICAgICAgICAgICAKICAgICAgICB9CiAgICAgICAgbGlzdC5hZGQocGFydCk7CiAgICB9CgogICAgc3RhdGljIE1hcCBidWlsZEF0dHJpYnV0ZVByb3BlcnR5TW9kZWxCeVFOYW1lKFNjaGVtYUF0dHJpYnV0ZU1vZGVsIGF0dHJNb2RlbCwgU2NoZW1hVHlwZSBvd25lcikKICAgIHsKICAgICAgICBNYXAgcmVzdWx0ID0gbmV3IExpbmtlZEhhc2hNYXAoKTsKICAgICAgICBTY2hlbWFMb2NhbEF0dHJpYnV0ZVtdIGF0dHJ1c2VzID0gYXR0ck1vZGVsLmdldEF0dHJpYnV0ZXMoKTsKCiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBhdHRydXNlcy5sZW5ndGg7IGkrKykKICAgICAgICAgICAgcmVzdWx0LnB1dChhdHRydXNlc1tpXS5nZXROYW1lKCksIGJ1aWxkVXNlUHJvcGVydHkoYXR0cnVzZXNbaV0sIG93bmVyKSk7CgogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICB9CgogICAgc3RhdGljIE1hcCBidWlsZENvbnRlbnRQcm9wZXJ0eU1vZGVsQnlRTmFtZShTY2hlbWFQYXJ0aWNsZSBwYXJ0LCBTY2hlbWFUeXBlIG93bmVyKQogICAgewogICAgICAgIGlmIChwYXJ0ID09IG51bGwpCiAgICAgICAgICAgIHJldHVybiBDb2xsZWN0aW9ucy5FTVBUWV9NQVA7CgogICAgICAgIGJvb2xlYW4gYXNTZXF1ZW5jZSA9IGZhbHNlOwogICAgICAgIE1hcCBtb2RlbCA9IG51bGw7CgogICAgICAgIHN3aXRjaCAocGFydC5nZXRQYXJ0aWNsZVR5cGUoKSkKICAgICAgICB7CiAgICAgICAgICAgIGNhc2UgU2NoZW1hUGFydGljbGUuQUxMOgogICAgICAgICAgICBjYXNlIFNjaGVtYVBhcnRpY2xlLlNFUVVFTkNFOgogICAgICAgICAgICAgICAgYXNTZXF1ZW5jZSA9IHRydWU7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSBTY2hlbWFQYXJ0aWNsZS5DSE9JQ0U6CiAgICAgICAgICAgICAgICBhc1NlcXVlbmNlID0gZmFsc2U7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSBTY2hlbWFQYXJ0aWNsZS5FTEVNRU5UOgogICAgICAgICAgICAgICAgbW9kZWwgPSBidWlsZEVsZW1lbnRQcm9wZXJ0eU1vZGVsKChTY2hlbWFMb2NhbEVsZW1lbnQpcGFydCwgb3duZXIpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgU2NoZW1hUGFydGljbGUuV0lMRENBUkQ6CiAgICAgICAgICAgICAgICBtb2RlbCA9IENvbGxlY3Rpb25zLkVNUFRZX01BUDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgYXNzZXJ0KGZhbHNlKTsKICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsU3RhdGVFeGNlcHRpb24oKTsKICAgICAgICB9CgogICAgICAgIGlmIChtb2RlbCA9PSBudWxsKQogICAgICAgIHsKICAgICAgICAgICAgLy8gYnVpbGQgbW9kZWwgZm9yIGNoaWxkcmVuCiAgICAgICAgICAgIG1vZGVsID0gbmV3IExpbmtlZEhhc2hNYXAoKTsKICAgICAgICAgICAgU2NoZW1hUGFydGljbGVbXSBjaGlsZHJlbiA9IHBhcnQuZ2V0UGFydGljbGVDaGlsZHJlbigpOwoKICAgICAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgLy8gaW5kZW50REJHKCk7CiAgICAgICAgICAgICAgICBNYXAgY2hpbGRNb2RlbCA9IGJ1aWxkQ29udGVudFByb3BlcnR5TW9kZWxCeVFOYW1lKGNoaWxkcmVuW2ldLCBvd25lcik7CiAgICAgICAgICAgICAgICAvLyBvdXRkZW50REJHKCk7CiAgICAgICAgICAgICAgICBmb3IgKEl0ZXJhdG9yIGogPSBjaGlsZE1vZGVsLnZhbHVlcygpLml0ZXJhdG9yKCk7IGouaGFzTmV4dCgpOyApCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgU2NoZW1hUHJvcGVydHkgaVByb3AgPSAoU2NoZW1hUHJvcGVydHkpai5uZXh0KCk7CiAgICAgICAgICAgICAgICAgICAgU2NoZW1hUHJvcGVydHlJbXBsIG9Qcm9wID0gKFNjaGVtYVByb3BlcnR5SW1wbCltb2RlbC5nZXQoaVByb3AuZ2V0TmFtZSgpKTsKICAgICAgICAgICAgICAgICAgICBpZiAob1Byb3AgPT0gbnVsbCkKICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghYXNTZXF1ZW5jZSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICgoU2NoZW1hUHJvcGVydHlJbXBsKWlQcm9wKS5zZXRNaW5PY2N1cnMoQmlnSW50ZWdlci5aRVJPKTsKICAgICAgICAgICAgICAgICAgICAgICAgbW9kZWwucHV0KGlQcm9wLmdldE5hbWUoKSwgaVByb3ApOwogICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgLy8gY29uc2lzdGVuY3kgdmVyaWZpZWQgaW4gYW4gZWFybGllciBzdGVwCiAgICAgICAgICAgICAgICAgICAgYXNzZXJ0KG9Qcm9wLmdldFR5cGUoKS5lcXVhbHMoaVByb3AuZ2V0VHlwZSgpKSk7CgogICAgICAgICAgICAgICAgICAgIG1lcmdlUHJvcGVydGllcyhvUHJvcCwgaVByb3AsIGFzU2VxdWVuY2UpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CgogICAgICAgICAgICAvLyBmaW5hbGx5IGRlYWwgd2l0aCBtaW5PY2N1cnMsIG1heE9jY3VycyBvdmVyIHdob2xlIGdyb3VwCiAgICAgICAgICAgIEJpZ0ludGVnZXIgbWluID0gcGFydC5nZXRNaW5PY2N1cnMoKTsKICAgICAgICAgICAgQmlnSW50ZWdlciBtYXggPSBwYXJ0LmdldE1heE9jY3VycygpOwoKICAgICAgICAgICAgZm9yIChJdGVyYXRvciBqID0gbW9kZWwudmFsdWVzKCkuaXRlcmF0b3IoKTsgai5oYXNOZXh0KCk7ICkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgU2NoZW1hUHJvcGVydHkgb1Byb3AgPSAoU2NoZW1hUHJvcGVydHkpai5uZXh0KCk7CiAgICAgICAgICAgICAgICBCaWdJbnRlZ2VyIG1pbk9jY3VycyA9IG9Qcm9wLmdldE1pbk9jY3VycygpOwogICAgICAgICAgICAgICAgQmlnSW50ZWdlciBtYXhPY2N1cnMgPSBvUHJvcC5nZXRNYXhPY2N1cnMoKTsKCiAgICAgICAgICAgICAgICBtaW5PY2N1cnMgPSBtaW5PY2N1cnMubXVsdGlwbHkobWluKTsKICAgICAgICAgICAgICAgIGlmIChtYXggIT0gbnVsbCAmJiBtYXguZXF1YWxzKEJpZ0ludGVnZXIuWkVSTykpCiAgICAgICAgICAgICAgICAgICAgbWF4T2NjdXJzID0gQmlnSW50ZWdlci5aRVJPOwogICAgICAgICAgICAgICAgZWxzZSBpZiAobWF4T2NjdXJzICE9IG51bGwgJiYgIW1heE9jY3Vycy5lcXVhbHMoQmlnSW50ZWdlci5aRVJPKSkKICAgICAgICAgICAgICAgICAgICBtYXhPY2N1cnMgPSBtYXggPT0gbnVsbCA/IG51bGwgOiBtYXhPY2N1cnMubXVsdGlwbHkobWF4KTsKCiAgICAgICAgICAgICAgICAoKFNjaGVtYVByb3BlcnR5SW1wbClvUHJvcCkuc2V0TWluT2NjdXJzKG1pbk9jY3Vycyk7CiAgICAgICAgICAgICAgICAoKFNjaGVtYVByb3BlcnR5SW1wbClvUHJvcCkuc2V0TWF4T2NjdXJzKG1heE9jY3Vycyk7CiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIHJldHVybiBtb2RlbDsKICAgIH0KCiAgICBzdGF0aWMgTWFwIGJ1aWxkRWxlbWVudFByb3BlcnR5TW9kZWwoU2NoZW1hTG9jYWxFbGVtZW50IGVwYXJ0LCBTY2hlbWFUeXBlIG93bmVyKQogICAgewogICAgICAgIE1hcCByZXN1bHQgPSBuZXcgSGFzaE1hcCgxKTsKCiAgICAgICAgU2NoZW1hUHJvcGVydHkgc1Byb3AgPSBidWlsZFVzZVByb3BlcnR5KGVwYXJ0LCBvd25lcik7CiAgICAgICAgcmVzdWx0LnB1dChzUHJvcC5nZXROYW1lKCksIHNQcm9wKTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgfQoKICAgIHN0YXRpYyBTY2hlbWFQcm9wZXJ0eSBidWlsZFVzZVByb3BlcnR5KFNjaGVtYUZpZWxkIHVzZSwgU2NoZW1hVHlwZSBvd25lcikKICAgIHsKICAgICAgICBTY2hlbWFQcm9wZXJ0eUltcGwgc1Byb3BJbXBsID0gbmV3IFNjaGVtYVByb3BlcnR5SW1wbCgpOwogICAgICAgIHNQcm9wSW1wbC5zZXROYW1lKHVzZS5nZXROYW1lKCkpOwogICAgICAgIHNQcm9wSW1wbC5zZXRDb250YWluZXJUeXBlUmVmKG93bmVyLmdldFJlZigpKTsKICAgICAgICBzUHJvcEltcGwuc2V0VHlwZVJlZih1c2UuZ2V0VHlwZSgpLmdldFJlZigpKTsKICAgICAgICBzUHJvcEltcGwuc2V0QXR0cmlidXRlKHVzZS5pc0F0dHJpYnV0ZSgpKTsKICAgICAgICBzUHJvcEltcGwuc2V0RGVmYXVsdCh1c2UuaXNEZWZhdWx0KCkgPyBTY2hlbWFQcm9wZXJ0eS5DT05TSVNURU5UTFkgOiBTY2hlbWFQcm9wZXJ0eS5ORVZFUik7CiAgICAgICAgc1Byb3BJbXBsLnNldEZpeGVkKHVzZS5pc0ZpeGVkKCkgPyBTY2hlbWFQcm9wZXJ0eS5DT05TSVNURU5UTFkgOiBTY2hlbWFQcm9wZXJ0eS5ORVZFUik7CiAgICAgICAgc1Byb3BJbXBsLnNldE5pbGxhYmxlKHVzZS5pc05pbGxhYmxlKCkgPyBTY2hlbWFQcm9wZXJ0eS5DT05TSVNURU5UTFkgOiBTY2hlbWFQcm9wZXJ0eS5ORVZFUik7CiAgICAgICAgc1Byb3BJbXBsLnNldERlZmF1bHRUZXh0KHVzZS5nZXREZWZhdWx0VGV4dCgpKTsKICAgICAgICBzUHJvcEltcGwuc2V0TWluT2NjdXJzKHVzZS5nZXRNaW5PY2N1cnMoKSk7CiAgICAgICAgc1Byb3BJbXBsLnNldE1heE9jY3Vycyh1c2UuZ2V0TWF4T2NjdXJzKCkpOwoKICAgICAgICBpZiAodXNlIGluc3RhbmNlb2YgU2NoZW1hTG9jYWxFbGVtZW50SW1wbCkKICAgICAgICB7CiAgICAgICAgICAgIFNjaGVtYUxvY2FsRWxlbWVudEltcGwgZWx0ID0gKFNjaGVtYUxvY2FsRWxlbWVudEltcGwpdXNlOwogICAgICAgICAgICBzUHJvcEltcGwuc2V0QWNjZXB0ZWROYW1lcyhlbHQuYWNjZXB0ZWRTdGFydE5hbWVzKCkpOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIHNQcm9wSW1wbDsKICAgIH0KCiAgICBzdGF0aWMgdm9pZCBtZXJnZVByb3BlcnRpZXMoU2NoZW1hUHJvcGVydHlJbXBsIGludG8sIFNjaGVtYVByb3BlcnR5IGZyb20sIGJvb2xlYW4gYXNTZXF1ZW5jZSkKICAgIHsKICAgICAgICAvLyBtaW5vY2N1ciwgbWF4b2NjdXIKICAgICAgICBCaWdJbnRlZ2VyIG1pbk9jY3VycyA9IGludG8uZ2V0TWluT2NjdXJzKCk7CiAgICAgICAgQmlnSW50ZWdlciBtYXhPY2N1cnMgPSBpbnRvLmdldE1heE9jY3VycygpOwogICAgICAgIGlmIChhc1NlcXVlbmNlKQogICAgICAgIHsKICAgICAgICAgICAgbWluT2NjdXJzID0gbWluT2NjdXJzLmFkZChmcm9tLmdldE1pbk9jY3VycygpKTsKICAgICAgICAgICAgaWYgKG1heE9jY3VycyAhPSBudWxsKQogICAgICAgICAgICAgICAgbWF4T2NjdXJzID0gKGZyb20uZ2V0TWF4T2NjdXJzKCkgPT0gbnVsbCA/IG51bGwgOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4T2NjdXJzLmFkZChmcm9tLmdldE1heE9jY3VycygpKSk7CiAgICAgICAgfQogICAgICAgIGVsc2UKICAgICAgICB7CiAgICAgICAgICAgIG1pbk9jY3VycyA9IG1pbk9jY3Vycy5taW4oZnJvbS5nZXRNaW5PY2N1cnMoKSk7CiAgICAgICAgICAgIGlmIChtYXhPY2N1cnMgIT0gbnVsbCkKICAgICAgICAgICAgICAgIG1heE9jY3VycyA9IChmcm9tLmdldE1heE9jY3VycygpID09IG51bGwgPyBudWxsIDoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXhPY2N1cnMubWF4KGZyb20uZ2V0TWF4T2NjdXJzKCkpKTsKICAgICAgICB9CiAgICAgICAgaW50by5zZXRNaW5PY2N1cnMobWluT2NjdXJzKTsKICAgICAgICBpbnRvLnNldE1heE9jY3VycyhtYXhPY2N1cnMpOwoKICAgICAgICAvLyBuaWxsYWJsZSwgZGVmYXVsdCwgZml4ZWQKICAgICAgICBpZiAoZnJvbS5oYXNOaWxsYWJsZSgpICE9IGludG8uaGFzTmlsbGFibGUoKSkKICAgICAgICAgICAgaW50by5zZXROaWxsYWJsZShTY2hlbWFQcm9wZXJ0eS5WQVJJQUJMRSk7CiAgICAgICAgaWYgKGZyb20uaGFzRGVmYXVsdCgpICE9IGludG8uaGFzRGVmYXVsdCgpKQogICAgICAgICAgICBpbnRvLnNldERlZmF1bHQoU2NoZW1hUHJvcGVydHkuVkFSSUFCTEUpOwogICAgICAgIGlmIChmcm9tLmhhc0ZpeGVkKCkgIT0gaW50by5oYXNGaXhlZCgpKQogICAgICAgICAgICBpbnRvLnNldEZpeGVkKFNjaGVtYVByb3BlcnR5LlZBUklBQkxFKTsKCiAgICAgICAgLy8gZGVmYXVsdCB2YWx1ZQogICAgICAgIGlmIChpbnRvLmdldERlZmF1bHRUZXh0KCkgIT0gbnVsbCkKICAgICAgICB7CiAgICAgICAgICAgIGlmIChmcm9tLmdldERlZmF1bHRUZXh0KCkgPT0gbnVsbCB8fAogICAgICAgICAgICAgICAgIWludG8uZ2V0RGVmYXVsdFRleHQoKS5lcXVhbHMoZnJvbS5nZXREZWZhdWx0VGV4dCgpKSkKICAgICAgICAgICAgICAgIGludG8uc2V0RGVmYXVsdFRleHQobnVsbCk7CiAgICAgICAgfQogICAgfQoKICAgIHN0YXRpYyBTY2hlbWFQYXJ0aWNsZVtdIGVuc3VyZVN0YXRlTWFjaGluZShTY2hlbWFQYXJ0aWNsZVtdIGNoaWxkcmVuKQogICAgewogICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgY2hpbGRyZW4ubGVuZ3RoOyBpKyspCiAgICAgICAgewogICAgICAgICAgICBidWlsZFN0YXRlTWFjaGluZShjaGlsZHJlbltpXSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBjaGlsZHJlbjsKICAgIH0KCiAgICBzdGF0aWMgdm9pZCBidWlsZFN0YXRlTWFjaGluZShTY2hlbWFQYXJ0aWNsZSBjb250ZW50TW9kZWwpCiAgICB7CiAgICAgICAgaWYgKGNvbnRlbnRNb2RlbCA9PSBudWxsKQogICAgICAgICAgICByZXR1cm47CgogICAgICAgIFNjaGVtYVBhcnRpY2xlSW1wbCBwYXJ0SW1wbCA9IChTY2hlbWFQYXJ0aWNsZUltcGwpY29udGVudE1vZGVsOwogICAgICAgIGlmIChwYXJ0SW1wbC5oYXNUcmFuc2l0aW9uTm90ZXMoKSkKICAgICAgICAgICAgcmV0dXJuOwoKICAgICAgICBRTmFtZVNldEJ1aWxkZXIgc3RhcnQgPSBuZXcgUU5hbWVTZXRCdWlsZGVyKCk7CiAgICAgICAgUU5hbWVTZXRCdWlsZGVyIGV4Y2x1ZGVuZXh0ID0gbmV3IFFOYW1lU2V0QnVpbGRlcigpOwogICAgICAgIGJvb2xlYW4gZGV0ZXJtaW5pc3RpYyA9IHRydWU7CiAgICAgICAgU2NoZW1hUGFydGljbGVbXSBjaGlsZHJlbiA9IG51bGw7CiAgICAgICAgYm9vbGVhbiBjYW5za2lwID0gKHBhcnRJbXBsLmdldE1pbk9jY3VycygpLnNpZ251bSgpID09IDApOwoKICAgICAgICBzd2l0Y2ggKHBhcnRJbXBsLmdldFBhcnRpY2xlVHlwZSgpKQogICAgICAgIHsKICAgICAgICAgICAgY2FzZSBTY2hlbWFQYXJ0aWNsZS5FTEVNRU5UOgogICAgICAgICAgICAgICAgLy8gY29tcHV0ZSBzdGFydCBhbmQgZXhjbHVkZU5leHQ7IGNhbnNraXAgaXMgYWxyZWFkeSBjb3JyZWN0CiAgICAgICAgICAgICAgICBpZiAocGFydEltcGwuaGFzVHJhbnNpdGlvblJ1bGVzKCkpCiAgICAgICAgICAgICAgICAgICAgc3RhcnQuYWRkQWxsKHBhcnRJbXBsLmFjY2VwdGVkU3RhcnROYW1lcygpKTsKICAgICAgICAgICAgICAgIGVsc2UKICAgICAgICAgICAgICAgICAgICBzdGFydC5hZGQocGFydEltcGwuZ2V0TmFtZSgpKTsKCiAgICAgICAgICAgICAgICBicmVhazsKCiAgICAgICAgICAgIGNhc2UgU2NoZW1hUGFydGljbGUuV0lMRENBUkQ6CiAgICAgICAgICAgICAgICAvLyBjb21wdXRlIHN0YXJ0IGFuZCBleGNsdWRlTmV4dDsgY2Fuc2tpcCBpcyBhbHJlYWR5IGNvcnJlY3QKICAgICAgICAgICAgICAgIHN0YXJ0LmFkZEFsbChwYXJ0SW1wbC5nZXRXaWxkY2FyZFNldCgpKTsKICAgICAgICAgICAgICAgIGJyZWFrOwoKICAgICAgICAgICAgY2FzZSBTY2hlbWFQYXJ0aWNsZS5TRVFVRU5DRToKICAgICAgICAgICAgICAgIGNoaWxkcmVuID0gZW5zdXJlU3RhdGVNYWNoaW5lKHBhcnRJbXBsLmdldFBhcnRpY2xlQ2hpbGRyZW4oKSk7CgogICAgICAgICAgICAgICAgLy8gYWRqdXN0IGNhbnNraXAgaWYgYWxsIGNoaWxkcmVuIGFyZSBza2lwcGFibGUKICAgICAgICAgICAgICAgIGNhbnNraXAgPSB0cnVlOwogICAgICAgICAgICAgICAgZm9yIChpbnQgaSA9IDA7IGNhbnNraXAgJiYgaSA8IGNoaWxkcmVuLmxlbmd0aDsgaSsrKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGlmICghKGNoaWxkcmVuW2ldKS5pc1NraXBwYWJsZSgpKQogICAgICAgICAgICAgICAgICAgICAgICBjYW5za2lwID0gZmFsc2U7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgIC8vIGJ1YmJsZSB1cCBub25kZXRlcm1pbmlzdGljIGJpdAogICAgICAgICAgICAgICAgZm9yIChpbnQgaSA9IDA7IGRldGVybWluaXN0aWMgJiYgaSA8IGNoaWxkcmVuLmxlbmd0aDsgaSsrKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGlmICghKChTY2hlbWFQYXJ0aWNsZUltcGwpY2hpbGRyZW5baV0pLmlzRGV0ZXJtaW5pc3RpYygpKQogICAgICAgICAgICAgICAgICAgICAgICBkZXRlcm1pbmlzdGljID0gZmFsc2U7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgIC8vIHZlcmlmeSBkZXRlcm1pbmlzdGljIGFuZCBjb21wdXRlIGV4Y2x1ZGVOZXh0IHNldAogICAgICAgICAgICAgICAgZm9yIChpbnQgaSA9IDE7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBleGNsdWRlbmV4dC5hZGRBbGwoKChTY2hlbWFQYXJ0aWNsZUltcGwpY2hpbGRyZW5baSAtIDFdKS5nZXRFeGNsdWRlTmV4dFNldCgpKTsKICAgICAgICAgICAgICAgICAgICBpZiAoZGV0ZXJtaW5pc3RpYyAmJiAhZXhjbHVkZW5leHQuaXNEaXNqb2ludCgoY2hpbGRyZW5baV0pLmFjY2VwdGVkU3RhcnROYW1lcygpKSkKICAgICAgICAgICAgICAgICAgICAgICAgZGV0ZXJtaW5pc3RpYyA9IGZhbHNlOwogICAgICAgICAgICAgICAgICAgIGlmICgoY2hpbGRyZW5baV0pLmlzU2tpcHBhYmxlKCkpCiAgICAgICAgICAgICAgICAgICAgICAgIGV4Y2x1ZGVuZXh0LmFkZEFsbCgoY2hpbGRyZW5baV0pLmFjY2VwdGVkU3RhcnROYW1lcygpKTsKICAgICAgICAgICAgICAgICAgICBlbHNlCiAgICAgICAgICAgICAgICAgICAgICAgIGV4Y2x1ZGVuZXh0LmNsZWFyKCk7CiAgICAgICAgICAgICAgICB9CgogICAgICAgICAgICAgICAgLy8gbmV4dCwgY29tcHV0ZSBzdGFydCBzZXQKICAgICAgICAgICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgY2hpbGRyZW4ubGVuZ3RoOyBpKyspCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgc3RhcnQuYWRkQWxsKChjaGlsZHJlbltpXSkuYWNjZXB0ZWRTdGFydE5hbWVzKCkpOwogICAgICAgICAgICAgICAgICAgIGlmICghKGNoaWxkcmVuW2ldKS5pc1NraXBwYWJsZSgpKQogICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwoKICAgICAgICAgICAgY2FzZSBTY2hlbWFQYXJ0aWNsZS5DSE9JQ0U6CiAgICAgICAgICAgICAgICBjaGlsZHJlbiA9IGVuc3VyZVN0YXRlTWFjaGluZShwYXJ0SW1wbC5nZXRQYXJ0aWNsZUNoaWxkcmVuKCkpOwoKICAgICAgICAgICAgICAgIC8vIGFkanVzdCBjYW5za2lwIGlmIGFueSBjaGlsZHJlbiBhcmUgc2tpcHBhYmxlCiAgICAgICAgICAgICAgICBjYW5za2lwID0gZmFsc2U7CiAgICAgICAgICAgICAgICBmb3IgKGludCBpID0gMDsgIWNhbnNraXAgJiYgaSA8IGNoaWxkcmVuLmxlbmd0aDsgaSsrKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGlmICgoY2hpbGRyZW5baV0pLmlzU2tpcHBhYmxlKCkpCiAgICAgICAgICAgICAgICAgICAgICAgIGNhbnNraXAgPSB0cnVlOwogICAgICAgICAgICAgICAgfQoKICAgICAgICAgICAgICAgIC8vIGJ1YmJsZSB1cCBub25kZXRlcm1pbmlzdGljIGJpdAogICAgICAgICAgICAgICAgZm9yIChpbnQgaSA9IDA7IGRldGVybWluaXN0aWMgJiYgaSA8IGNoaWxkcmVuLmxlbmd0aDsgaSsrKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGlmICghKChTY2hlbWFQYXJ0aWNsZUltcGwpY2hpbGRyZW5baV0pLmlzRGV0ZXJtaW5pc3RpYygpKQogICAgICAgICAgICAgICAgICAgICAgICBkZXRlcm1pbmlzdGljID0gZmFsc2U7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgIC8vIGNvbXB1dGUgc3RhcnQgYW5kIGV4Y2x1ZGVOZXh0IHNldHMsIHZlcmlmeSBkZXRlcm1pbmlzdGljCiAgICAgICAgICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IGNoaWxkcmVuLmxlbmd0aDsgaSsrKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGlmIChkZXRlcm1pbmlzdGljICYmICFzdGFydC5pc0Rpc2pvaW50KChjaGlsZHJlbltpXSkuYWNjZXB0ZWRTdGFydE5hbWVzKCkpKQogICAgICAgICAgICAgICAgICAgICAgICBkZXRlcm1pbmlzdGljID0gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgc3RhcnQuYWRkQWxsKChjaGlsZHJlbltpXSkuYWNjZXB0ZWRTdGFydE5hbWVzKCkpOwogICAgICAgICAgICAgICAgICAgIGV4Y2x1ZGVuZXh0LmFkZEFsbCgoKFNjaGVtYVBhcnRpY2xlSW1wbCljaGlsZHJlbltpXSkuZ2V0RXhjbHVkZU5leHRTZXQoKSk7CiAgICAgICAgICAgICAgICB9CgogICAgICAgICAgICAgICAgYnJlYWs7CgogICAgICAgICAgICBjYXNlIFNjaGVtYVBhcnRpY2xlLkFMTDoKICAgICAgICAgICAgICAgIGNoaWxkcmVuID0gZW5zdXJlU3RhdGVNYWNoaW5lKHBhcnRJbXBsLmdldFBhcnRpY2xlQ2hpbGRyZW4oKSk7CgogICAgICAgICAgICAgICAgLy8gYWRqdXN0IGNhbnNraXAgaWYgYWxsIGNoaWxkcmVuIGFyZSBza2lwcGFibGUKICAgICAgICAgICAgICAgIGNhbnNraXAgPSB0cnVlOwogICAgICAgICAgICAgICAgZm9yIChpbnQgaSA9IDA7ICFjYW5za2lwICYmIGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBpZiAoIShjaGlsZHJlbltpXSkuaXNTa2lwcGFibGUoKSkKICAgICAgICAgICAgICAgICAgICAgICAgY2Fuc2tpcCA9IGZhbHNlOwogICAgICAgICAgICAgICAgfQoKICAgICAgICAgICAgICAgIC8vIGJ1YmJsZSB1cCBub25kZXRlcm1pbmlzdGljIGJpdAogICAgICAgICAgICAgICAgZm9yIChpbnQgaSA9IDA7IGRldGVybWluaXN0aWMgJiYgaSA8IGNoaWxkcmVuLmxlbmd0aDsgaSsrKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGlmICghKChTY2hlbWFQYXJ0aWNsZUltcGwpY2hpbGRyZW5baV0pLmlzRGV0ZXJtaW5pc3RpYygpKQogICAgICAgICAgICAgICAgICAgICAgICBkZXRlcm1pbmlzdGljID0gZmFsc2U7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgIC8vIGNvbXB1dGUgc3RhcnQgYW5kIGV4Y2x1ZGVOZXh0IHNldHMsIHZlcmlmeSBkZXRlcm1pbmlzdGljCiAgICAgICAgICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IGNoaWxkcmVuLmxlbmd0aDsgaSsrKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGlmIChkZXRlcm1pbmlzdGljICYmICFzdGFydC5pc0Rpc2pvaW50KChjaGlsZHJlbltpXSkuYWNjZXB0ZWRTdGFydE5hbWVzKCkpKQogICAgICAgICAgICAgICAgICAgICAgICBkZXRlcm1pbmlzdGljID0gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgc3RhcnQuYWRkQWxsKChjaGlsZHJlbltpXSkuYWNjZXB0ZWRTdGFydE5hbWVzKCkpOwogICAgICAgICAgICAgICAgICAgIGV4Y2x1ZGVuZXh0LmFkZEFsbCgoKFNjaGVtYVBhcnRpY2xlSW1wbCljaGlsZHJlbltpXSkuZ2V0RXhjbHVkZU5leHRTZXQoKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpZiAoY2Fuc2tpcCkKICAgICAgICAgICAgICAgICAgICBleGNsdWRlbmV4dC5hZGRBbGwoc3RhcnQpOwoKICAgICAgICAgICAgICAgIGJyZWFrOwoKICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgIC8vIHdpbGRjYXJkLCBhbGwgY2FzZXMgbnlpCiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbFN0YXRlRXhjZXB0aW9uKCJVbnJlY29nbml6ZWQgc2NoZW1hIHBhcnRpY2xlIik7CiAgICAgICAgfQoKICAgICAgICAvLyBhcHBseSBsb29waW5nIGxvZ2ljCgogICAgICAgIEJpZ0ludGVnZXIgbWluT2NjdXJzID0gcGFydEltcGwuZ2V0TWluT2NjdXJzKCk7CiAgICAgICAgQmlnSW50ZWdlciBtYXhPY2N1cnMgPSBwYXJ0SW1wbC5nZXRNYXhPY2N1cnMoKTsKICAgICAgICBib29sZWFuIGNhbmxvb3AgPSAobWF4T2NjdXJzID09IG51bGwgfHwgbWF4T2NjdXJzLmNvbXBhcmVUbyhCaWdJbnRlZ2VyLk9ORSkgPiAwKTsKICAgICAgICBib29sZWFuIHZhcmxvb3AgPSAobWF4T2NjdXJzID09IG51bGwgfHwgbWluT2NjdXJzLmNvbXBhcmVUbyhtYXhPY2N1cnMpIDwgMCk7CgogICAgICAgIGlmIChjYW5sb29wICYmIGRldGVybWluaXN0aWMgJiYgIWV4Y2x1ZGVuZXh0LmlzRGlzam9pbnQoc3RhcnQpKQogICAgICAgIHsKICAgICAgICAgICAgLy8gd2UgaGF2ZSBhIHBvc3NpYmxlIGxvb3Bpbmcgbm9uZGV0ZXJtaW5pc20uCiAgICAgICAgICAgIC8vIGxldCdzIHRha2Ugc29tZSB0aW1lIG5vdyB0byBzZWUgaWYgaXQncyBhY3R1YWxseSBjYXVzZWQKICAgICAgICAgICAgLy8gYnkgbm9uLXVuaXF1ZS1wYXJ0aWNsZS1hdHRyaWJ1dGUgb3Igbm90LgogICAgICAgICAgICBRTmFtZVNldCBzdXNwZWN0U2V0ID0gZXhjbHVkZW5leHQuaW50ZXJzZWN0KHN0YXJ0KTsKICAgICAgICAgICAgCiAgICAgICAgICAgIC8vIGNvbXB1dGUgdGhlIHNldCBvZiBhbGwgcGFydGljbGVzIHRoYXQgY291bGQgc3RhcnQgdGhpcyBncm91cAogICAgICAgICAgICBNYXAgc3RhcnRNYXAgPSBuZXcgSGFzaE1hcCgpOwogICAgICAgICAgICBwYXJ0aWNsZXNNYXRjaGluZ1N0YXJ0KHBhcnRJbXBsLCBzdXNwZWN0U2V0LCBzdGFydE1hcCwgbmV3IFFOYW1lU2V0QnVpbGRlcigpKTsKICAgICAgICAgICAgCiAgICAgICAgICAgIC8vIGNvbXB1dGUgdGhlIHNldCBvZiBhbGwgcGFydGljbGVzIHRoYXQgY291bGQgaGF2ZSBiZWVuIHJlcGVhdGVkIHJhdGhlciB0aGFuIGVuZGluZyB0aGlzIGdyb3VwCiAgICAgICAgICAgIE1hcCBhZnRlck1hcCA9IG5ldyBIYXNoTWFwKCk7CiAgICAgICAgICAgIHBhcnRpY2xlc01hdGNoaW5nQWZ0ZXIocGFydEltcGwsIHN1c3BlY3RTZXQsIGFmdGVyTWFwLCBuZXcgUU5hbWVTZXRCdWlsZGVyKCksIHRydWUpOwogICAgICAgICAgICAKICAgICAgICAgICAgLy8gc2VlIGlmIHdlIGNhbiBmaW5kIGEgbWVtYmVyIG9mIGFmdGVyIHRoYXQgaXMgbm90IGEgbWVtYmVyIG9mIHN0YXJ0CiAgICAgICAgICAgIC8vIGlmIHdlIGNhbiwgdGhlbiBwYXJ0aWNsZSBhdHRyaWJ1dGlvbiBpcyBub3QgdW5pcXVlCiAgICAgICAgICAgIGRldGVybWluaXN0aWMgPSBhZnRlck1hcFN1YnN1bWVkQnlTdGFydE1hcChzdGFydE1hcCwgYWZ0ZXJNYXApOwogICAgICAgIH0KCiAgICAgICAgaWYgKHZhcmxvb3ApCiAgICAgICAgICAgIGV4Y2x1ZGVuZXh0LmFkZEFsbChzdGFydCk7CgogICAgICAgIGNhbnNraXAgPSBjYW5za2lwIHx8IG1pbk9jY3Vycy5zaWdudW0oKSA9PSAwOwoKICAgICAgICBwYXJ0SW1wbC5zZXRUcmFuc2l0aW9uUnVsZXMoc3RhcnQudG9RTmFtZVNldCgpLCBjYW5za2lwKTsKICAgICAgICBwYXJ0SW1wbC5zZXRUcmFuc2l0aW9uTm90ZXMoZXhjbHVkZW5leHQudG9RTmFtZVNldCgpLCBkZXRlcm1pbmlzdGljKTsKICAgIH0KICAgIAogICAgcHJpdmF0ZSBzdGF0aWMgYm9vbGVhbiBhZnRlck1hcFN1YnN1bWVkQnlTdGFydE1hcChNYXAgc3RhcnRNYXAsIE1hcCBhZnRlck1hcCkKICAgIHsKICAgICAgICBpZiAoYWZ0ZXJNYXAuc2l6ZSgpID4gc3RhcnRNYXAuc2l6ZSgpKQogICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgCiAgICAgICAgaWYgKGFmdGVyTWFwLmlzRW1wdHkoKSkKICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgCiAgICAgICAgZm9yIChJdGVyYXRvciBpID0gc3RhcnRNYXAua2V5U2V0KCkuaXRlcmF0b3IoKTsgaS5oYXNOZXh0KCk7ICkKICAgICAgICB7CiAgICAgICAgICAgIFNjaGVtYVBhcnRpY2xlIHBhcnQgPSAoU2NoZW1hUGFydGljbGUpaS5uZXh0KCk7CiAgICAgICAgICAgIGlmIChwYXJ0LmdldFBhcnRpY2xlVHlwZSgpID09IFNjaGVtYVBhcnRpY2xlLldJTERDQVJEKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBpZiAoYWZ0ZXJNYXAuY29udGFpbnNLZXkocGFydCkpCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgUU5hbWVTZXQgc3RhcnRTZXQgPSAoUU5hbWVTZXQpc3RhcnRNYXAuZ2V0KHBhcnQpOwogICAgICAgICAgICAgICAgICAgIFFOYW1lU2V0IGFmdGVyU2V0ID0gKFFOYW1lU2V0KWFmdGVyTWFwLmdldChwYXJ0KTsKICAgICAgICAgICAgICAgICAgICBpZiAoIXN0YXJ0U2V0LmNvbnRhaW5zQWxsKGFmdGVyU2V0KSkKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIGFmdGVyTWFwLnJlbW92ZShwYXJ0KTsKICAgICAgICAgICAgaWYgKGFmdGVyTWFwLmlzRW1wdHkoKSkKICAgICAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0KICAgICAgICByZXR1cm4gKGFmdGVyTWFwLmlzRW1wdHkoKSk7CiAgICB9CiAgICAKICAgIHByaXZhdGUgc3RhdGljIHZvaWQgcGFydGljbGVzTWF0Y2hpbmdTdGFydChTY2hlbWFQYXJ0aWNsZSBwYXJ0LCBRTmFtZVNldFNwZWNpZmljYXRpb24gc3VzcGVjdFNldCwgTWFwIHJlc3VsdCwgUU5hbWVTZXRCdWlsZGVyIGVsaW1pbmF0ZSkKICAgIHsKICAgICAgICBzd2l0Y2ggKHBhcnQuZ2V0UGFydGljbGVUeXBlKCkpCiAgICAgICAgewogICAgICAgICAgICBjYXNlIFNjaGVtYVBhcnRpY2xlLkVMRU1FTlQ6CiAgICAgICAgICAgICAgICBpZiAoIXN1c3BlY3RTZXQuY29udGFpbnMocGFydC5nZXROYW1lKCkpKQogICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgIHJlc3VsdC5wdXQocGFydCwgbnVsbCk7CiAgICAgICAgICAgICAgICBlbGltaW5hdGUuYWRkKHBhcnQuZ2V0TmFtZSgpKTsKICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgIAogICAgICAgICAgICBjYXNlIFNjaGVtYVBhcnRpY2xlLldJTERDQVJEOgogICAgICAgICAgICAgICAgaWYgKHN1c3BlY3RTZXQuaXNEaXNqb2ludChwYXJ0LmdldFdpbGRjYXJkU2V0KCkpKQogICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgIHJlc3VsdC5wdXQocGFydCwgcGFydC5nZXRXaWxkY2FyZFNldCgpLmludGVyc2VjdChzdXNwZWN0U2V0KSk7CiAgICAgICAgICAgICAgICBlbGltaW5hdGUuYWRkQWxsKHBhcnQuZ2V0V2lsZGNhcmRTZXQoKSk7CiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAKICAgICAgICAgICAgY2FzZSBTY2hlbWFQYXJ0aWNsZS5DSE9JQ0U6CiAgICAgICAgICAgIGNhc2UgU2NoZW1hUGFydGljbGUuQUxMOgogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIFNjaGVtYVBhcnRpY2xlW10gY2hpbGRyZW4gPSBwYXJ0LmdldFBhcnRpY2xlQ2hpbGRyZW4oKTsKICAgICAgICAgICAgICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IGNoaWxkcmVuLmxlbmd0aDsgaSsrKQogICAgICAgICAgICAgICAgICAgICAgICBwYXJ0aWNsZXNNYXRjaGluZ1N0YXJ0KGNoaWxkcmVuW2ldLCBzdXNwZWN0U2V0LCByZXN1bHQsIGVsaW1pbmF0ZSk7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgCiAgICAgICAgICAgIGNhc2UgU2NoZW1hUGFydGljbGUuU0VRVUVOQ0U6CiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgU2NoZW1hUGFydGljbGVbXSBjaGlsZHJlbiA9IHBhcnQuZ2V0UGFydGljbGVDaGlsZHJlbigpOwogICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZHJlbi5sZW5ndGggPT0gMCkKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgIGlmICghY2hpbGRyZW5bMF0uaXNTa2lwcGFibGUoKSkKICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgIHBhcnRpY2xlc01hdGNoaW5nU3RhcnQoY2hpbGRyZW5bMF0sIHN1c3BlY3RTZXQsIHJlc3VsdCwgZWxpbWluYXRlKTsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBRTmFtZVNldEJ1aWxkZXIgcmVtYWluaW5nU3VzcGVjdHMgPSBuZXcgUU5hbWVTZXRCdWlsZGVyKHN1c3BlY3RTZXQpOwogICAgICAgICAgICAgICAgICAgIFFOYW1lU2V0QnVpbGRlciBzdXNwZWN0c1RvRWxpbWluYXRlID0gbmV3IFFOYW1lU2V0QnVpbGRlcigpOwogICAgICAgICAgICAgICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgY2hpbGRyZW4ubGVuZ3RoOyBpKyspCiAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICBwYXJ0aWNsZXNNYXRjaGluZ1N0YXJ0KGNoaWxkcmVuW2ldLCByZW1haW5pbmdTdXNwZWN0cywgcmVzdWx0LCBzdXNwZWN0c1RvRWxpbWluYXRlKTsKICAgICAgICAgICAgICAgICAgICAgICAgZWxpbWluYXRlLmFkZEFsbChzdXNwZWN0c1RvRWxpbWluYXRlKTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFjaGlsZHJlbltpXS5pc1NraXBwYWJsZSgpKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICByZW1haW5pbmdTdXNwZWN0cy5yZW1vdmVBbGwoc3VzcGVjdHNUb0VsaW1pbmF0ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyZW1haW5pbmdTdXNwZWN0cy5pc0VtcHR5KCkpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgIHN1c3BlY3RzVG9FbGltaW5hdGUuY2xlYXIoKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KICAgIAogICAgcHJpdmF0ZSBzdGF0aWMgdm9pZCBwYXJ0aWNsZXNNYXRjaGluZ0FmdGVyKFNjaGVtYVBhcnRpY2xlIHBhcnQsIFFOYW1lU2V0U3BlY2lmaWNhdGlvbiBzdXNwZWN0U2V0LCBNYXAgcmVzdWx0LCBRTmFtZVNldEJ1aWxkZXIgZWxpbWluYXRlLCBib29sZWFuIHRvcCkKICAgIHsKICAgICAgICByZWN1cnNlOiBzd2l0Y2ggKHBhcnQuZ2V0UGFydGljbGVUeXBlKCkpCiAgICAgICAgewogICAgICAgICAgICBjYXNlIFNjaGVtYVBhcnRpY2xlLkNIT0lDRToKICAgICAgICAgICAgY2FzZSBTY2hlbWFQYXJ0aWNsZS5BTEw6CiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgU2NoZW1hUGFydGljbGVbXSBjaGlsZHJlbiA9IHBhcnQuZ2V0UGFydGljbGVDaGlsZHJlbigpOwogICAgICAgICAgICAgICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgY2hpbGRyZW4ubGVuZ3RoOyBpKyspCiAgICAgICAgICAgICAgICAgICAgICAgIHBhcnRpY2xlc01hdGNoaW5nQWZ0ZXIoY2hpbGRyZW5baV0sIHN1c3BlY3RTZXQsIHJlc3VsdCwgZWxpbWluYXRlLCBmYWxzZSk7CiAgICAgICAgICAgICAgICAgICAgYnJlYWsgcmVjdXJzZTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIAogICAgICAgICAgICBjYXNlIFNjaGVtYVBhcnRpY2xlLlNFUVVFTkNFOgogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIFNjaGVtYVBhcnRpY2xlW10gY2hpbGRyZW4gPSBwYXJ0LmdldFBhcnRpY2xlQ2hpbGRyZW4oKTsKICAgICAgICAgICAgICAgICAgICBpZiAoY2hpbGRyZW4ubGVuZ3RoID09IDApCiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrIHJlY3Vyc2U7CiAgICAgICAgICAgICAgICAgICAgaWYgKCFjaGlsZHJlbltjaGlsZHJlbi5sZW5ndGggLSAxXS5pc1NraXBwYWJsZSgpKQogICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgcGFydGljbGVzTWF0Y2hpbmdBZnRlcihjaGlsZHJlblswXSwgc3VzcGVjdFNldCwgcmVzdWx0LCBlbGltaW5hdGUsIGZhbHNlKTsKICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWsgcmVjdXJzZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgUU5hbWVTZXRCdWlsZGVyIHJlbWFpbmluZ1N1c3BlY3RzID0gbmV3IFFOYW1lU2V0QnVpbGRlcihzdXNwZWN0U2V0KTsKICAgICAgICAgICAgICAgICAgICBRTmFtZVNldEJ1aWxkZXIgc3VzcGVjdHNUb0VsaW1pbmF0ZSA9IG5ldyBRTmFtZVNldEJ1aWxkZXIoKTsKICAgICAgICAgICAgICAgICAgICBmb3IgKGludCBpID0gY2hpbGRyZW4ubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pCiAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICBwYXJ0aWNsZXNNYXRjaGluZ0FmdGVyKGNoaWxkcmVuW2ldLCByZW1haW5pbmdTdXNwZWN0cywgcmVzdWx0LCBzdXNwZWN0c1RvRWxpbWluYXRlLCBmYWxzZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGVsaW1pbmF0ZS5hZGRBbGwoc3VzcGVjdHNUb0VsaW1pbmF0ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghY2hpbGRyZW5baV0uaXNTa2lwcGFibGUoKSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrIHJlY3Vyc2U7CiAgICAgICAgICAgICAgICAgICAgICAgIHJlbWFpbmluZ1N1c3BlY3RzLnJlbW92ZUFsbChzdXNwZWN0c1RvRWxpbWluYXRlKTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlbWFpbmluZ1N1c3BlY3RzLmlzRW1wdHkoKSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrIHJlY3Vyc2U7CiAgICAgICAgICAgICAgICAgICAgICAgIHN1c3BlY3RzVG9FbGltaW5hdGUuY2xlYXIoKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgYnJlYWsgcmVjdXJzZTsKICAgICAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIGlmICghdG9wKQogICAgICAgIHsKICAgICAgICAgICAgQmlnSW50ZWdlciBtaW5PY2N1cnMgPSBwYXJ0LmdldE1pbk9jY3VycygpOwogICAgICAgICAgICBCaWdJbnRlZ2VyIG1heE9jY3VycyA9IHBhcnQuZ2V0TWF4T2NjdXJzKCk7CiAgICAgICAgICAgIGJvb2xlYW4gdmFybG9vcCA9IChtYXhPY2N1cnMgPT0gbnVsbCB8fCBtaW5PY2N1cnMuY29tcGFyZVRvKG1heE9jY3VycykgPCAwKTsKICAgICAgICAgICAgaWYgKHZhcmxvb3ApCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIHBhcnRpY2xlc01hdGNoaW5nU3RhcnQocGFydCwgc3VzcGVjdFNldCwgcmVzdWx0LCBlbGltaW5hdGUpOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKICAgIHByaXZhdGUgc3RhdGljIGNsYXNzIENvZGVGb3JOYW1lRW50cnkKICAgIHsKICAgICAgICBDb2RlRm9yTmFtZUVudHJ5KFFOYW1lIG5hbWUsIGludCBjb2RlKQogICAgICAgICAgICB7IHRoaXMubmFtZSA9IG5hbWU7IHRoaXMuY29kZSA9IGNvZGU7IH0KICAgICAgICBwdWJsaWMgUU5hbWUgbmFtZTsKICAgICAgICBwdWJsaWMgaW50IGNvZGU7CiAgICB9CgogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgaW50IE1PREVMX0dST1VQX0NPREUgPSAxMDA7CgogICAgcHJpdmF0ZSBzdGF0aWMgQ29kZUZvck5hbWVFbnRyeVtdIHBhcnRpY2xlQ29kZXMgPSBuZXcgQ29kZUZvck5hbWVFbnRyeVtdCiAgICB7CiAgICAgICAgbmV3IENvZGVGb3JOYW1lRW50cnkoUU5hbWVIZWxwZXIuZm9yTE5TKCJhbGwiLCAiaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEiKSwgU2NoZW1hUGFydGljbGUuQUxMKSwKICAgICAgICBuZXcgQ29kZUZvck5hbWVFbnRyeShRTmFtZUhlbHBlci5mb3JMTlMoInNlcXVlbmNlIiwgImh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hIiksIFNjaGVtYVBhcnRpY2xlLlNFUVVFTkNFKSwKICAgICAgICBuZXcgQ29kZUZvck5hbWVFbnRyeShRTmFtZUhlbHBlci5mb3JMTlMoImNob2ljZSIsICJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYSIpLCBTY2hlbWFQYXJ0aWNsZS5DSE9JQ0UpLAogICAgICAgIG5ldyBDb2RlRm9yTmFtZUVudHJ5KFFOYW1lSGVscGVyLmZvckxOUygiZWxlbWVudCIsICJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYSIpLCBTY2hlbWFQYXJ0aWNsZS5FTEVNRU5UKSwKICAgICAgICBuZXcgQ29kZUZvck5hbWVFbnRyeShRTmFtZUhlbHBlci5mb3JMTlMoImFueSIsICJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYSIpLCBTY2hlbWFQYXJ0aWNsZS5XSUxEQ0FSRCksCiAgICAgICAgbmV3IENvZGVGb3JOYW1lRW50cnkoUU5hbWVIZWxwZXIuZm9yTE5TKCJncm91cCIsICJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYSIpLCBNT0RFTF9HUk9VUF9DT0RFKSwKICAgIH07CgogICAgcHJpdmF0ZSBzdGF0aWMgTWFwIHBhcnRpY2xlQ29kZU1hcCA9IGJ1aWxkUGFydGljbGVDb2RlTWFwKCk7CgogICAgcHJpdmF0ZSBzdGF0aWMgTWFwIGJ1aWxkUGFydGljbGVDb2RlTWFwKCkKICAgIHsKICAgICAgICBNYXAgcmVzdWx0ID0gbmV3IEhhc2hNYXAoKTsKICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IHBhcnRpY2xlQ29kZXMubGVuZ3RoOyBpKyspCiAgICAgICAgICAgIHJlc3VsdC5wdXQocGFydGljbGVDb2Rlc1tpXS5uYW1lLCAgbmV3IEludGVnZXIocGFydGljbGVDb2Rlc1tpXS5jb2RlKSk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgIH0KCiAgICBwcml2YXRlIHN0YXRpYyBpbnQgdHJhbnNsYXRlUGFydGljbGVDb2RlKEdyb3VwIHBhcnNlRWcpCiAgICB7CiAgICAgICAgaWYgKHBhcnNlRWcgPT0gbnVsbCkKICAgICAgICAgICAgcmV0dXJuIDA7CiAgICAgICAgcmV0dXJuIHRyYW5zbGF0ZVBhcnRpY2xlQ29kZShwYXJzZUVnLm5ld0N1cnNvcigpLmdldE5hbWUoKSk7CiAgICB9CgogICAgcHJpdmF0ZSBzdGF0aWMgaW50IHRyYW5zbGF0ZVBhcnRpY2xlQ29kZShRTmFtZSBuYW1lKQogICAgewogICAgICAgIEludGVnZXIgcmVzdWx0ID0gKEludGVnZXIpcGFydGljbGVDb2RlTWFwLmdldChuYW1lKTsKICAgICAgICBpZiAocmVzdWx0ID09IG51bGwpCiAgICAgICAgICAgIHJldHVybiAwOwogICAgICAgIHJldHVybiByZXN1bHQuaW50VmFsdWUoKTsKICAgIH0KCiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBpbnQgQVRUUklCVVRFX0NPREUgPSAxMDA7CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBpbnQgQVRUUklCVVRFX0dST1VQX0NPREUgPSAxMDE7CiAgICBwcml2YXRlIHN0YXRpYyBmaW5hbCBpbnQgQU5ZX0FUVFJJQlVURV9DT0RFID0gMTAyOwoKICAgIHByaXZhdGUgc3RhdGljIENvZGVGb3JOYW1lRW50cnlbXSBhdHRyaWJ1dGVDb2RlcyA9IG5ldyBDb2RlRm9yTmFtZUVudHJ5W10KICAgIHsKICAgICAgICBuZXcgQ29kZUZvck5hbWVFbnRyeShRTmFtZUhlbHBlci5mb3JMTlMoImF0dHJpYnV0ZSIsICJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYSIpLCBBVFRSSUJVVEVfQ09ERSksCiAgICAgICAgbmV3IENvZGVGb3JOYW1lRW50cnkoUU5hbWVIZWxwZXIuZm9yTE5TKCJhdHRyaWJ1dGVHcm91cCIsICJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYSIpLCBBVFRSSUJVVEVfR1JPVVBfQ09ERSksCiAgICAgICAgbmV3IENvZGVGb3JOYW1lRW50cnkoUU5hbWVIZWxwZXIuZm9yTE5TKCJhbnlBdHRyaWJ1dGUiLCAiaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEiKSwgQU5ZX0FUVFJJQlVURV9DT0RFKSwKICAgIH07CgogICAgcHJpdmF0ZSBzdGF0aWMgTWFwIGF0dHJpYnV0ZUNvZGVNYXAgPSBidWlsZEF0dHJpYnV0ZUNvZGVNYXAoKTsKCiAgICBwcml2YXRlIHN0YXRpYyBNYXAgYnVpbGRBdHRyaWJ1dGVDb2RlTWFwKCkKICAgIHsKICAgICAgICBNYXAgcmVzdWx0ID0gbmV3IEhhc2hNYXAoKTsKICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IGF0dHJpYnV0ZUNvZGVzLmxlbmd0aDsgaSsrKQogICAgICAgICAgICByZXN1bHQucHV0KGF0dHJpYnV0ZUNvZGVzW2ldLm5hbWUsICBuZXcgSW50ZWdlcihhdHRyaWJ1dGVDb2Rlc1tpXS5jb2RlKSk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgIH0KCiAgICBzdGF0aWMgaW50IHRyYW5zbGF0ZUF0dHJpYnV0ZUNvZGUoUU5hbWUgY3VycmVudE5hbWUpCiAgICB7CiAgICAgICAgSW50ZWdlciByZXN1bHQgPSAoSW50ZWdlcilhdHRyaWJ1dGVDb2RlTWFwLmdldChjdXJyZW50TmFtZSk7CiAgICAgICAgaWYgKHJlc3VsdCA9PSBudWxsKQogICAgICAgICAgICByZXR1cm4gMDsKICAgICAgICByZXR1cm4gcmVzdWx0LmludFZhbHVlKCk7CiAgICB9CgoKfQo=