PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/Pgo8IURPQ1RZUEUgczEgU1lTVEVNICIuLi8uLi9zdHlsZS9kdGQvZG9jdW1lbnQuZHRkIj4KPCEtLSAKICogVGhlIEFwYWNoZSBTb2Z0d2FyZSBMaWNlbnNlLCBWZXJzaW9uIDEuMQogKgogKgogKiBDb3B5cmlnaHQgKGMpIDIwMDEgVGhlIEFwYWNoZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLiAgQWxsIHJpZ2h0cwogKiByZXNlcnZlZC4KICoKICogUmVkaXN0cmlidXRpb24gYW5kIHVzZSBpbiBzb3VyY2UgYW5kIGJpbmFyeSBmb3Jtcywgd2l0aCBvciB3aXRob3V0CiAqIG1vZGlmaWNhdGlvbiwgYXJlIHBlcm1pdHRlZCBwcm92aWRlZCB0aGF0IHRoZSBmb2xsb3dpbmcgY29uZGl0aW9ucwogKiBhcmUgbWV0OgogKgogKiAxLiBSZWRpc3RyaWJ1dGlvbnMgb2Ygc291cmNlIGNvZGUgbXVzdCByZXRhaW4gdGhlIGFib3ZlIGNvcHlyaWdodAogKiAgICBub3RpY2UsIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIuCiAqCiAqIDIuIFJlZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9ybSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUgY29weXJpZ2h0CiAqICAgIG5vdGljZSwgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lciBpbgogKiAgICB0aGUgZG9jdW1lbnRhdGlvbiBhbmQvb3Igb3RoZXIgbWF0ZXJpYWxzIHByb3ZpZGVkIHdpdGggdGhlCiAqICAgIGRpc3RyaWJ1dGlvbi4KICoKICogMy4gVGhlIGVuZC11c2VyIGRvY3VtZW50YXRpb24gaW5jbHVkZWQgd2l0aCB0aGUgcmVkaXN0cmlidXRpb24sCiAqICAgIGlmIGFueSwgbXVzdCBpbmNsdWRlIHRoZSBmb2xsb3dpbmcgYWNrbm93bGVkZ21lbnQ6CiAqICAgICAgICJUaGlzIHByb2R1Y3QgaW5jbHVkZXMgc29mdHdhcmUgZGV2ZWxvcGVkIGJ5IHRoZQogKiAgICAgICAgQXBhY2hlIFNvZnR3YXJlIEZvdW5kYXRpb24gKGh0dHA6Ly93d3cuYXBhY2hlLm9yZy8pLiIKICogICAgQWx0ZXJuYXRlbHksIHRoaXMgYWNrbm93bGVkZ21lbnQgbWF5IGFwcGVhciBpbiB0aGUgc29mdHdhcmUgaXRzZWxmLAogKiAgICBpZiBhbmQgd2hlcmV2ZXIgc3VjaCB0aGlyZC1wYXJ0eSBhY2tub3dsZWRnbWVudHMgbm9ybWFsbHkgYXBwZWFyLgogKgogKiA0LiBUaGUgbmFtZXMgIlhhbGFuIiBhbmQgIkFwYWNoZSBTb2Z0d2FyZSBGb3VuZGF0aW9uIiBtdXN0CiAqICAgIG5vdCBiZSB1c2VkIHRvIGVuZG9yc2Ugb3IgcHJvbW90ZSBwcm9kdWN0cyBkZXJpdmVkIGZyb20gdGhpcwogKiAgICBzb2Z0d2FyZSB3aXRob3V0IHByaW9yIHdyaXR0ZW4gcGVybWlzc2lvbi4gRm9yIHdyaXR0ZW4KICogICAgcGVybWlzc2lvbiwgcGxlYXNlIGNvbnRhY3QgYXBhY2hlQGFwYWNoZS5vcmcuCiAqCiAqIDUuIFByb2R1Y3RzIGRlcml2ZWQgZnJvbSB0aGlzIHNvZnR3YXJlIG1heSBub3QgYmUgY2FsbGVkICJBcGFjaGUiLAogKiAgICBub3IgbWF5ICJBcGFjaGUiIGFwcGVhciBpbiB0aGVpciBuYW1lLCB3aXRob3V0IHByaW9yIHdyaXR0ZW4KICogICAgcGVybWlzc2lvbiBvZiB0aGUgQXBhY2hlIFNvZnR3YXJlIEZvdW5kYXRpb24uCiAqCiAqIFRISVMgU09GVFdBUkUgSVMgUFJPVklERUQgYGBBUyBJUycnIEFORCBBTlkgRVhQUkVTU0VEIE9SIElNUExJRUQKICogV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRSBJTVBMSUVEIFdBUlJBTlRJRVMKICogT0YgTUVSQ0hBTlRBQklMSVRZIEFORCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBUkUKICogRElTQ0xBSU1FRC4gIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBBUEFDSEUgU09GVFdBUkUgRk9VTkRBVElPTiBPUgogKiBJVFMgQ09OVFJJQlVUT1JTIEJFIExJQUJMRSBGT1IgQU5ZIERJUkVDVCwgSU5ESVJFQ1QsIElOQ0lERU5UQUwsCiAqIFNQRUNJQUwsIEVYRU1QTEFSWSwgT1IgQ09OU0VRVUVOVElBTCBEQU1BR0VTIChJTkNMVURJTkcsIEJVVCBOT1QKICogTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0YgU1VCU1RJVFVURSBHT09EUyBPUiBTRVJWSUNFUzsgTE9TUyBPRgogKiBVU0UsIERBVEEsIE9SIFBST0ZJVFM7IE9SIEJVU0lORVNTIElOVEVSUlVQVElPTikgSE9XRVZFUiBDQVVTRUQgQU5ECiAqIE9OIEFOWSBUSEVPUlkgT0YgTElBQklMSVRZLCBXSEVUSEVSIElOIENPTlRSQUNULCBTVFJJQ1QgTElBQklMSVRZLAogKiBPUiBUT1JUIChJTkNMVURJTkcgTkVHTElHRU5DRSBPUiBPVEhFUldJU0UpIEFSSVNJTkcgSU4gQU5ZIFdBWSBPVVQKICogT0YgVEhFIFVTRSBPRiBUSElTIFNPRlRXQVJFLCBFVkVOIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GCiAqIFNVQ0ggREFNQUdFLgogKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQogKgogKiBUaGlzIHNvZnR3YXJlIGNvbnNpc3RzIG9mIHZvbHVudGFyeSBjb250cmlidXRpb25zIG1hZGUgYnkgbWFueQogKiBpbmRpdmlkdWFscyBvbiBiZWhhbGYgb2YgdGhlIEFwYWNoZSBTb2Z0d2FyZSBGb3VuZGF0aW9uIGFuZCB3YXMKICogb3JpZ2luYWxseSBiYXNlZCBvbiBzb2Z0d2FyZSBjb3B5cmlnaHQgKGMpIDIwMDEsIFN1bgogKiBNaWNyb3N5c3RlbXMuLCBodHRwOi8vd3d3LnN1bi5jb20uICBGb3IgbW9yZQogKiBpbmZvcm1hdGlvbiBvbiB0aGUgQXBhY2hlIFNvZnR3YXJlIEZvdW5kYXRpb24sIHBsZWFzZSBzZWUKICogPGh0dHA6Ly93d3cuYXBhY2hlLm9yZy8+LgogLS0+CjxzMSB0aXRsZT0iVGhlIFRyYW5zbGV0IEFQSSAmYW1wOyBUckFYIj4KPHA+PHJlZj5CeTwvcmVmPiA8anVtcCBocmVmPSJtYWlsdG86dG9kZC5taWxsZXJAZWFzdC5zdW4uY29tIj5HLiBUb2RkIE1pbGxlcjwvanVtcD4gLXVwZGF0ZWQgTWF5IDExLCAyMDAxPC9wPgo8dWw+CiAgPGxpPjxsaW5rIGFuY2hvcj0iYWJzdHJhY3QiPkFic3RyYWN0PC9saW5rPjwvbGk+CiAgPGxpPjxsaW5rIGFuY2hvcj0idHJheCI+VHJBWDwvbGluaz48L2xpPgogIDxsaT48bGluayBhbmNob3I9ImludGVncmF0ZSI+VHJhbnNsZXQgSW50ZWdyYXRpb248L2xpbms+PC9saT4KICA8bGk+PGxpbmsgYW5jaG9yPSJmYWN0b3J5Ij5TQVhUcmFuc2Zvcm1lckZhY3RvcnkgZm9yIFRyYW5zbGV0czwvbGluaz48L2xpPgogIDxsaT48bGluayBhbmNob3I9InRyYW5zZm9ybSI+QWJzdHJhY3RUcmFuc2xldCB0cmFuc2Zvcm0oKSBtZXRob2Q8L2xpbms+PC9saT4KICA8bGk+PGxpbmsgYW5jaG9yPSJjb25jbHVzaW9uIj5Db25jbHVzaW9uPC9saW5rPjwvbGk+CiAgPGxpPjxsaW5rIGFuY2hvcj0iYXBwZW5kaXgiPkFwcGVuZGl4PC9saW5rPjwvbGk+ICAgICAgCjwvdWw+CjxwPlNlZSBhbHNvOiA8anVtcCBocmVmPSIuLi94c2x0Y191c2FnZS5odG1sI2FwaSI+Q2FsbGluZyBYU0xUQyB3aXRoIHRoZSBUckFYL0pBWFAgQVBJPC9qdW1wPjwvcD4KPGFuY2hvciBuYW1lPSJhYnN0cmFjdCIvPgo8czIgdGl0bGU9IkFic3RyYWN0Ij4KPHA+VGhpcyBkb2N1bWVudCBkZXNjcmliZXMgd2hhdCBJIGhhdmUgc28gZmFyIGFzIGEgcHJvdG90eXBlIGZvciBpbnRlZ3JhdGluZwpUcmFuc2xldHMgd2l0aCB0aGUgSkFYUCBUckFYLiBJbiBhIG51dHNoZWxsLCBhIG5ldyBUcmFuc2Zvcm1lciBmYWN0b3J5CmNsYXNzIGhhcyBiZSB3cml0dGVuIHRoYXQgZXh0ZW5kcyB0aGUgSkFYUCBTQVhUcmFuc2Zvcm1lckZhY3RvcnkgY2xhc3MuClRoZSBuZXdmYWN0b3J5IGRlbGl2ZXJzIFRyYW5zbGV0cyBhcyBUcmFuc2Zvcm1lcnMsIGFuZCBjcmVhdGVzIFRlbXBsYXRlcy4KQ2FsbGluZyB0aGUgVHJhbnNmb3JtZXIgdHJhbnNmb3JtKCkgbWV0aG9kIHdpbGwgY2F1c2UgdGhlIGdpdmVuIFhNTApkb2N1bWVudCB0byBiZSB0cmFuc2Zvcm1lZCBieSBhIHRyYW5zbGV0IHRoYXQgaGFzIGJlZW4gY29tcGlsZWQgZnJvbSB0aGUKc3VwcGxpZWQgc3R5bGVzaGVldC4gVGhlIHN3aXRjaCB0aGF0IGRldGVybWluZXMgd2hhdCBYU0xUIHByb2Nlc3NvciBnZXRzCnRvIHRyYW5zZm9ybSB0aGUgWE1MIGRvY3VtZW50IGlzIGJhc2VkIG9uIHRoZSB2YWx1ZSBvZiBhIEpBWFAgc3lzdGVtCnByb3BlcnR5IGZvciB0aGUgVHJhbnNmb3JtZXJzIGZhY3RvcnkuPC9wPgo8L3MyPjxhbmNob3IgbmFtZT0idHJheCIvPgo8czIgdGl0bGU9IlRyQVgiPgo8cD5UaGUgSmF2YSBBUEkgZm9yIFhNTCBQcm9jZXNzaW5nIChKQVhQKSBpbmNsdWRlcyBhbiBYU0xUIGZyYW1ld29yayBiYXNlZCBvbiB0aGUKVHJhbnNmb3JtYXRpb24gQVBJIGZvciBYTUwgKFRyQVgpLiBJbiBhIHR5cGljYWwgSkFYUCB0cmFuc2Zvcm1hdGlvbiBhcHBsaWNhdGlvbgp0aGUgc3RlcHMgaW52b2x2ZWQgaW4gdHJhbnNmb3JtaW5nIGFuIFhNTCBkb2N1bWVudCB3aXRoIGFuIFhTTFQgc3R5bGVzaGVldCBhcmU6ICgxKQpjcmVhdGUgYW4gaW5zdGFuY2Ugb2YgdGhlIFRyYW5zZm9ybWVyRmFjdG9yeSBjbGFzcywgKDIpIGZyb20gdGhlIGZhY3RvcnkgaW5zdGFuY2UgYW5kCmEgZ2l2ZW4gWFNMVCBzdHlsZXNoZWV0LCBjcmVhdGUgYSBuZXcgVHJhbnNmb3JtZXIgb2JqZWN0LCAoMykgY2FsbCB0aGUgVHJhbnNmb3JtZXIKb2JqZWN0cyB0cmFuc2Zvcm0oKSBtZXRob2Qgb24gYSBnaXZlbiBYTUwgZG9jdW1lbnQgYW5kIGEgc3BlY2lmaWVkIFJlc3VsdCBvYmplY3QuCkFsdGVybmF0aXZlbHksIG9uZSBjb3VsZCBhbHNvIGFzayB0aGUgaW5zdGFuY2Ugb2YgdGhlIFRyYW5zZm9ybWVyRmFjdG9yeSBmb3IKYSBUZW1wbGF0ZXMgb2JqZWN0IGdpdmVuIGFuIFhTTFQgc3R5bGVzaGVldC4gRnJvbSB0aGUgVGVtcGxhdGVzIG9iamVjdCwgYSBuZXcKVHJhbnNmb3JtZXIgY2FuIGJlIGNyZWF0ZWQsIGFuZCBhZ2FpbiwgaXRzIHRyYW5zZm9ybSgpIG1ldGhvZCBjYW4gYmUgY2FsbGVkIHdpdGgKYW4gWE1MIGRvY3VtZW50IGFuZCBzcGVjaWZpZWQgUmVzdWx0IG9iamVjdC48L3A+CjxwPlRoZSBjb2RlIGJlbG93IGlsbHVzdHJhdGVzIGEgc2ltcGxlIEpBWFAgdHJhbnNmb3JtYXRpb24gYXBwbGljYXRpb24gKFByb3RvLmphdmEpCnRoYXQgY3JlYXRlcyB0aGUgVHJhbnNmb3JtZXIgZGlyZWN0bHkuPC9wPgo8c291cmNlPmltcG9ydCBqYXZheC54bWwudHJhbnNmb3JtLnN0cmVhbS5TdHJlYW1Tb3VyY2U7CmltcG9ydCBqYXZheC54bWwudHJhbnNmb3JtLnN0cmVhbS5TdHJlYW1SZXN1bHQ7CmltcG9ydCBqYXZheC54bWwudHJhbnNmb3JtLlRyYW5zZm9ybWVyOwppbXBvcnQgamF2YXgueG1sLnRyYW5zZm9ybS5UcmFuc2Zvcm1lckZhY3Rvcnk7CgpwdWJsaWMgY2xhc3MgUHJvdG8gewogIHB1YmxpYyBzdGF0aWMgdm9pZCBtYWluKFN0cmluZ1tdIGFyZ3MpewogICAgUHJvdG8gYXBwID0gbmV3IFByb3RvKCk7CiAgICBhcHAucnVuKGFyZ3MpOwogIH0KCiAgcHVibGljIHZvaWQgcnVuKFN0cmluZ1tdIGFyZ3MpewogICAgaWYgKGFyZ3MubGVuZ3RoICE9IDIpIHsKICAgICAgdXNhZ2UoKTsKICAgIH0KICAgIFN0cmluZyBpbnB1dEZpbGVuYW1lID0gYXJnc1swXTsKICAgIFN0cmluZyBzdHlsZXNoZWV0ID0gYXJnc1sxXTsKICAgIFRyYW5zZm9ybWVyIHRyYW5zZm9ybWVyOwogICAgVHJhbnNmb3JtZXJGYWN0b3J5IGZhY3RvcnkgPSBUcmFuc2Zvcm1lckZhY3RvcnkubmV3SW5zdGFuY2UoKTsKICAgIHRyeSB7CiAgICAgIHRyYW5zZm9ybWVyID0gZmFjdG9yeS5uZXdUcmFuc2Zvcm1lcihuZXcgU3RyZWFtU291cmNlKHN0eWxlc2hlZXQpKTsKICAgICAgdHJhbnNmb3JtZXIudHJhbnNmb3JtKG5ldyBTdHJlYW1Tb3VyY2UoaW5wdXRGaWxlbmFtZSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXcgU3RyZWFtUmVzdWx0KFN5c3RlbS5vdXQpKTsKICAgIH0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CiAgICAgIC8vIG5vdGhpbmcuLi4KICAgIH0KICB9CgogIHB1YmxpYyB2b2lkIHVzYWdlKCkgewogICAgU3lzdGVtLmVyci5wcmludGxuKAogICAgICAgIlVzYWdlOiBydW4gJmx0O3htbF9maWxlJmd0OyAmbHQ7eHNsX2ZpbGUmZ3Q7Iik7CiAgICBTeXN0ZW0uZXhpdCgxKTsKICB9Cn08L3NvdXJjZT4KPHA+VGhlIHVzZSBvZiBUZW1wbGF0ZXMgaXMgdXNlZnVsIHdoZW4gbXVsdGlwbGUgaW5zdGFuY2VzIG9mIHRoZSBzYW1lIHRyYW5zZm9ybWVyCmFyZSBuZWVkZWQuIEZvciBleGFtcGxlIHRyYW5zZm9ybWluZyBtdWx0aXBsZSBkb2N1bWVudHMgYnkgdGhlIHNhbWUgdHJhbnNmb3JtZXIsCmVhY2ggd29ya2luZyBpbiBhIHNlcGFyYXRlIHRocmVhZC4gSW4gdGhpcyBjYXNlLCB0aGUgVHJhbnNmb3JtZXJGYWN0b3J5IGlzIHVzZWQgdG8KY3JlYXRlIGEgVGVtcGxhdGVzIG9iamVjdCBmb3IgYSBnaXZlbiBzdHlsZXNoZWV0LiBFYWNoIFRyYW5zZm9ybWVyIGluc3RhbmNlIGlzIHRoZW4KY3JlYXRlZCBieSB0aGUgVGVtcGxhdGVzIG9iamVjdC4gSW4gdGhpcyB3YXkgdGhlIFRlbXBsYXRlcyBvYmplY3QgY2FuIGNvbXBpbGUgdGhlCnN0eWxlc2hlZXQgb25jZSwgYW5kIGVhY2ggdGltZSBhIG5ldyBpbnN0YW5jZSBvZiB0aGUgdHJhbnNmb3JtZXIgaXMgYXNrZWQgZm9yLCBhIGNsb25lIGlzCnByb3ZpZGVkIHJhdGhlciB0aGFuIHJlY29tcGlsZSB0aGUgc3R5bGVzaGVldCBhZ2FpbiBhbmQgYWdhaW4uIFRoZSBQcm90byBjbGFzcyBhYm92ZQp3b3VsZCBiZSBtb2RpZmllZCBhcyBmb2xsb3dzOjwvcD4KPHNvdXJjZT50cnkgewogIFRlbXBsYXRlcyB0ZW1wbGF0ZXMgPSBmYWN0b3J5Lm5ld1RlbXBsYXRlcyhuZXcgU3RyZWFtU291cmNlKHN0eWxlc2hlZXQpKTsKICB0cmFuc2Zvcm1lciA9IHRlbXBsYXRlcy5uZXdUcmFuc2Zvcm1lcigpOwogIHRyYW5zZm9ybWVyLnRyYW5zZm9ybShuZXcgU3RyZWFtU291cmNlKGlucHV0RmlsZW5hbWUpLAogICAgICAgICAgICAgICAgICAgICAgICBuZXcgU3RyZWFtUmVzdWx0KFN5c3RlbS5vdXQpKTsKfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKICAvLyBub3RoaW5nLi4uCn08L3NvdXJjZT4KPHA+VGhlIEpBWFAgVHJhbnNmb3JtZXJGYWN0b3J5IGlzIGNvbmZpZ3VyYWJsZS4gVGhlIEFQSSBzdXBwb3J0cyBjb25maWd1cmluZyB0aGUKZmFjdG9yeSB0bzogKDEpIHVzZSBhdHRyaWJ1dGVzIHdoaWNoIGFyZSBwYXNzZWQgZG93biB0byB0aGUgdW5kZXJseWluZyBYU0wgcHJvY2Vzc29yLAp0aGVzZSBhcmUgdmVuZG9yIGRlcGVuZGVudCwgKDIpIHJlZ2lzdGVyIGFuIEVycm9yTGlzdGVuZXIgdGhhdCBwcm92aWRlcyBjYWxsYmFja3MKdG8gaGFuZGxlIGVycm9yIGFuZCB3YXJuaW5nIG1lc3NhZ2UgZ2VuZXJhdGVkIGJ5IHRoZSBYU0wgcHJvY2Vzc29yLCAoMykgcmVnaXN0ZXIKYW4gVVJJUmVzb2x2ZXIgd2hpY2ggY2FuIGJlIHVzZWQgdG8gcmVzb2x2ZSBVUklzIGVuY291bnRlcmVkIGluIHhzbDppbmNsdWRlLAp4c2w6aW1wb3J0LGFuZGRvY3VtZW50KCkgZnVuY3Rpb25zLjwvcD4KPHA+VGhlIEpBWFAgVHJhbnNmb3JtZXJGYWN0b3J5IGNhbiBiZSBxdWVyaWVkIGF0IHJ1bnRtZSB0byBkaXNjb3ZlciB3aGF0IGZlYXR1cmVzCml0IHN1cHBvcnRzLiBGb3IgZXhhbXBsZSwgYW4gYXBwbGljYXRpb24gbWlnaHQgd2FudCB0byBrbm93IGlmIGEgcGFydGljdWxhciBmYWN0b3J5CmltcGxlbWVudGF0aW9uIHN1cHBvcnRzIHRoZSB1c2Ugb2YgU0FYIGV2ZW50cyBhcyBhIHNvdXJjZSwgb3Igd2hldGhlciBpdCBjYW4gd3JpdGUKb3V0IHRyYW5zZm9ybWF0aW9uIHJlc3VsdHMgYXMgYSBET00uIFRoZSBmYWN0b3J5IEFQSSBxdWVyaWVzIHdpdGggdGhlIGdldEZlYXR1cmUoKQptZXRob2QuIEluIHRoZSBQcm90byBjb2RlIGFib3ZlLCBJIGNvdWxkIGFkZCB0aGUgZm9sbG93aW5nIGNvZGUgYmVmb3JlIHRoZSB0cnktY2F0Y2gKYmxvY2s6PC9wPgo8c291cmNlPmlmICghKGZhY3RvcnkuZ2V0RmVhdHVyZShTdHJlYW1Tb3VyY2UuRkVBVFVSRSkpIHx8CiAgICAhKGZhY3RvcnkuZ2V0RmVhdHVyZShTdHJlYW1SZXN1bHQuRkVBVFVSRSkpKSB7CiAgICAgICBTeXN0ZW0uZXJyLnByaW50bG4oCiAgICAgICAgICJTdHJlYW0gU291cmNlL1Jlc3VsdCBub3Qgc3VwcG9ydGVkIGJ5IFRyYW5zZm9ybWVyIEZhY3RvcnlcbiIgKwogICAgICAgICAiZXhpdGluZy4iKTsKICAgICAgIFN5c3RlbS5leGl0KDEpOwp9PC9zb3VyY2U+CjwvczI+PGFuY2hvciBuYW1lPSJpbnRlZ3JhdGUiLz4KPHMyIHRpdGxlPSJUcmFuc2xldCBJbnRlZ3JhdGlvbiI+CjxwPlRoZSBjcnV4IG9mIHRoZSBpbnRlZ3JhdGlvbiBzdHJhdGVneSBpcyB0aGUgcGx1Z2dhYmxlIFRyYW5zZm9ybWVyRmFjdG9yeSBjbGFzcy4gVGhlCkpBWFAgc3BlY2lmaWVzIHRoYXQgdGhlIGFjdHVhbCBUcmFuc2Zvcm1lckZhY3RvcnkgaW1wbGVtZW50YXRpb24gYmUgY29udHJvbGxlZCBieSB0aGUKYSBKYXZhIHN5c3RlbSBwcm9wZXJ0eSAoamF2YXgueG1sLnRyYW5zZm9ybWVyLlRyYW5zZm9ybWVyRmFjdG9yeSkgLiBUaGlzIHN5c3RlbSBwcm9wZXJ0eSBjYW4gYmUgc3BlY2lmaWVkIGluIHRoZSB1c3VhbCB3YXlzLCBmb3IKZXhhbXBsZSBpbiBhIHByb3BlcnRpZXMgZmlsZSBvciBvbiB0aGUgY29tbWFuZCBsaW5lIGFzIGEgLUQgb3B0aW9ucGFzc2VkIHRvIHRoZWphdmEKZW5naW5lIGl0c2VsZi4gVGhlIHN0cmF0ZWd5IGludm9sdmVzIHdyaXRpbmcgYSBUcmFuc2Zvcm1lckZhY3RvcnkgZm9yIFRyYW5zbGV0cy4KSW4gdGhlIEpBWFAgdGhlIFRyYW5zZm9ybWVyRmFjdG9yeSBpcyBhbiBhYnN0cmFjdCBjbGFzcy4gSW4gWGFsYW4sIHRoZSBzeXN0ZW0KcHJvcGVydHkgc3BlY2lmaWVzIHRoZSBpbXBsZW1lbnRhdGlvbiBjbGFzcyBUcmFuc2Zvcm1lckZhY3RvcnlJbXBsIChvcmcuYXBhY2hlLnhhbGFuLnByb2Nlc3Nvci5UcmFuc2Zvcm1lckZhY3RvcnlJbXBsKS4KIFRoaXMgaW1wbGVtZW50YXRpb24gaXMgYW4gZXh0ZW5zaW9uIG9mIHRoZSBhYnN0cmFjdCBTQVhUcmFuc2Zvcm1lckZhY3RvcnkgY2xhc3MsIHdoaWNoIGluCnR1cm4gaXMgYW4gZXh0ZW5zaW9uIG9mIHRoZSBhYnN0cmFjdCBUcmFuc2Zvcm1lckZhY3RvcnkgY2xhc3MgKGphdmF4LnhtbC50cmFuc2Zvcm0uc2F4LlNBWFRyYW5zZm9ybWVyRmFjdG9yeSkuPC9wPgo8cD5JbiB0aGlzIHByb3RvdHlwZSBpbnRlZ3JhdGlvbiBJIGhhdmUgY29uc3RydWN0ZWQgYW4gWFNMVEMgVHJhbnNmb3JtZXJGYWN0b3J5IGFzCmFuIGV4dGVuc2lvbiBvZiB0aGUgYWJzdHJhY3QgU0FYVHJhbnNmb3JtZXJGYWN0b3J5IGNsYXNzLjwvcD4KCjwvczI+PGFuY2hvciBuYW1lPSJmYWN0b3J5Ii8+CjxzMiB0aXRsZT0iU0FYVHJhbnNmb3JtZXJGYWN0b3J5IGZvciBUcmFuc2xldHMiPgo8cD5UaGUgcHJvdG90eXBlIFhTTFRDIFRyYW5zZm9ybWVyRmFjdG9yeSBuZWVkcyB0byBhY2NvbXBsaXNoIHRoZSBmb2xsb3dpbmc6PC9wPgogPHVsPgogICA8bGk+PGxpbmsgYW5jaG9yPSJzYXh0cmFuc2Zvcm1lcmZhY3RvcnkiPkltcGxlbWVudCB0aGUgYWJzdHJhY3QgbWV0aG9kcyBvZiB0aGUgU0FYVHJhbnNmb3JtZXJGYWN0b3J5IGNsYXNzPC9saW5rPjwvbGk+CiAgIDxsaT48bGluayBhbmNob3I9InRyYW5zZm9ybWVyZmFjdG9yeSI+SW1wbGVtZW50IHRoZSBhYnN0cmFjdCBtZXRob2RzIG9mIHRoZSBUcmFuc2Zvcm1lckZhY3RvcnkgY2xhc3M8L2xpbms+PC9saT48L3VsPgo8YW5jaG9yIG5hbWU9InNheHRyYW5zZm9ybWVyZmFjdG9yeSIvPgo8czMgdGl0bGU9IlNBWFRyYW5zZm9ybWVyRmFjdG9yeSBNZXRob2RzIj4KCjxwPlRoZSBtZXRob2RzIG9mIHRoZSBhYnN0cmFjdCBTQVhUcmFuc2Zvcm1lckZhY3RvcnkgY2xhc3MgaGF2ZSBiZWVuIHN0dWJiZWQgb3V0IGFzCmZvbGxvd3MuPC9wPgo8c291cmNlPnB1YmxpYyBUZW1wbGF0ZXNIYW5kbGVyIG5ld1RlbXBsYXRlc0hhbmRsZXIoKSB7IHJldHVybiBudWxsOyB9CnB1YmxpYyBUcmFuc2Zvcm1lckhhbmRsZXIgbmV3VHJhbnNmb3JtZXJIYW5kbGVyKCkgeyByZXR1cm4gbnVsbDsgfQpwdWJsaWMgVHJhbnNmb3JtZXJIYW5kbGVyIG5ld1RyYW5zZm9ybWVySGFuZGxlcihTb3VyY2Ugc3JjKSB7CnJldHVybiBudWxsOwp9CnB1YmxpYyBUcmFuc2Zvcm1lckhhbmRsZXIgbmV3VHJhbnNmb3JtZXJIYW5kbGVyKFRlbXBsYXRlcyB0ZW1wbGF0ZXMpIHsKcmV0dXJuIG51bGw7Cn0KcHVibGljIFhNTEZpbHRlciBuZXdYTUxGaWx0ZXIoU291cmNlIHNyYykgeyByZXR1cm4gbnVsbDsgfQpwdWJsaWMgWE1MRmlsdGVyIG5ld1hNTEZpbHRlcihUZW1wbGF0ZXMgdGVtcGxhdGVzKSB7IHJldHVybiBudWxsOyB9PC9zb3VyY2U+CjxwPlRoZXNlIHN0dWJiZWQgb3V0IG1ldGhvZHMgd2lsbCBuZWVkIHRvIGJlIHJlcGxhY2VkIHdpdGggcmVhbCBpbXBsZW1lbnRhdGlvbnMuPC9wPgo8L3MzPjxhbmNob3IgbmFtZT0idHJhbnNmb3JtZXJmYWN0b3J5Ii8+CjxzMyB0aXRsZT0iVHJhbnNmb3JtZXJGYWN0b3J5IE1ldGhvZHMiPgo8cD5UaGUgbWV0aG9kcyBvZiB0aGUgYWJzdHJhY3QgVHJhbnNmb3JtZXJGYWN0b3J5IGNsYXNzIGhhdmUgYmVlbiBzdHViYmVkIG91dCBhcwpmb2xsb3dzOjwvcD4KPHNvdXJjZT5wdWJsaWMgRXJyb3JMaXN0ZW5lciBnZXRFcnJvckxpc3RlbmVyKCkgeyByZXR1cm4gbnVsbDsgfQpwdWJsaWMgdm9pZCBzZXRFcnJvckxpc3RlbmVyKEVycm9yTGlzdGVuZXIgbGlzdGVuZXIpIHsgfQpwdWJsaWMgT2JqZWN0IGdldEF0dHJpYnV0ZShTdHJpbmcgbmFtZSkgeyByZXR1cm4gbnVsbDsgfQpwdWJsaWMgdm9pZCBzZXRBdHRyaWJ1dGUoU3RyaW5nIG5hbWUsIE9iamVjdCB2YWx1ZSkgeyB9CnB1YmxpYyBib29sZWFuIGdldEZlYXR1cmUoU3RyaW5nIG5hbWUpIHsgcmV0dXJuIGZhbHNlOyB9CnB1YmxpYyBVUklSZXNvbHZlciBnZXRVUklSZXNvbHZlcigpIHsgcmV0dXJuIG51bGw7IH0KcHVibGljIHZvaWQgc2V0VVJJUmVzb2x2ZXIoVVJJUmVzb2x2ZXIgcmVzb2x2ZXIpIHsgfQpwdWJsaWMgU291cmNlIGdldEFzc29jaWF0ZWRTdHlsZXNoZWV0KFNvdXJjZSBzcmMsIFN0cmluZyBtZWRpYSwKU3RyaW5nIHRpdGxlLCBTdHJpbmcgY2hhcnNldCkgeyByZXR1cm4gbnVsbDsgfQpwdWJsaWMgVGVtcGxhdGVzIG5ld1RlbXBsYXRlcyhTb3VyY2UgeHNsU3JjKSB0aHJvd3MKVHJhbnNmb3JtZXJDb25maWd1cmF0aW9uRXhjZXB0aW9uIHsgcmV0dXJuIG51bGw7IH0KcHVibGljIFRyYW5zZm9ybWVyIG5ld1RyYW5zZm9ybWVyKCkgdGhyb3dzClRyYW5zZm9ybWVyQ29uZmlndXJhdGlvbkV4Y2VwdGlvbiB7IHJldHVybiBudWxsOyB9PC9zb3VyY2U+CjxwPlRoZSBtZXRob2RzIGxpc3RlZCBhYm92ZSBmYWxsIGludG8gNCBjYXRlZ29yaWVzOiAoMSkgPGxpbmsgYW5jaG9yPSJ0cmFuc2Zvcm1jcmVhdGlvbiI+VHJhbnNmb3JtIGNyZWF0aW9uPC9saW5rPiwgCigyKSA8bGluayBhbmNob3I9InRlbXBsYXRlc2NyZWF0aW9uIj5UZW1wbGF0ZXMgY3JlYXRpb248L2xpbms+LCAoMykgPGxpbmsgYW5jaG9yPSJmZWF0dXJlZGlzY292ZXJ5Ij5mZWF0dXJlIGRpc2NvdmVyeTwvbGluaz4sIAphbmQgKDQpIDxsaW5rIGFuY2hvcj0ibGltaXRhdGlvbnMiPm90aGVycyB0aGF0IHdpbGwgcmVtYWluIHVuaW1wbGVtZW50ZWQgYXQgdGhpcyB0aW1lPC9saW5rPi48L3A+CjxhbmNob3IgbmFtZT0idHJhbnNmb3JtZXJjcmVhdGlvbiIvPgo8czQgdGl0bGU9IlRyYW5zZm9ybWVyIENyZWF0aW9uIj4KPHA+VGhlIEpBWFAgc3BlY2lmaWVzIGEgbWV0aG9kIHRoYXQgdGFrZXMgdGhlIHN0eWxlc2hlZXQgYXMgYSBTb3VyY2Ugb2JqZWN0IGFuZCByZXR1cm5zIGEKVHJhbnNmb3JtZXIuPC9wPgo8cD48Y29kZT5wdWJsaWMgVHJhbnNmb3JtZXIgbmV3VHJhbnNmb3JtZXIoU291cmNlIHhzbFNyYyk8L2NvZGU+PC9wPgo8cD5UaGlzIG1ldGhvZCBuZWVkcyB0byByZXR1cm4gYSBUcmFuc2Zvcm1lciB0byBjb21wbHkgd2l0aCB0aGUgSkFYUCBBUEksIGJ1dCBhbHNvCm5lZWRzIHRvIHJldHVybiBhIFRyYW5zbGV0LiBJbiB0aGUgWFNMVEMvWGFsYW4gQVBJLCBhIFRyYW5zbGV0IGlzIGFuIGludGVyZmFjZSB0aGF0IGlzCmltcGxlbWVudGVkIGJ5IHRoZSBydW50aW1lIGFic3RyYWN0IGNsYXNzIEFic3RyYWN0VHJhbnNsZXQgKG9yZy5hcGFjaGUueGFsYW4ueHNsdGMuVHJhbnNsZXQgYW5kIG9yZy5hcGFjaGUueGFsYW4ueHNsdGMucnVudGltZS5BYnN0cmFjdFRyYW5zbGV0LCByZXBlY3RpdmVseSkuIFRoZXJlZm9yZSwgSSBoYWQgdG8KY2hhbmdlIHRoZSBBYnN0cmFjdFRyYW5zbGV0IGNsYXNzIHNvIHRoYXQgaXQgd2lsbCBleHRlbmQgdGhlIGFic3RyYWN0IFRyYW5zZm9ybWVyCmNsYXNzIHdoaWxlIHN0aWxsIGltcGxlbWVudGluZyB0aGUgVHJhbnNsZXQgaW50ZXJmYWNlLiBPbmNlIHRoaXMgaXMgZG9uZSwgdGhlbiB0aGUKbmV3VHJhbnNmb3JtZXIoKSBtZXRob2Qgb2YgdGhlIG5ldyBUcmFuc2Zvcm1lckZhY3RvcnkgY2FuIHJldHVybiBhIFRyYW5zbGV0IHRoYXQKaXMgYSBUcmFuc2Zvcm1lci48L3A+CjxwPkluIG9yZGVyIHRvIGhhdmUgQWJzdHJhY3RUcmFuc2xldCBleHRlbmQgVHJhbnNmb3JtZXIsIHNldmVyYWwgYWJzdHJhY3QgbWV0aG9kcwpoYXZlIHRvIGJlIGltcGxlbWVudGVkIGluIEFic3RyYWN0VHJhbnNsZXQgY2xhc3MuIFRoZXNlIGFyZTo8L3A+Cjxzb3VyY2U+cHVibGljIHZvaWQgY2xlYXJQYXJhbWV0ZXJzKCkgeyB9CnB1YmxpYyBFcnJvckxpc3RlbmVyIGdldEVycm9yTGlzdGVuZXIoKSB7IHJldHVybiBudWxsOyB9CnB1YmxpYyBQcm9wZXJ0aWVzIGdldE91dHB1dFByb3BlcnRpZXMoKSB0aHJvd3MgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uIHsKICByZXR1cm4gbnVsbDsKfQpwdWJsaWMgU3RyaW5nIGdldE91dHB1dFByb3BlcnR5KFN0cmluZyBuYW1lKQogIHRocm93cyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb257IHJldHVybiAiIjsgfQovL3B1YmxpYyBPYmplY3QgZ2V0UGFyYW1ldGVyKFN0cmluZyBuYW1lKSB7IHJldHVybiBudWxsOyB9CnB1YmxpYyBVUklSZXNvbHZlciBnZXRVUklSZXNvbHZlcigpIHsgcmV0dXJuIG51bGw7IH0KcHVibGljIHZvaWQgc2V0RXJyb3JMaXN0ZW5lcihFcnJvckxpc3RlbmVyIGxpc3RlbmVyKQogIHRocm93cyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24geyB9CnB1YmxpYyB2b2lkIHNldE91dHB1dFByb3BlcnRpZXMoUHJvcGVydGllcyBwcm9wcykKICB0aHJvd3MgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uIHsgfQpwdWJsaWMgdm9pZCBzZXRPdXRwdXRQcm9wZXJ0eShTdHJpbmcgbmFtZSwgU3RyaW5nIHZhbHVlKQogIHRocm93cyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24geyB9CnB1YmxpYyB2b2lkIHNldFBhcmFtZXRlcihTdHJpbmcgbmFtZSwgT2JqZWN0IHZhbHVlKSB7IH0KcHVibGljIHZvaWQgc2V0VVJJUmVzb2x2ZXIoVVJJUmVzb2x2ZXIgcmVzb2x2ZXIpIHsgfQpwdWJsaWMgdm9pZCB0cmFuc2Zvcm0oU291cmNlIHhtbHNyYywgUmVzdWx0IG91dHB1dFRhcmdldCkKICB0aHJvd3MgVHJhbnNmb3JtZXJFeGNlcHRpb24geyAuLi4gfTwvc291cmNlPgo8cD5NYXBwaW5nIHRoZXNlIG1ldGhvZHMgdG8gc29tZSBleGlzdGluZyBvbmVzIGluIEFic3RyYWN0VHJhbnNsZXQgc3RpbGwgaGFzIHRvIGJlCmRvbmUuIEluIHBhcnRpY3VsYXIgdGhlIHRyYW5zZm9ybSgpIG1ldGhvZCB3aGljaCBpcyBleHBsYWluZWQgZnVydGhlciBpbiBhIGZvbGxvd2luZwpzZWN0aW9uLjwvcD4KPHA+Tm93IHRoYXQgWFNMVEOScyBBYnN0cmFjdFRyYW5zbGV0IGlzIGEgVHJhbnNmb3JtZXIsIHRoZSBuZXcgVHJhbnNmb3JtZXIKZmFjdG9yeSBjbGFzcyBjYW4gaW1wbGVtZW50IHRoZSBuZXdUcmFuc2Zvcm1lcigpIG1ldGhvZC4gVGhpcyBtZXRob2QgbmVlZHMgdG8gZG8KdHdvIGZ1bmRhbWVudGFsIHRoaW5nczogKDEpIGNyZWF0ZSBhIHRyYW5zbGV0IGZyb20gdGhlIGdpdmVuIFhTTFQgc3R5bGVzaGVldCBhbmQgKDIpCmluc3RhbnRpYXRlIHRoZSB0cmFuc2xldCBzbyBpdCBjYW4gYmUgcmV0dXJuZWQgYXMgYSBUcmFuc2Zvcm1lci48L3A+CjxwPlRoZSBjb2RlIGJlbG93cyBob3dzIG15IGN1cnJlbnQgaW1wbGVtZW50YXRpb24gb2YgdGhlIG5ld1RyYW5zZm9ybWVyKCkgbWV0aG9kCmluIHRoZSBuZXcgZmFjdG9yeSBjbGFzczo8L3A+Cjxzb3VyY2U+cHVibGljIGNsYXNzIFRvZGRzVHJhbnNmb3JtZXJGYWN0b3J5SW1wbCBleHRlbmRzIFNBWFRyYW5zZm9ybWVyRmFjdG9yeSB7CiAgLi4uCiAgcHVibGljIFRyYW5zZm9ybWVyIG5ld1RyYW5zZm9ybWVyKFNvdXJjZSBzdHlsZXNoZWV0KSB0aHJvd3MKICAgIFRyYW5zZm9ybWVyQ29uZmlndXJhdGlvbkV4Y2VwdGlvbgogIHsKICAgIFhTTFRDIHhzbHRjID0gbmV3IFhTTFRDKCk7CiAgICB4c2x0Yy5pbml0KCk7CiAgICBTdHJpbmcgc3R5bGVzaGVldE5hbWUgPSBzdHlsZXNoZWV0LmdldFN5c3RlbUlkKCk7CiAgICBpbnQgaW5kZXggPSBzdHlsZXNoZWV0TmFtZS5pbmRleE9mKJIukik7CiAgICBTdHJpbmcgdHJhbnNsZXROYW1lID0gc3R5bGVzaGVldE5hbWUuc3Vic3RyaW5nKDAsaW5kZXgpOwogICAgYm9vbGVhbiBpc1N1Y2Nlc3NmdWwgPSB0cnVlOwogICAgdHJ5IHsKICAgICAgRmlsZSBmaWxlID0gbmV3IEZpbGUoc3R5bGVzaGVldE5hbWUpOwogICAgICBVUkwgdXJsID0gZmlsZS50b1VSTCgpOwogICAgICBpc1N1Y2Nlc3NmdWwgPSB4c2x0Yy5jb21waWxlKHVybCk7CiAgICB9IGNhdGNoIChNYWxmb3JtZWRVUkxFeGNlcHRpb24gZSkgewogICAgICAgIHRocm93IG5ldyBUcmFuc2Zvcm1lckNvbmZpZ3VyYXRpb25FeGNlcHRpb24oCiAgICAgICAgICAgICAgICJVUkwgZm9yIHN0eWxlc2hlZXQgkiIgKyBzdHlsZXNoZWV0TmFtZSArCiAgICAgICAgICAgICAgICKSIGNhbiBub3QgYmUgZm9ybWVkLiIpOwogICAgfQoKICAgIGlmICghaXNTdWNjZXNzZnVsKSB7CiAgICAgIHRocm93IG5ldyBUcmFuc2Zvcm1lckNvbmZpZ3VyYXRpb25FeGNlcHRpb24oCiAgICAgICAgICAiQ29tcGlsYXRpb24gb2Ygc3R5bGVzaGVldCCSIiArIHN0eWxlc2hlZXROYW1lICsgIpIgZmFpbGVkLiIpOwogICAgfQogICAgCiAgICBUcmFuc2xldCB0cmFuc2xldCA9IG51bGw7CiAgICB0cnkgewogICAgICBDbGFzcyBjbGF6eiA9IENsYXNzLmZvck5hbWUodHJhbnNsZXROYW1lKTsKICAgICAgdHJhbnNsZXQgPSAoVHJhbnNsZXQpY2xhenoubmV3SW5zdGFuY2UoKTsKICAgICAgKChBYnN0cmFjdFRyYW5zbGV0KXRyYW5zbGV0KS5zZXRUcmFuc2xldE5hbWUodHJhbnNsZXROYW1lKTsKICAgICB9IGNhdGNoIChDbGFzc05vdEZvdW5kRXhjZXB0aW9uIGUpIHsKICAgICAgICAgdGhyb3cgbmV3IFRyYW5zZm9ybWVyQ29uZmlndXJhdGlvbkV4Y2VwdGlvbigKICAgICAgICAgICAgICAiVHJhbnNsZXQgY2xhc3MgkiIgKyB0cmFuc2xldE5hbWUgKyAikiBub3QgZm91bmQuIik7CiAgICAgfSBjYXRjaCAoSW5zdGFudGlhdGlvbkV4Y2VwdGlvbiBlKSB7CiAgICAgICAgIHRocm93IG5ldyBUcmFuc2Zvcm1lckNvbmZpZ3VyYXRpb25FeGNlcHRpb24oCiAgICAgICAgICAgICAgIlRyYW5zbGV0IGNsYXNzIJIiICsgdHJhbnNsZXROYW1lICsKICAgICAgICAgICAgICAikiBjb3VsZCBub3QgYmUgaW5zdGFudGlhdGVkIik7CiAgICAgfSBjYXRjaCAoSWxsZWdhbEFjY2Vzc0V4Y2VwdGlvbiBlKSB7CiAgICAgICAgIHRocm93IG5ldyBUcmFuc2Zvcm1lckNvbmZpZ3VyYXRpb25FeGNlcHRpb24oCiAgICAgICAgICAgICAiVHJhbnNsZXQgY2xhc3MgkiIgKyB0cmFuc2xldE5hbWUgKyAikiBjb3VsZCBub3QgYmUgYWNjZXNzZWQuIik7CiAgICAgfQogICAgIHJldHVybiAoQWJzdHJhY3RUcmFuc2xldCl0cmFuc2xldDsKICB9Cn08L3NvdXJjZT4KPC9zND48YW5jaG9yIG5hbWU9InRlbXBsYXRlc2NyZWF0aW9uIi8+CjxzNCB0aXRsZT0iVGVtcGxhdGVzIENyZWF0aW9uIj4KPHA+VGhlIEpBWFAgc3BlY2lmaWVzIGEgbWV0aG9kIHRoYXQgdGFrZXMgdGhlIHN0eWxlc2hlZXQgYXMgYSBTb3VyY2Ugb2JqZWN0IGFuZCByZXR1cm5zIGEKVGVtcGxhdGVzIG9iamVjdC48L3A+CjxwPjxjb2RlPnB1YmxpYyBUZW1wbGF0ZXMgbmV3VGVtcGxhdGVzKFNvdXJjZSB4c2xTcmMpPC9jb2RlPjwvcD4KPHA+VG8gaW1wbGVtZW50IHRoaXMgbWV0aG9kIEkgbmVlZGVkIHRvIGNyZWF0ZSBhIG5ldyBjbGFzcyB0aGF0IHdvdWxkIGJlIGEgVGVtcGxhdGVzCmZvciBUcmFuc2xldHMgb2JqZWN0LiBUaGUgbmV3IGNsYXNzIFRyYW5zbGV0VGVtcGxhdGVzIChvcmcuYXBhY2hlLnhhbGFuLnhzbHRjLnRyYXguVHJhbnNsZXRUZW1wbGF0ZXMpIGltcGxlbWVudHMgdGhlIFRlbXBsYXRlcwppbnRlcmZhY2UgYXMgaXMgc2hvd24gYmVsb3c6PC9wPgo8c291cmNlPnBhY2thZ2Ugb3JnLmFwYWNoZS54YWxhbi54c2x0Yy50cmF4OwoKaW1wb3J0IGphdmF4LnhtbC50cmFuc2Zvcm0uVGVtcGxhdGVzOwppbXBvcnQgamF2YXgueG1sLnRyYW5zZm9ybS5UcmFuc2Zvcm1lcjsKaW1wb3J0IGphdmF4LnhtbC50cmFuc2Zvcm0uVHJhbnNmb3JtZXJDb25maWd1cmF0aW9uRXhjZXB0aW9uOwppbXBvcnQgamF2YXgueG1sLnRyYW5zZm9ybS5zYXguU0FYVHJhbnNmb3JtZXJGYWN0b3J5OwppbXBvcnQgb3JnLmFwYWNoZS54YWxhbi54c2x0Yy5ydW50aW1lLkFic3RyYWN0VHJhbnNsZXQ7CmltcG9ydCBqYXZhLnV0aWwuUHJvcGVydGllczsKCnB1YmxpYyBjbGFzcyBUcmFuc2xldFRlbXBsYXRlcyBpbXBsZW1lbnRzIFRlbXBsYXRlcyB7CiAgcHVibGljIFRyYW5zbGV0VGVtcGxhdGVzKFRyYW5zZm9ybWVyIHRyYW5zbGV0KSB7CiAgICBfdHJhbnNsZXQgPSAoQWJzdHJhY3RUcmFuc2xldCl0cmFuc2xldDsKICB9CgogIHB1YmxpYyBQcm9wZXJ0aWVzIGdldE91dHB1dFByb3BlcnRpZXMoKSB7IC8qVEJEKi8gcmV0dXJuIG51bGw7IH0KCiAgcHVibGljIFRyYW5zZm9ybWVyIG5ld1RyYW5zZm9ybWVyKCkgdGhyb3dzCiAgICBUcmFuc2Zvcm1lckNvbmZpZ3VyYXRpb25FeGNlcHRpb24KICB7CiAgICBpZiAoX3RyYW5zbGV0ID09IG51bGwpIHsKICAgICAgdGhyb3cgbmV3IFRyYW5zZm9ybWVyQ29uZmlndXJhdGlvbkV4Y2VwdGlvbigKICAgICAgICAgICAgICAiRXJyb3I6IE51bGwgVHJhbnNsZXQiKTsKICAgIH0KICAgIHJldHVybiBfdHJhbnNsZXQ7CiAgfQogIHByaXZhdGUgQWJzdHJhY3RUcmFuc2xldCBfdHJhbnNsZXQgPSBudWxsOwp9PC9zb3VyY2U+CjxwPlRoZSBmYWN0b3J5IG1ldGhvZCBuZXdUZW1wbGF0ZXMoKSBzaW1wbHkgY3JlYXRlcyBhIFRyYW5zZm9ybWVyIGZvciB0aGUgc3R5bGVzaGVldCwKYW5kIHJldHVybnMgYSBuZXdUcmFuc2xldFRlbXBsYXRlcyBvYmplY3QuIFRoZSBpbXBsZW1lbnRhdGlvbiBvZiBuZXdUZW1wbGF0ZXMoKQppcyBzaG93biBiZWxvdzo8L3A+Cjxzb3VyY2U+cHVibGljIGNsYXNzIFRyYW5zZm9ybWVyRmFjdG9yeUltcGwgZXh0ZW5kcyBTQVhUcmFuc2Zvcm1lckZhY3RvcnkgewouLi4KICBwdWJsaWMgVGVtcGxhdGVzIG5ld1RlbXBsYXRlcyhTb3VyY2Ugc3R5bGVzaGVldCkgdGhyb3dzCiAgICBUcmFuc2Zvcm1lckNvbmZpZ3VyYXRpb25FeGNlcHRpb24KICB7CiAgICBUcmFuc2Zvcm1lciB0cmFuc2xldCA9IG5ld1RyYW5zZm9ybWVyKHN0eWxlc2hlZXQpOwogICAgcmV0dXJuIG5ldyBUcmFuc2xldFRlbXBsYXRlcyh0cmFuc2xldCk7CiAgfQp9PC9zb3VyY2U+CjxwPlRoaXMgaW1wbGVtZW50YXRpb24gb25seSBzYXRpc2ZpZXMgdGhlIEpBWFAsIGl0IGRvZXMgbm90IGFkZHJlc3MgY2FjaGluZyBvZiBwcmV2aW91c2x5CmNyZWF0ZWQgdHJhbnNsZXRzLiBUaGlzIHR5cGUgb2YgbWVjaGFuaXNtIGJlbG9uZ3MgaW4gVGVtcGxhdGVzLHdoZXJlIGEgZ2l2ZW4Kc3R5bGVzaGVldCB3aWxsIGJlIGNvbXBpbGVkIG9uZSB0aW1lIG9ubHksIGJ1dCB0aGUgZ2VuZXJhdGVkIHRyYW5zbGV0IGNhbiBiZSBjbG9uZWQgdG8KY3JlYXRlIG11bHRpcGxlIGluc3RhbmNlcyB1cG9uIGRlbWFuZC48L3A+CjwvczQ+PGFuY2hvciBuYW1lPSJmZWF0dXJlZGlzY292ZXJ5Ii8+CjxzNCB0aXRsZT0iRmVhdHVyZSBEaXNjb3ZlcnkiPgo8cD5UaGUgSkFYUCBzcGVjaWZpZXMgYSBtZXRob2QgdGhhdCBhbGxvd3MgcHJvZ3JhbXMgdG8gZGlzY292ZXIgd2hhdCBmZWF0dXJlcyB0aGUgZmFjdG9yeQppcyBjYXBhYmxlIG9mIHN1cHBvcnRpbmcuPC9wPgo8cD48Y29kZT5wdWJsaWMgYm9vbGVhbiBnZXRGZWF0dXJlKFN0cmluZyBmZWF0dXJlTmFtZSk8L2NvZGU+PC9wPgo8cD5BdCB0aGlzIHRpbWUgdGhlIG5ldyB0cmFuc2Zvcm1lciBmYWN0b3J5IHN1cHBvcnRzIFN0cmVhbSBzb3VyY2VzIGFuZCByZXN1bHRzLCBhbmQKdGhlIFNBWCBUcmFuc2Zvcm0gZmFjdG9yeSBmZWF0dXJlLiBUaGUgZ2V0RmVhdHVyZSgpIGltcGxlbWVudGF0aW9uIGlzIHNob3duIGJlbG93OjwvcD4KPHNvdXJjZT5wdWJsaWMgY2xhc3MgVHJhbnNmb3JtZXJGYWN0b3J5SW1wbCBleHRlbmRzIFNBWFRyYW5zZm9ybWVyRmFjdG9yeSB7CiAgLi4uCiAgcHVibGljIGJvb2xlYW4gZ2V0RmVhdHVyZShTdHJpbmcgbmFtZSkgewogICAgaWYgKChTdHJlYW1Tb3VyY2UuRkVBVFVSRSA9PSBuYW1lKSB8fAogICAgICAgIChTdHJlYW1SZXN1bHQuRkVBVFVSRSA9PSBuYW1lKSB8fAogICAgICAgIChTQVhUcmFuc2Zvcm1lckZhY3RvcnkuRkVBVFVSRSA9PSBuYW1lKSkgewogICAgICAgIHJldHVybiB0cnVlOwogICAgfSBlbHNlIGlmICgoU3RyZWFtU291cmNlLkZFQVRVUkUuZXF1YWxzKG5hbWUpKQogICAgICAgICAgICB8fCAoU3RyZWFtUmVzdWx0LkZFQVRVUkUuZXF1YWxzKG5hbWUpKQogICAgICAgICAgICB8fCAoU0FYVHJhbnNmb3JtZXJGYWN0b3J5LkZFQVRVUkUuZXF1YWxzKG5hbWUpKSkgewogICAgICAgICByZXR1cm4gdHJ1ZTsKICAgIH0gZWxzZSB7CiAgICAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICB9Cn08L3NvdXJjZT4KPHA+QXMgdGhlIG90aGVyIGZlYXR1cmVzIGFyZSBpbXBsZW1lbnRlZCwgdGhpcyBtZXRob2RzIHdpbGwgbmVlZCB0byBiZSB1cGRhdGVkLjwvcD4KCjwvczQ+PGFuY2hvciBuYW1lPSJsaW1pdGF0aW9ucyIvPgo8czQgdGl0bGU9IkxpbWl0YXRpb25zIj4KPHA+QXMgeW91IGNhbiBzZWUsIHRoZSBwcm90b3R5cGUgd2lsbCBjb21waWxlIHRoZSBzdHlsZXNoZWV0IGV2ZXJ5dGltZS4gVGhpcyBvYnZpb3VzbHkKbmVlZHMgdG8gYmUgc21hcnRlci4gVGhpcyBpcyB3aGVyZSB0aGUgcXVlc3Rpb24glGRvIEkgYWxyZWFkeSBoYXZlIHRoaXMgdHJhbnNsZXQ/lCBuZWVkcwp0byBiZSBhbnN3ZXJlZC4gQWxzbyBmb3Igbm93IHRoZSB0cmFuc2xldCBieXRlY29kZXMgYXJlIHdyaXR0ZW4gb3V0IHRvIGEgRmlsZSBpbiB0aGUgY3VycmVudAp3b3JraW5nIGRpcmVjdG9yeSwgYW5kIHRoZW4gaW5zdGFudGlhdGVkIHVzaW5nIGEgQ2xhc3MuZm9yTmFtZSwgbmV3SW5zdGFuY2UoKQpwYWlyLiBUaGlzIGFsc28gbmVlZHMgd29yay4gTm90ZSB0aGUgcmV0dXJuIHN0YXRlbWVudCwgdGhlIFRyYW5zbGV0IGlzIGNhc3QgdG8gYW4gQWJzdHJhY3RUcmFuc2xldAp3aGljaCBub3cgaXMgYSBUcmFuc2Zvcm1lci48L3A+CjwvczQ+CjwvczM+CjwvczI+PGFuY2hvciBuYW1lPSJ0cmFuc2Zvcm0iLz4KPHMyIHRpdGxlPSJBYnN0cmFjdFRyYW5zbGV0knMgdHJhbnNmb3JtKCkgTWV0aG9kIj4KPHA+Tm93IHRoZSBKQVhQIHByb2dyYW0gKFByb3RvKSBzaG93biBpbiB0aGUgZmlyc3Qgc2VjdGlvbiBoYXMgYSB3YXkgdG8gZ2V0IGEgVHJhbnNmb3JtZXIKZmFjdG9yeSB0aGF0IGNhbiByZXR1cm4gVHJhbnNsZXRzLiBUaGUgbmV4dCBzdGVwIG9mIHRoZSBQcm90by5qYXZhIHByb2dyYW0gaXMKY2FsbGluZyB0aGUgdHJhbnNmb3JtKCkgbWV0aG9kIGFuZCBoYXZpbmcgdGhlIFRyYW5zbGV0IHByb2Nlc3MgdGhlIGdpdmVuIFhNTApkb2N1bWVudC48L3A+CjxwPlRoaXMgcmVxdWlyZXMgc29tZSBzdXJnZXJ5IGluIHRoZSBBYnN0cmFjdFRyYW5zbGV0IGNsYXNzIGFnYWluLiBUaGUgQWJzdHJhY3RUcmFuc2xldAphbHJlYWR5IGhhcyBhIHRyYW5zZm9ybSgpIG1ldGhvZCwgYnV0IGl0cyBzaWduYXR1cmUgaXMgbm90IHRoZSBzYW1lIGFzIHRoZQpKQVhQIFRyYW5zZm9ybSBzaWduYXR1cmUuIEluIHRoZSBBYnN0cmFjdFRyYW5zbGV0LCB0cmFuc2Zvcm0gbWV0aG9kcyBleHBlY3QgYSBET00KYXJndW1lbnQsIGluIHNvbWUgY2FzZXMgYSBOb2RlSXRlcmF0b3IsIGFuZCBhIFRyYW5zbGV0T3V0cHV0SGFuZGxlciBhcmd1bWVudC4gVGhlCkpBWFAgVHJhbnNmb3JtknMgdHJhbnNmb3JtKCkgc2lnbmF0dXJlIHJlcXVpcmVzIG9ubHkgdGhlIFhNTCBkb2N1bWVudCBhcyBhIFNvdXJjZQpvYmplY3QgcmVmZXJlbmNlIGFuZCBhbiBvdXRwdXRUYXJnZXQgYXMgYSBSZXN1bHQgb2JqZWN0IHJlZmVyZW5jZS4gTXkgaW1wbGVtZW50YXRpb24Kb2YgdGhlIEpBWFAgdHJhbnNmb3JtKCkgc2lnbmF0dXJlIGlzIGFzIHNob3duOjwvcD4KCjxzb3VyY2U+cHVibGljIHZvaWQgdHJhbnNmb3JtKFNvdXJjZSB4bWxzcmMsIFJlc3VsdCBvdXRwdXRUYXJnZXQpCiAgdGhyb3dzIFRyYW5zZm9ybWVyRXhjZXB0aW9uCnsKICBkb1RyYW5zZm9ybSggeG1sc3JjLmdldFN5c3RlbUlkKCksCiAgICAoKFN0cmVhbVJlc3VsdClvdXRwdXRUYXJnZXQpLmdldE91dHB1dFN0cmVhbSgpICk7Cn08L3NvdXJjZT4KPHA+VGhpcyBpbXBsZW1lbnRhdGlvbiBsZXZlcmFnZXMgY29kZSBkZXJpdmVkIGZyb20gWFNMVEOScyBEZWZhdWx0UnVuIGNsYXNzLiBJbgp0aGF0IGNsYXNzIHRoZXJlIGlzIGEgZG9UcmFuc2Zvcm0oKSBtZXRob2QgdGhhdCBjYXJyaWVzIG91dCB0aGUgd29yayBvZjogKDEpIHBhcnNpbmcgdGhlCmlucHV0IFhNTCBkb2N1bWVudCAodXNpbmcgYSBKQVhQIFNBWFBhcnNlckZhY3RvcnkgYW5kIFNBWFBhcnNlciksICgyKSBjcmVhdGluZwphIERPTUltcGwgKG9yZy5hcGFjaGUueGFsYW4ueHNsdGMuZG9tLkRPTUltcGwpLCAoMykgY3JlYXRpbmcgYSBTQVhPdXRwdXRIYW5kbGVyLCBhbmQgZmluYWxseSAoNCkgY2FsbGluZyB0aGUgdHJhbnNsZXQgdG8KdHJhbnNmb3JtIHRoZSBpbnB1dCBYTUwgZG9jdW1lbnQgKGZyb20gdGhlIERPTUltcGwpLjwvcD4KPHA+VGhlIGNvZGUgZm9yIGRvVHJhbnNmb3JtIGlzIHNob3duIGJlbG93OjwvcD4KPHNvdXJjZT5wdWJsaWMgYWJzdHJhY3QgY2xhc3MgQWJzdHJhY3RUcmFuc2xldCBleHRlbmRzIFRyYW5zZm9ybWVyIGltcGxlbWVudHMgVHJhbnNsZXR7CiAgLi4uCiAgcHJpdmF0ZSB2b2lkIGRvVHJhbnNmb3JtKFN0cmluZyB4bWxEb2NOYW1lLCBPdXRwdXRTdHJlYW0gb3N0cmVhbSkgewogICAgdHJ5IHsKICAgICAgZmluYWwgVHJhbnNsZXQgdHJhbnNsZXQgPSAoVHJhbnNsZXQpdGhpczsgLy8gR1RNIGFkZGVkCgogICAgICAvLyBDcmVhdGUgYSBTQVggcGFyc2VyIGFuZCBnZXQgdGhlIFhNTFJlYWRlciBvYmplY3QgaXQgdXNlcwogICAgICBmaW5hbCBTQVhQYXJzZXJGYWN0b3J5IGZhY3RvcnkgPSBTQVhQYXJzZXJGYWN0b3J5Lm5ld0luc3RhbmNlKCk7CiAgICAgIGZpbmFsIFNBWFBhcnNlciBwYXJzZXIgPSBmYWN0b3J5Lm5ld1NBWFBhcnNlcigpOwogICAgICBmaW5hbCBYTUxSZWFkZXIgcmVhZGVyID0gcGFyc2VyLmdldFhNTFJlYWRlcigpOwoKICAgICAgLy8gU2V0IHRoZSBET02ScyBET00gYnVpbGRlciBhcyB0aGUgWE1MUmVhZGVyknMgU0FYMiBjb250ZW50IGhhbmRsZXIKICAgICAgZmluYWwgRE9NSW1wbCBkb20gPSBuZXcgRE9NSW1wbCgpOwogICAgICByZWFkZXIuc2V0Q29udGVudEhhbmRsZXIoZG9tLmdldEJ1aWxkZXIoKSk7CiAgICAgIC8vIENyZWF0ZSBhIERURCBtb25pdG9yIGFuZCBwYXNzIGl0IHRvIHRoZSBYTUxSZWFkZXIgb2JqZWN0CiAgICAgIGZpbmFsIERURE1vbml0b3IgZHRkTW9uaXRvciA9IG5ldyBEVERNb25pdG9yKCk7CiAgICAgIGR0ZE1vbml0b3IuaGFuZGxlRFREKHJlYWRlcik7CiAgICAgIGRvbS5zZXREb2N1bWVudFVSSSh4bWxEb2NOYW1lKTsKICAgICAgLyoqKioqKioqKioqKioqKioKICAgICAgaWYgKF91cmkpCiAgICAgICAgcmVhZGVyLnBhcnNlKHhtbERvY05hbWUpOwogICAgICBlbHNlCiAgICAgICoqKioqKioqKioqKioqKioqKiovCiAgICAgIHJlYWRlci5wYXJzZSgiZmlsZToiKyhuZXcgRmlsZSh4bWxEb2NOYW1lKS5nZXRBYnNvbHV0ZVBhdGgoKSkpOwoKICAgICAgLy8gU2V0IHNpemUgb2Yga2V5L2lkIGluZGljZXMKICAgICAgc2V0SW5kZXhTaXplKGRvbS5nZXRTaXplKCkpOwogICAgICAvLyBJZiB0aGVyZSBhcmUgYW55IGVsZW1lbnRzIHdpdGggSUQgYXR0cmlidXRlcywgYnVpbGQgYW4gaW5kZXgKICAgICAgZHRkTW9uaXRvci5idWlsZElkSW5kZXgoZG9tLCAwLCB0aGlzKTsKCiAgICAgIHNldFVucGFyc2VkRW50aXR5VVJJcyhkdGRNb25pdG9yLmdldFVucGFyc2VkRW50aXR5VVJJcygpKTsKICAgIAogICAgICAvLyBUcmFuc2Zvcm0gdGhlIGRvY3VtZW50CiAgICAgIFN0cmluZyBlbmNvZGluZyA9IHRyYW5zbGV0LmdldE91dHB1dEVuY29kaW5nKCk7CiAgICAgIGlmIChlbmNvZGluZyA9PSBudWxsKSBlbmNvZGluZyA9ICJVVEYtOCI7CiAgICAKICAgICAgLy9UZXh0T3V0cHV0IHRleHRPdXRwdXQgPSBuZXcgVGV4dE91dHB1dChTeXN0ZW0ub3V0LCBlbmNvZGluZyk7CiAgICAgIERlZmF1bHRTQVhPdXRwdXRIYW5kbGVyIHNheEhhbmRsZXIgPSBuZXcKICAgICAgICAgRGVmYXVsdFNBWE91dHB1dEhhbmRsZXIob3N0cmVhbSwgZW5jb2RpbmcpOwogICAgICBUZXh0T3V0cHV0IHRleHRPdXRwdXQgPSBuZXcgVGV4dE91dHB1dChzYXhIYW5kbGVyLCBlbmNvZGluZyk7CiAgICAgIHRyYW5zbGV0LnRyYW5zZm9ybShkb20sIHRleHRPdXRwdXQpOwogICAgICB0ZXh0T3V0cHV0LmZsdXNoKCk7CiAgICB9CiAgICBjYXRjaCAoVHJhbnNsZXRFeGNlcHRpb24gZSkgewogICAgICAuLi4KICAgIH0KICAgIGNhdGNoIChSdW50aW1lRXhjZXB0aW9uIGUpIHsKICAgICAgLi4uCiAgICB9CiAgICBjYXRjaCAoRmlsZU5vdEZvdW5kRXhjZXB0aW9uIGUpIHsKICAgICAgLi4uCiAgICB9CiAgICBjYXRjaCAoTWFsZm9ybWVkVVJMRXhjZXB0aW9uIGUpIHsKICAgICAgLi4uCiAgICB9CiAgICBjYXRjaCAoVW5rbm93bkhvc3RFeGNlcHRpb24gZSkgewogICAgICAuLi4KICAgIH0KICAgIGNhdGNoIChFeGNlcHRpb24gZSkgewogICAgICAuLi4KICAgIH0KICB9Cn08L3NvdXJjZT4KPC9zMj48YW5jaG9yIG5hbWU9ImNvbmNsdXNpb24iLz4KPHMyIHRpdGxlPSJDb25jbHVzaW9uIj4KPHA+VGhpcyBpcyB0aGUgY3VycmVudCBzdGF0ZSBvZiB0aGUgaW50ZWdyYXRpb24gb2YgVHJhbnNsZXQgYW5kIFRyQVguIFRoZSBKQVhQIHByb2dyYW0KaWxsdXN0cmF0ZWQgaW4gdGhlIGZpcnN0IHNlY3Rpb24gKFByb3RvLmphdmEpIGNvbXBpbGVzIGFuZCBydW5zIHdpdGggdGhlIGNoYW5nZXMgb3V0bGluZWQKYWJvdmUuIFRoZSBuZXcgdHJhbnNmb3JtZXIgZmFjdG9yeSBUcmFuc2Zvcm1lckZhY3RvcnlJbXBsIHN1cHBvcnRzIHRyYW5zZm9ybWVyLAp0ZW1wbGF0ZXMgY3JlYXRpb24sIGFuZCB0aGUgZmVhdHVyZSBkaXNjb3ZlcnkgbWVjaGFuaXNtLiBUaGUgdHJhbnNmb3JtZXJzCnJldHVybmVkIGZyb20gdGhlIGZhY3RvcnkgYXJlIGluIGZhY3QgQWJzdHJhY3RUcmFuc2xldCBvYmplY3RzLiBUaGUgbmV3IGNsYXNzClRyYW5zbGV0VGVtcGxhdGVzIGltcGxlbWVudHMgdGhlIFRlbXBsYXRlcyBpbnRlcmZhY2UgZm9yIHRyYW5zbGV0cy4gVGhpcyBpcyB0aGUKcmVzdWx0IG9mIGEgZmlyc3QgcGFzcyBpbXBsZW1lbnRhdGlvbiwgdGhlcmUgYXJlIG1hbnkgc3R1YmJlZCBvdXQgbWV0aG9kcyB0aGF0IG5lZWQgdG8KYmUgaW1wbGVtZW50ZWQsIHRyYW5zbGV0IGNhY2hpbmcgaW4gVGVtcGxhdGVzIG5lZWRzIHRvIGJlIGltcGxlbWVudGVkIGFuZCBzdXBwb3J0CmZvciBTb3VyY2UgYW5kIFJlc3VsdCB0eXBlcyBiZXlvbmQgc2ltcGxlIHN0cmVhbSB0eXBlcywgc3VjaCBhcyBET00gYW5kIFNBWC48L3A+Cgo8L3MyPjxhbmNob3IgbmFtZT0iYXBwZW5kaXgiLz4KPHMyIHRpdGxlPSJBcHBlbmRpeCI+Cjx1bD4KICA8bGk+PGxpbmsgYW5jaG9yPSJydW5zY3JpcHQiPlRoZSBSdW4gc2NyaXB0PC9saW5rPjwvbGk+CiAgPGxpPjxsaW5rIGFuY2hvcj0idHJhbnNmb3JtZXJmYWN0b3J5aW1wbCI+VHJhbnNmb3JtZXJGYWN0b3J5SW1wbC5qYXZhPC9saW5rPjwvbGk+CiAgPGxpPjxsaW5rIGFuY2hvcj0iVHJhbnNsZXRUZW1wbGF0ZXMiPlRyYW5zbGV0VGVtcGxhdGVzLmphdmE8L2xpbms+PC9saT4KICA8bGk+PGxpbmsgYW5jaG9yPSJtYWtlZmlsZSI+VGhlIE1ha2VmaWxlPC9saW5rPjwvbGk+CjwvdWw+CjxhbmNob3IgbmFtZT0icnVuc2NyaXB0Ii8+CjxzMyB0aXRsZT0iVGhlIFJ1biBzY3JpcHQiPgo8cD5CeSBjaGFuZ2luZyB0aGUgRkFDIHZhcmlhYmxlIEkgY2FuIHN3aXRjaCBiZXR3ZWVuIHRoZSB0d28gVHJhbnNmb3JtZXIgZmFjdG9yeSBpbXBsZW1lbnRhdGlvbnMKZm9yIHRlc3RpbmcuPC9wPgo8c291cmNlPiMhL2Jpbi9rc2gKSkFYUD0vdXNyL2xvY2FsL2pheHAtMS4xL2pheHAuamFyCkNSSU1TT049L3Vzci9sb2NhbC9qYXhwLTEuMS9jcmltc29uLmphcgpYU0xUPS9uZXQvYmlnYmxvY2svZmlsZXMxOC90bWlsbGVyL3htbC14YWxhbi9qYXZhL2J1aWxkL2NsYXNzZXMKWE1MPS9uZXQvYmlnYmxvY2svZmlsZXMxOC90bWlsbGVyL3htbC14YWxhbi9qYXZhL2Jpbi94bWwuamFyCkJDRUw9L25ldC9iaWdibG9jay9maWxlczE4L3RtaWxsZXIveG1sLXhhbGFuL2phdmEvYmluL0JDRUwuamFyCkpDVVA9L25ldC9iaWdibG9jay9maWxlczE4L3RtaWxsZXIveG1sLXhhbGFuL2phdmEvYmluL2phdmFfY3VwLmphcgpKQ1VQUlQ9L25ldC9iaWdibG9jay9maWxlczE4L3RtaWxsZXIveG1sLXhhbGFuL2phdmEvYmluL3J1bnRpbWUuamFyCkNMQVNTUEFUSD0ke0pBWFB9OiR7Q1JJTVNPTn06JHtYU0xUfToke1hNTH06JHtCQ0VMfToke0pDVVB9OiR7SkNVUFJUfTouCkZBQz1vcmcuYXBhY2hlLnhhbGFuLnhzbHRjLnRyYXguVHJhbnNmb3JtZXJGYWN0b3J5SW1wbAojRkFDPW9yZy5hcGFjaGUueGFsYW4ucHJvY2Vzc29yLlRyYW5zZm9ybWVyRmFjdG9yeUltcGwKamF2YSAtY2xhc3NwYXRoICR7Q0xBU1NQQVRIfSBcCiAgICAgLURqYXZheC54bWwudHJhbnNmb3JtLlRyYW5zZm9ybWVyRmFjdG9yeT0ke0ZBQ30gXAogICAgIFByb3RvICRAPC9zb3VyY2U+CjwvczM+PGFuY2hvciBuYW1lPSJ0cmFuc2Zvcm1lcmZhY3RvcnlpbXBsIi8+CjxzMyB0aXRsZT0iVHJhbnNmb3JtZXJGYWN0b3J5SW1wbC5qYXZhIj4KCjxzb3VyY2U+cGFja2FnZSBvcmcuYXBhY2hlLnhhbGFuLnhzbHRjLnRyYXg7CgppbXBvcnQgamF2YXgueG1sLnRyYW5zZm9ybS5UZW1wbGF0ZXM7CmltcG9ydCBqYXZheC54bWwudHJhbnNmb3JtLlRyYW5zZm9ybWVyOwppbXBvcnQgamF2YXgueG1sLnRyYW5zZm9ybS5FcnJvckxpc3RlbmVyOwppbXBvcnQgamF2YXgueG1sLnRyYW5zZm9ybS5Tb3VyY2U7CmltcG9ydCBqYXZheC54bWwudHJhbnNmb3JtLnN0cmVhbS5TdHJlYW1Tb3VyY2U7CmltcG9ydCBqYXZheC54bWwudHJhbnNmb3JtLnN0cmVhbS5TdHJlYW1SZXN1bHQ7CmltcG9ydCBqYXZheC54bWwudHJhbnNmb3JtLlVSSVJlc29sdmVyOwppbXBvcnQgamF2YXgueG1sLnRyYW5zZm9ybS5UcmFuc2Zvcm1lckNvbmZpZ3VyYXRpb25FeGNlcHRpb247CmltcG9ydCBqYXZheC54bWwudHJhbnNmb3JtLnNheC5TQVhUcmFuc2Zvcm1lckZhY3Rvcnk7CmltcG9ydCBqYXZheC54bWwudHJhbnNmb3JtLnNheC5UZW1wbGF0ZXNIYW5kbGVyOwppbXBvcnQgamF2YXgueG1sLnRyYW5zZm9ybS5zYXguVHJhbnNmb3JtZXJIYW5kbGVyOwoKaW1wb3J0IG9yZy54bWwuc2F4LlhNTEZpbHRlcjsKCmltcG9ydCBvcmcuYXBhY2hlLnhhbGFuLnhzbHRjLlRyYW5zbGV0OwppbXBvcnQgb3JnLmFwYWNoZS54YWxhbi54c2x0Yy5jb21waWxlci5YU0xUQzsKaW1wb3J0IG9yZy5hcGFjaGUueGFsYW4ueHNsdGMucnVudGltZS5BYnN0cmFjdFRyYW5zbGV0OwoKaW1wb3J0IGphdmEuaW8uRmlsZTsKaW1wb3J0IGphdmEubmV0LlVSTDsKaW1wb3J0IGphdmEubmV0Lk1hbGZvcm1lZFVSTEV4Y2VwdGlvbjsKCi8qKgogKiBJbXBsZW1lbnRhdGlvbiBvZiBhIEpBWFAxLjEgU0FYVHJhbnNmb3JtZXJGYWN0b3J5IGZvciBUcmFuc2xldHMuCiAqLwpwdWJsaWMgY2xhc3MgVHJhbnNmb3JtZXJGYWN0b3J5SW1wbCBleHRlbmRzIFNBWFRyYW5zZm9ybWVyRmFjdG9yeSB7CiAgcHVibGljIFRyYW5zZm9ybWVyRmFjdG9yeUltcGwoKSB7IC8qIG5vdGhpbmcgeWV0ICovIH0KCiAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCiAgLy8gU0FYVHJhbnNmb3JtZXJGYWN0b3J5IChzdWJjbGFzcyBvZiBUcmFuc2Zvcm1lckZhY3RvcnkpCiAgLy8KICBwdWJsaWMgVGVtcGxhdGVzSGFuZGxlciBuZXdUZW1wbGF0ZXNIYW5kbGVyKCkgeyAvKlRCRCovIHJldHVybiBudWxsOyB9CiAgcHVibGljIFRyYW5zZm9ybWVySGFuZGxlciBuZXdUcmFuc2Zvcm1lckhhbmRsZXIoKSB7IC8qVEJEKi8gcmV0dXJuIG51bGw7IH0KICBwdWJsaWMgVHJhbnNmb3JtZXJIYW5kbGVyIG5ld1RyYW5zZm9ybWVySGFuZGxlcihTb3VyY2Ugc3JjKSB7CiAgICAgLypUQkQqLyByZXR1cm4gbnVsbDsKICB9CiAgcHVibGljIFRyYW5zZm9ybWVySGFuZGxlciBuZXdUcmFuc2Zvcm1lckhhbmRsZXIoVGVtcGxhdGVzIHRlbXBsYXRlcykgewogICAgIC8qVEJEKi8gcmV0dXJuIG51bGw7CiAgfQogIHB1YmxpYyBYTUxGaWx0ZXIgbmV3WE1MRmlsdGVyKFNvdXJjZSBzcmMpIHsgLypUQkQqLyByZXR1cm4gbnVsbDsgfQogIHB1YmxpYyBYTUxGaWx0ZXIgbmV3WE1MRmlsdGVyKFRlbXBsYXRlcyB0ZW1wbGF0ZXMpIHsgLypUQkQqLyByZXR1cm4gbnVsbDsgfQoKICAvLwogIC8vIEVuZCBTQVhUcmFuc2Zvcm1lckZhY3RvcnkgbWV0aG9kcwogIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwogIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwogIC8vIFRyYW5zZm9ybWVyRmFjdG9yeQogIC8vCiAgcHVibGljIEVycm9yTGlzdGVuZXIgZ2V0RXJyb3JMaXN0ZW5lcigpIHsgLypUQkQqLyByZXR1cm4gbnVsbDsgfQogIHB1YmxpYyB2b2lkIHNldEVycm9yTGlzdGVuZXIoRXJyb3JMaXN0ZW5lciBsaXN0ZW5lcikgey8qVEJEKi8gfQogIHB1YmxpYyBPYmplY3QgZ2V0QXR0cmlidXRlKFN0cmluZyBuYW1lKSB7IC8qVEJEKi8gcmV0dXJuIG51bGw7IH0KICBwdWJsaWMgdm9pZCBzZXRBdHRyaWJ1dGUoU3RyaW5nIG5hbWUsIE9iamVjdCB2YWx1ZSkgeyAvKlRCRCovIH0KICBwdWJsaWMgYm9vbGVhbiBnZXRGZWF0dXJlKFN0cmluZyBuYW1lKSB7CiAgICBpZiAoKFN0cmVhbVNvdXJjZS5GRUFUVVJFID09IG5hbWUpIHx8CiAgICAgICAgKFN0cmVhbVJlc3VsdC5GRUFUVVJFID09IG5hbWUpIHx8CiAgICAgICAgKFNBWFRyYW5zZm9ybWVyRmFjdG9yeS5GRUFUVVJFID09IG5hbWUpKSB7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgfSBlbHNlIGlmICgoU3RyZWFtU291cmNlLkZFQVRVUkUuZXF1YWxzKG5hbWUpKQogICAgICAgICAgICAgfHwgKFN0cmVhbVJlc3VsdC5GRUFUVVJFLmVxdWFscyhuYW1lKSkKICAgICAgICAgICAgIHx8IChTQVhUcmFuc2Zvcm1lckZhY3RvcnkuRkVBVFVSRS5lcXVhbHMobmFtZSkpKSB7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgfQogIHB1YmxpYyBVUklSZXNvbHZlciBnZXRVUklSZXNvbHZlcigpIHsgLypUQkQqLyByZXR1cm4gbnVsbDsgfQogIHB1YmxpYyB2b2lkIHNldFVSSVJlc29sdmVyKFVSSVJlc29sdmVyIHJlc29sdmVyKSB7LypUQkQqLyB9CiAgcHVibGljIFNvdXJjZSBnZXRBc3NvY2lhdGVkU3R5bGVzaGVldChTb3VyY2Ugc3JjLCBTdHJpbmcgbWVkaWEsCiAgICAgICBTdHJpbmcgdGl0bGUsIFN0cmluZyBjaGFyc2V0KSB7IC8qVEJEKi8gcmV0dXJuIG51bGw7IH0KICBwdWJsaWMgVHJhbnNmb3JtZXIgbmV3VHJhbnNmb3JtZXIoKSB0aHJvd3MKICAgIFRyYW5zZm9ybWVyQ29uZmlndXJhdGlvbkV4Y2VwdGlvbiB7IC8qVEJEKi8gcmV0dXJuIG51bGw7IH0KICAvLwogIC8vIEVuZCBUcmFuc2Zvcm1lckZhY3RvcnkgbWV0aG9kcwogIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwogIHB1YmxpYyBUcmFuc2Zvcm1lciBuZXdUcmFuc2Zvcm1lcihTb3VyY2Ugc3R5bGVzaGVldCkgdGhyb3dzCiAgVHJhbnNmb3JtZXJDb25maWd1cmF0aW9uRXhjZXB0aW9uCiAgewogICAgWFNMVEMgeHNsdGMgPSBuZXcgWFNMVEMoKTsKICAgIHhzbHRjLmluaXQoKTsKICAgIFN0cmluZyBzdHlsZXNoZWV0TmFtZSA9IHN0eWxlc2hlZXQuZ2V0U3lzdGVtSWQoKTsKICAgIGludCBpbmRleCA9IHN0eWxlc2hlZXROYW1lLmluZGV4T2Yoki6SKTsKICAgIFN0cmluZyB0cmFuc2xldE5hbWUgPSBzdHlsZXNoZWV0TmFtZS5zdWJzdHJpbmcoMCxpbmRleCk7CiAgICBib29sZWFuIGlzU3VjY2Vzc2Z1bCA9IHRydWU7CiAgICB0cnkgewogICAgICBGaWxlIGZpbGUgPSBuZXcgRmlsZShzdHlsZXNoZWV0TmFtZSk7CiAgICAgIFVSTCB1cmwgPSBmaWxlLnRvVVJMKCk7CiAgICAgIGlzU3VjY2Vzc2Z1bCA9IHhzbHRjLmNvbXBpbGUodXJsKTsKICAgIH0gY2F0Y2ggKE1hbGZvcm1lZFVSTEV4Y2VwdGlvbiBlKSB7CiAgICAgICAgdGhyb3cgbmV3IFRyYW5zZm9ybWVyQ29uZmlndXJhdGlvbkV4Y2VwdGlvbigKICAgICAgICAgICAgIlVSTCBmb3Igc3R5bGVzaGVldCCSIiArIHN0eWxlc2hlZXROYW1lICsKICAgICAgICAgICAgIpIgY2FuIG5vdCBiZSBmb3JtZWQuIik7CiAgICB9CiAgICBpZiAoIWlzU3VjY2Vzc2Z1bCkgewogICAgICB0aHJvdyBuZXcgVHJhbnNmb3JtZXJDb25maWd1cmF0aW9uRXhjZXB0aW9uKAogICAgICAgICAgICJDb21waWxhdGlvbiBvZiBzdHlsZXNoZWV0IJIiICsgc3R5bGVzaGVldE5hbWUgKyAikiBmYWlsZWQuIik7CiAgICB9CiAgICAKICAgIFRyYW5zbGV0IHRyYW5zbGV0ID0gbnVsbDsKICAgIHRyeSB7CiAgICAgIENsYXNzIGNsYXp6ID0gQ2xhc3MuZm9yTmFtZSh0cmFuc2xldE5hbWUpOwogICAgICB0cmFuc2xldCA9IChUcmFuc2xldCljbGF6ei5uZXdJbnN0YW5jZSgpOwogICAgICAoKEFic3RyYWN0VHJhbnNsZXQpdHJhbnNsZXQpLnNldFRyYW5zbGV0TmFtZSh0cmFuc2xldE5hbWUpOwogICAgfSBjYXRjaCAoQ2xhc3NOb3RGb3VuZEV4Y2VwdGlvbiBlKSB7CiAgICAgICB0aHJvdyBuZXcgVHJhbnNmb3JtZXJDb25maWd1cmF0aW9uRXhjZXB0aW9uKAogICAgICAgICAgICAiVHJhbnNsZXQgY2xhc3MgkiIgKyB0cmFuc2xldE5hbWUgKyAikiBub3QgZm91bmQuIik7CiAgICB9IGNhdGNoIChJbnN0YW50aWF0aW9uRXhjZXB0aW9uIGUpIHsKICAgICAgICB0aHJvdyBuZXcgVHJhbnNmb3JtZXJDb25maWd1cmF0aW9uRXhjZXB0aW9uKAogICAgICAgICAgICAiVHJhbnNsZXQgY2xhc3MgkiIgKyB0cmFuc2xldE5hbWUgKwogICAgICAgICAgICAikiBjb3VsZCBub3QgYmUgaW5zdGFudGlhdGVkIik7CiAgICB9IGNhdGNoIChJbGxlZ2FsQWNjZXNzRXhjZXB0aW9uIGUpIHsKICAgICAgICB0aHJvdyBuZXcgVHJhbnNmb3JtZXJDb25maWd1cmF0aW9uRXhjZXB0aW9uKAogICAgICAgICAgICAiVHJhbnNsZXQgY2xhc3MgkiIgKyB0cmFuc2xldE5hbWUgKyAikiBjb3VsZCBub3QgYmUgYWNjZXNzZWQuIik7CiAgICB9CiAgICByZXR1cm4gKEFic3RyYWN0VHJhbnNsZXQpdHJhbnNsZXQ7CiAgfQogIHB1YmxpYyBUZW1wbGF0ZXMgbmV3VGVtcGxhdGVzKFNvdXJjZSBzdHlsZXNoZWV0KSB0aHJvd3MKICBUcmFuc2Zvcm1lckNvbmZpZ3VyYXRpb25FeGNlcHRpb24KICB7CiAgVHJhbnNmb3JtZXIgdHJhbnNsZXQgPSBuZXdUcmFuc2Zvcm1lcihzdHlsZXNoZWV0KTsKICByZXR1cm4gbmV3IFRyYW5zbGV0VGVtcGxhdGVzKHRyYW5zbGV0KTsKICB9Cn08L3NvdXJjZT4KPC9zMz48YW5jaG9yIG5hbWU9InRyYW5zbGV0dGVtcGxhdGVzIi8+CjxzMyB0aXRsZT0iVHJhbnNsZXRUZW1wbGF0ZXMuamF2YSI+Cjxzb3VyY2U+cGFja2FnZSBvcmcuYXBhY2hlLnhhbGFuLnhzbHRjLnRyYXg7CgppbXBvcnQgamF2YXgueG1sLnRyYW5zZm9ybS5UZW1wbGF0ZXM7CmltcG9ydCBqYXZheC54bWwudHJhbnNmb3JtLlRyYW5zZm9ybWVyOwppbXBvcnQgamF2YXgueG1sLnRyYW5zZm9ybS5UcmFuc2Zvcm1lckNvbmZpZ3VyYXRpb25FeGNlcHRpb247CmltcG9ydCBqYXZheC54bWwudHJhbnNmb3JtLnNheC5TQVhUcmFuc2Zvcm1lckZhY3Rvcnk7CgppbXBvcnQgb3JnLmFwYWNoZS54YWxhbi54c2x0Yy5ydW50aW1lLkFic3RyYWN0VHJhbnNsZXQ7CmltcG9ydCBqYXZhLnV0aWwuUHJvcGVydGllczsKCi8qKgogKiBJbXBsZW1lbnRhdGlvbiBvZiBhIEpBWFAxLjEgVGVtcGxhdGVzIG9iamVjdCBmb3IgVHJhbnNsZXRzLgogKi8KcHVibGljIGNsYXNzIFRyYW5zbGV0VGVtcGxhdGVzIGltcGxlbWVudHMgVGVtcGxhdGVzIHsKICBwdWJsaWMgVHJhbnNsZXRUZW1wbGF0ZXMoVHJhbnNmb3JtZXIgdHJhbnNsZXQpIHsKICAgIF90cmFuc2xldCA9IChBYnN0cmFjdFRyYW5zbGV0KXRyYW5zbGV0OwogIH0KICBwdWJsaWMgUHJvcGVydGllcyBnZXRPdXRwdXRQcm9wZXJ0aWVzKCkgeyAvKlRCRCovIHJldHVybiBudWxsOyB9CiAgcHVibGljIFRyYW5zZm9ybWVyIG5ld1RyYW5zZm9ybWVyKCkgdGhyb3dzCiAgICBUcmFuc2Zvcm1lckNvbmZpZ3VyYXRpb25FeGNlcHRpb24KICB7CiAgICBpZiAoX3RyYW5zbGV0ID09IG51bGwpIHsKICAgICAgdGhyb3cgbmV3IFRyYW5zZm9ybWVyQ29uZmlndXJhdGlvbkV4Y2VwdGlvbigKICAgICAgICAgICAiRXJyb3I6IE51bGwgVHJhbnNsZXQiKTsKICAgIH0KICAgIHJldHVybiBfdHJhbnNsZXQ7CiAgfQogIHByaXZhdGUgQWJzdHJhY3RUcmFuc2xldCBfdHJhbnNsZXQgPSBudWxsOwp9PC9zb3VyY2U+CjwvczM+PGFuY2hvciBuYW1lPSJtYWtlZmlsZSIvPiAKPHMzIHRpdGxlPSJUaGUgTWFrZWZpbGUiPgo8c291cmNlPkpBWFA9L3Vzci9sb2NhbC9qYXhwLTEuMS9qYXhwLmphcgpDUklNU09OPS91c3IvbG9jYWwvamF4cC0xLjEvY3JpbXNvbi5qYXIKWFNMVD0vbmV0L2JpZ2Jsb2NrL2ZpbGVzMTgvdG1pbGxlci94bWwteGFsYW4vamF2YS9idWlsZC9jbGFzc2VzCkNMQVNTUEFUSD0ke0pBWFB9OiR7Q1JJTVNPTn06JHtYU0xUfQpTUkNTPVwKUHJvdG8uamF2YQphbGw6CmphdmFjIC1jbGFzc3BhdGggJHtDTEFTU1BBVEh9ICR7U1JDU308L3NvdXJjZT4KPC9zMz4KPC9zMj4KPC9zMT4K