Ly8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KLy8KLy8gIExpY2Vuc2VkIHRvIHRoZSBBcGFjaGUgU29mdHdhcmUgRm91bmRhdGlvbiAoQVNGKSB1bmRlciBvbmUgb3IgbW9yZQovLyAgY29udHJpYnV0b3IgbGljZW5zZSBhZ3JlZW1lbnRzLiAgU2VlIHRoZSBOT1RJQ0UgZmlsZSBkaXN0cmlidXRlZCB3aXRoCi8vICB0aGlzIHdvcmsgZm9yIGFkZGl0aW9uYWwgaW5mb3JtYXRpb24gcmVnYXJkaW5nIGNvcHlyaWdodCBvd25lcnNoaXAuCi8vICBUaGUgQVNGIGxpY2Vuc2VzIHRoaXMgZmlsZSB0byBZb3UgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMAovLyAgKHRoZSAiTGljZW5zZSIpOyB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGgKLy8gIHRoZSBMaWNlbnNlLiAgWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0Ci8vCi8vICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wCi8vCi8vICBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlCi8vICBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiAiQVMgSVMiIEJBU0lTLAovLyAgV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuCi8vICBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kCi8vICBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS4KLy8KLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KcGFja2FnZSBmbGFzaHgudGV4dExheW91dC5mb3JtYXRzCnsKCWltcG9ydCBmbGFzaHgudGV4dExheW91dC5kZWJ1Zy5hc3NlcnQ7CglpbXBvcnQgZmxhc2h4LnRleHRMYXlvdXQucHJvcGVydHkuUHJvcGVydHk7CglpbXBvcnQgZmxhc2h4LnRleHRMYXlvdXQudGxmX2ludGVybmFsOwoJdXNlIG5hbWVzcGFjZSB0bGZfaW50ZXJuYWw7CgoJaW1wb3J0IGZsYXNoeC50ZXh0TGF5b3V0LmZvcm1hdHMuQnJlYWtTdHlsZTsKCWltcG9ydCBmbGFzaHgudGV4dExheW91dC5mb3JtYXRzLkJyZWFrU3R5bGU7CglpbXBvcnQgZmxhc2h4LnRleHRMYXlvdXQuZm9ybWF0cy5CcmVha1N0eWxlOwoJaW1wb3J0IGZsYXNoeC50ZXh0TGF5b3V0LmZvcm1hdHMuQnJlYWtTdHlsZTsKCWltcG9ydCBmbGFzaHgudGV4dExheW91dC5mb3JtYXRzLkNvbG9yTmFtZTsKCWltcG9ydCBmbGFzaHgudGV4dExheW91dC5mb3JtYXRzLkJhY2tncm91bmRDb2xvcjsKCWltcG9ydCBmbGFzaC50ZXh0LmVuZ2luZS5CcmVha09wcG9ydHVuaXR5OwoJaW1wb3J0IGZsYXNoLnRleHQuZW5naW5lLkRpZ2l0Q2FzZTsKCWltcG9ydCBmbGFzaC50ZXh0LmVuZ2luZS5EaWdpdFdpZHRoOwoJaW1wb3J0IGZsYXNoLnRleHQuZW5naW5lLlRleHRCYXNlbGluZTsKCWltcG9ydCBmbGFzaC50ZXh0LmVuZ2luZS5LZXJuaW5nOwoJaW1wb3J0IGZsYXNoLnRleHQuZW5naW5lLkxpZ2F0dXJlTGV2ZWw7CglpbXBvcnQgZmxhc2gudGV4dC5lbmdpbmUuVGV4dEJhc2VsaW5lOwoJaW1wb3J0IGZsYXNoeC50ZXh0TGF5b3V0LmZvcm1hdHMuVExGVHlwb2dyYXBoaWNDYXNlOwoJaW1wb3J0IGZsYXNoeC50ZXh0TGF5b3V0LmZvcm1hdHMuVGV4dERlY29yYXRpb247CglpbXBvcnQgZmxhc2gudGV4dC5lbmdpbmUuRm9udFdlaWdodDsKCWltcG9ydCBmbGFzaC50ZXh0LmVuZ2luZS5Gb250UG9zdHVyZTsKCWltcG9ydCBmbGFzaHgudGV4dExheW91dC5mb3JtYXRzLldoaXRlU3BhY2VDb2xsYXBzZTsKCWltcG9ydCBmbGFzaC50ZXh0LmVuZ2luZS5SZW5kZXJpbmdNb2RlOwoJaW1wb3J0IGZsYXNoLnRleHQuZW5naW5lLkNGRkhpbnRpbmc7CglpbXBvcnQgZmxhc2gudGV4dC5lbmdpbmUuRm9udExvb2t1cDsKCWltcG9ydCBmbGFzaC50ZXh0LmVuZ2luZS5UZXh0Um90YXRpb247CglpbXBvcnQgZmxhc2h4LnRleHRMYXlvdXQuZm9ybWF0cy5UZXh0QWxpZ247CglpbXBvcnQgZmxhc2h4LnRleHRMYXlvdXQuZm9ybWF0cy5UZXh0QWxpZ247CglpbXBvcnQgZmxhc2h4LnRleHRMYXlvdXQuZm9ybWF0cy5UZXh0SnVzdGlmeTsKCWltcG9ydCBmbGFzaHgudGV4dExheW91dC5mb3JtYXRzLkp1c3RpZmljYXRpb25SdWxlOwoJaW1wb3J0IGZsYXNoLnRleHQuZW5naW5lLkp1c3RpZmljYXRpb25TdHlsZTsKCWltcG9ydCBmbGFzaHgudGV4dExheW91dC5mb3JtYXRzLkRpcmVjdGlvbjsKCWltcG9ydCBmbGFzaHgudGV4dExheW91dC5mb3JtYXRzLkxlYWRpbmdNb2RlbDsKCWltcG9ydCBmbGFzaHgudGV4dExheW91dC5mb3JtYXRzLkZvcm1hdFZhbHVlOwoJaW1wb3J0IGZsYXNoeC50ZXh0TGF5b3V0LmZvcm1hdHMuRm9ybWF0VmFsdWU7CglpbXBvcnQgZmxhc2h4LnRleHRMYXlvdXQuZm9ybWF0cy5Gb3JtYXRWYWx1ZTsKCWltcG9ydCBmbGFzaHgudGV4dExheW91dC5mb3JtYXRzLkZvcm1hdFZhbHVlOwoJaW1wb3J0IGZsYXNoeC50ZXh0TGF5b3V0LmZvcm1hdHMuRm9ybWF0VmFsdWU7CglpbXBvcnQgZmxhc2h4LnRleHRMYXlvdXQuZm9ybWF0cy5Gb3JtYXRWYWx1ZTsKCWltcG9ydCBmbGFzaHgudGV4dExheW91dC5mb3JtYXRzLkJhc2VsaW5lT2Zmc2V0OwoJaW1wb3J0IGZsYXNoeC50ZXh0TGF5b3V0LmZvcm1hdHMuVmVydGljYWxBbGlnbjsKCWltcG9ydCBmbGFzaHgudGV4dExheW91dC5mb3JtYXRzLkJsb2NrUHJvZ3Jlc3Npb247CglpbXBvcnQgZmxhc2h4LnRleHRMYXlvdXQuZm9ybWF0cy5MaW5lQnJlYWs7CglpbXBvcnQgZmxhc2h4LnRleHRMYXlvdXQuZm9ybWF0cy5MaXN0U3R5bGVUeXBlOwoJaW1wb3J0IGZsYXNoeC50ZXh0TGF5b3V0LmZvcm1hdHMuTGlzdFN0eWxlUG9zaXRpb247CglpbXBvcnQgZmxhc2h4LnRleHRMYXlvdXQuZm9ybWF0cy5DbGVhckZsb2F0czsKCWltcG9ydCBmbGFzaHgudGV4dExheW91dC5mb3JtYXRzLkJvcmRlckNvbG9yOwoJaW1wb3J0IGZsYXNoeC50ZXh0TGF5b3V0LmZvcm1hdHMuQm9yZGVyQ29sb3I7CglpbXBvcnQgZmxhc2h4LnRleHRMYXlvdXQuZm9ybWF0cy5Cb3JkZXJDb2xvcjsKCWltcG9ydCBmbGFzaHgudGV4dExheW91dC5mb3JtYXRzLkJvcmRlckNvbG9yOwoJaW1wb3J0IGZsYXNoeC50ZXh0TGF5b3V0LmZvcm1hdHMuVGFibGVGcmFtZTsKCWltcG9ydCBmbGFzaHgudGV4dExheW91dC5mb3JtYXRzLlRhYmxlUnVsZXM7CgoJLyoqCgkgKiBUaGUgVGV4dExheW91dEZvcm1hdCBjbGFzcyBob2xkcyBhbGwgb2YgdGhlIHRleHQgbGF5b3V0IHByb3BlcnRpZXMuIFRoZXNlIHByb3BlcnRpZXMgYWZmZWN0IHRoZSBmb3JtYXQgYW5kIHN0eWxlIG9mIGEgdGV4dCBmbG93IGF0IHRoZSBjb250YWluZXIgbGV2ZWwsIHBhcmFncmFwaCBsZXZlbCwgYW5kIHRleHQgbGV2ZWwuICBCb3RoIHRoZSBDb250YWluZXJDb250cm9sbGVyIGNsYXNzIGFuZCB0aGUgRmxvd0VsZW1lbnQgYmFzZSBjbGFzcyBoYXZlIDxjb2RlPmZvcm1hdDwvY29kZT4gcHJvcGVydGllcyB0aGF0IGVuYWJsZSB5b3UgdG8gYXNzaWduIGEgVGV4dExheW91dEZvcm1hdCBpbnN0YW5jZSB0byB0aGVtLiBBc3NpZ24gYSBUZXh0TGF5b3V0Rm9ybWF0IG9iamVjdCB0byBhIGNvbnRhaW5lciB0byBhZmZlY3QgdGhlIGZvcm1hdCBvZiBhbGwgb2YgdGhlIGNvbnRhaW5lcidzIGNvbnRlbnQuIEFzc2lnbiBhIFRleHRMYXlvdXRGb3JtYXQgb2JqZWN0IHRvIGEgRmxvd0VsZW1lbnQgZGVzY2VuZGFudCB0byBzcGVjaWZ5IGZvcm1hdHRpbmcgZm9yIHRoYXQgcGFydGljdWxhciBlbGVtZW50OiBUZXh0RmxvdywgUGFyYWdyYXBoRWxlbWVudCwgRGl2RWxlbWVudCwgU3BhbkVsZW1lbnQsIElubGluZUdyYXBoaWNFbGVtZW50LCBMaW5rRWxlbWVudCwgYW5kIFRDWUVsZW1lbnQuCgkgKiBJbiBhZGRpdGlvbiB0byB0aGUgPGNvZGU+Zm9ybWF0PC9jb2RlPiBwcm9wZXJ0eSwgdGhlc2UgY2xhc3NlcyBhbHNvIGRlZmluZSBlYWNoIG9mIHRoZSBpbmRpdmlkdWFsIFRleHRMYXlvdXRGb3JtYXQgcHJvcGVydGllcyBzbyB0aGF0IHlvdSBjYW4gb3ZlcnJpZGUgdGhlIHNldHRpbmcgb2YgYSBwYXJ0aWN1bGFyIHN0eWxlIHByb3BlcnR5IGZvciB0aGF0IGVsZW1lbnQsIGlmIHlvdSB3aXNoLiA8cD5CZWNhdXNlIHlvdSBjYW4gc2V0IGEgZ2l2ZW4gc3R5bGUgYXQgbXVsdGlwbGUgbGV2ZWxzLCBpdCBpcyBwb3NzaWJsZSB0byBoYXZlIGNvbmZsaWN0cy4gRm9yIGV4YW1wbGUsIHRoZSBjb2xvciBvZiB0aGUgdGV4dCBhdCB0aGUgVGV4dEZsb3cgbGV2ZWwgY291bGQgYmUgc2V0IHRvIGJsYWNrIHdoaWxlIGEgU3BhbkVsZW1lbnQgb2JqZWN0IHNldHMgaXQgdG8gYmx1ZS4gVGhlIGdlbmVyYWwgcnVsZSBpcyB0aGF0IHRoZSBzZXR0aW5nIGF0IHRoZSBsb3dlc3QgbGV2ZWwgb24gdGhlIHRleHQgZmxvdyB0cmVlIHRha2VzIHByZWNlZGVuY2UuIFNvIGlmIHRoZSBsaWdhdHVyZSBsZXZlbCBpcyBzZXQgZm9yIGEgVGV4dEZsb3cgaW5zdGFuY2UgYW5kIGFsc28gc2V0IGZvciBhIERpdkVsZW1lbnQsIHRoZSBEaXZFbGVtZW50IHNldHRpbmcgdGFrZXMgcHJlY2VkZW5jZS4gPC9wPjxwPkNhc2NhZGluZyBzdHlsZXMgcmVmZXJzIHRvIHRoZSBwcm9jZXNzIG9mIGFkb3B0aW5nIHN0eWxlcyBmcm9tIGEgaGlnaGVyIGxldmVsIGluIHRoZSB0ZXh0IGZsb3cgaWYgYSBzdHlsZSB2YWx1ZSBpcyB1bmRlZmluZWQgYXQgYSBsb3dlciBsZXZlbC4gV2hlbiBhIHN0eWxlIGlzIHVuZGVmaW5lZCBvbiBhbiBlbGVtZW50IGF0IHRoZSBwb2ludCBpdCBpcyBhYm91dCB0byBiZSByZW5kZXJlZCwgaXQgZWl0aGVyIHRha2VzIGl0cyBkZWZhdWx0IHZhbHVlIG9yIHRoZSB2YWx1ZSBjYXNjYWRlcyBvciBkZXNjZW5kcyBmcm9tIHRoZSB2YWx1ZSBvbiBhIHBhcmVudCBlbGVtZW50LiBGb3IgZXhhbXBsZSwgaWYgdGhlIHRyYW5zcGFyZW5jeSAoPGNvZGU+dGV4dEFscGhhPC9jb2RlPiBwcm9wZXJ0eSkgb2YgdGhlIHRleHQgaXMgdW5kZWZpbmVkIG9uIGEgU3BhbkVsZW1lbnQgb2JqZWN0LCBidXQgaXMgc2V0IG9uIHRoZSBUZXh0RmxvdywgdGhlIHZhbHVlIG9mIHRoZSA8Y29kZT5UZXh0Rmxvdy50ZXh0QWxwaGE8L2NvZGU+IHByb3BlcnR5IGNhc2NhZGVzIHRvIHRoZSBTcGFuRWxlbWVudCBvYmplY3QgYW5kIGlzIGFwcGxpZWQgdG8gdGhlIHRleHQgZm9yIHRoYXQgc3Bhbi4gVGhlIHJlc3VsdCBvZiB0aGUgY2FzY2FkZSwgb3IgdGhlIHN1bSBvZiB0aGUgc3R5bGVzIHRoYXQgaXMgYXBwbGllZCB0byB0aGUgZWxlbWVudCwgaXMgc3RvcmVkIGluIHRoZSBlbGVtZW50J3MgPGNvZGU+Y29tcHV0ZWRGb3JtYXQ8L2NvZGU+IHByb3BlcnR5LjwvcD48cD5JbiB0aGUgc2FtZSB3YXksIHlvdSBjYW4gYXBwbHkgdXNlciBzdHlsZXMgdXNpbmcgdGhlIDxjb2RlPnVzZXJTdHlsZXM8L2NvZGU+IHByb3BlcnR5IG9mIHRoZSBDb250YWluZXJDb250cm9sbGVyIGFuZCBGbG93RWxlbWVudCBjbGFzc2VzLiBUaGlzICBwcm9wZXJ0eSBhbGxvd3MgeW91IHRvIHJlYWQgb3Igd3JpdGUgYSBkaWN0aW9uYXJ5IG9mIHVzZXIgc3R5bGVzIGFuZCBhcHBseSBpdHMgc2V0dGluZ3MgdG8gYSBjb250YWluZXIgb3IgYSB0ZXh0IGZsb3cgZWxlbWVudC4gVGhlIHVzZXIgc3R5bGVzIGRpY3Rpb25hcnkgaXMgYW4gb2JqZWN0IHRoYXQgY29uc2lzdHMgb2YgPGVtPnN0eWxlbmFtZS12YWx1ZTwvZW0+IHBhaXJzLiBTdHlsZXMgc3BlY2lmaWVkIGJ5IHRoZSA8Y29kZT51c2VyU3R5bGVzPC9jb2RlPiBwcm9wZXJ0eSB0YWtlIHByZWNlZGVuY2Ugb3ZlciBhbGwgb3RoZXJzLjwvcD48cD5Nb3N0IHN0eWxlcyB0aGF0IGFyZSB1bmRlZmluZWQgaW5oZXJpdCB0aGUgdmFsdWUgb2YgdGhlaXIgaW1tZWRpYXRlIHBhcmVudCBkdXJpbmcgYSBjYXNjYWRlLiBBIHNtYWxsIG51bWJlciBvZiBzdHlsZXMsIGhvd2V2ZXIsIGRvIG5vdCBpbmhlcml0IHRoZWlyIHBhcmVudNVzIHZhbHVlIGFuZCB0YWtlIG9uIHRoZWlyIGRlZmF1bHQgdmFsdWVzIGluc3RlYWQuPC9wPjxwPjxzdHJvbmc+U3R5bGUgcHJvcGVydGllcyB0aGF0IGFkb3B0IHRoZWlyIGRlZmF1bHQgdmFsdWVzLCBpZiB1bmRlZmluZWQsIGluY2x1ZGU6PC9zdHJvbmc+IDxjb2RlPmJhY2tncm91bmRBbHBoYTwvY29kZT4sIDxjb2RlPmJhY2tncm91bmRDb2xvcjwvY29kZT4sIDxjb2RlPmNvbHVtbkNvdW50PC9jb2RlPiwgPGNvZGU+Y29sdW1uR2FwPC9jb2RlPiwgPGNvZGU+Y29sdW1uV2lkdGg8L2NvZGU+LCA8Y29kZT5saW5lQnJlYWs8L2NvZGU+LCA8Y29kZT5wYWRkaW5nQm90dG9tPC9jb2RlPiwgPGNvZGU+cGFkZGluZ0xlZnQ8L2NvZGU+LCA8Y29kZT5wYWRkaW5nUmlnaHQ8L2NvZGU+LCA8Y29kZT5wYWRkaW5nVG9wPC9jb2RlPiwgPGNvZGU+dmVydGljYWxBbGlnbjwvY29kZT48L3A+LgoJICogQGluY2x1ZGVFeGFtcGxlIGV4YW1wbGVzXFRleHRMYXlvdXRGb3JtYXRFeGFtcGxlLmFzIC1ub3N3ZgoJICogQGluY2x1ZGVFeGFtcGxlIGV4YW1wbGVzXFRleHRMYXlvdXRGb3JtYXRFeGFtcGxlMi5hcyAtbm9zd2YKCSAqIEBzZWUgZmxhc2h4LnRleHRMYXlvdXQuZWxlbWVudHMuRmxvd0VsZW1lbnQjZm9ybWF0CgkgKiBAc2VlIGZsYXNoeC50ZXh0TGF5b3V0LmZhY3RvcnkuVGV4dEZsb3dUZXh0TGluZUZhY3RvcnkKCSAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCgkgKiBAcGxheWVydmVyc2lvbiBBSVIgMS41IAoJICogQGxhbmd2ZXJzaW9uIDMuMCAKCSAqLwoJcHVibGljIGNsYXNzIFRleHRMYXlvdXRGb3JtYXQgaW1wbGVtZW50cyBJVGV4dExheW91dEZvcm1hdAoJewoJCS8qKiBAcHJpdmF0ZSAqLwoJCXN0YXRpYyBwcml2YXRlIHZhciBfY29sdW1uQnJlYWtCZWZvcmVQcm9wZXJ0eTpQcm9wZXJ0eTsKCQlzdGF0aWMgcHVibGljIGZ1bmN0aW9uIGdldCBjb2x1bW5CcmVha0JlZm9yZVByb3BlcnR5KCk6UHJvcGVydHkKCQl7CgkJCWlmICghX2NvbHVtbkJyZWFrQmVmb3JlUHJvcGVydHkpCgkJCQlfY29sdW1uQnJlYWtCZWZvcmVQcm9wZXJ0eSA9IFByb3BlcnR5Lk5ld0VudW1TdHJpbmdQcm9wZXJ0eSgKCQkJCSJjb2x1bW5CcmVha0JlZm9yZSIsQnJlYWtTdHlsZS5BVVRPLGZhbHNlLFZlY3Rvci48U3RyaW5nPihbQ2F0ZWdvcnkuUEFSQUdSQVBIXSkKCQkJCSxCcmVha1N0eWxlLkFVVE8KCQkJCSxCcmVha1N0eWxlLkFMV0FZUwoJCQkJKTsKCQkJcmV0dXJuIF9jb2x1bW5CcmVha0JlZm9yZVByb3BlcnR5OwoJCX0KCQkvKiogQHByaXZhdGUgKi8KCQlzdGF0aWMgcHJpdmF0ZSB2YXIgX2NvbHVtbkJyZWFrQWZ0ZXJQcm9wZXJ0eTpQcm9wZXJ0eTsKCQlzdGF0aWMgcHVibGljIGZ1bmN0aW9uIGdldCBjb2x1bW5CcmVha0FmdGVyUHJvcGVydHkoKTpQcm9wZXJ0eQoJCXsKCQkJaWYgKCFfY29sdW1uQnJlYWtBZnRlclByb3BlcnR5KQoJCQkJX2NvbHVtbkJyZWFrQWZ0ZXJQcm9wZXJ0eSA9IFByb3BlcnR5Lk5ld0VudW1TdHJpbmdQcm9wZXJ0eSgKCQkJCSJjb2x1bW5CcmVha0FmdGVyIixCcmVha1N0eWxlLkFVVE8sZmFsc2UsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5QQVJBR1JBUEhdKQoJCQkJLEJyZWFrU3R5bGUuQVVUTwoJCQkJLEJyZWFrU3R5bGUuQUxXQVlTCgkJCQkpOwoJCQlyZXR1cm4gX2NvbHVtbkJyZWFrQWZ0ZXJQcm9wZXJ0eTsKCQl9CgkJLyoqIEBwcml2YXRlICovCgkJc3RhdGljIHByaXZhdGUgdmFyIF9jb250YWluZXJCcmVha0JlZm9yZVByb3BlcnR5OlByb3BlcnR5OwoJCXN0YXRpYyBwdWJsaWMgZnVuY3Rpb24gZ2V0IGNvbnRhaW5lckJyZWFrQmVmb3JlUHJvcGVydHkoKTpQcm9wZXJ0eQoJCXsKCQkJaWYgKCFfY29udGFpbmVyQnJlYWtCZWZvcmVQcm9wZXJ0eSkKCQkJCV9jb250YWluZXJCcmVha0JlZm9yZVByb3BlcnR5ID0gUHJvcGVydHkuTmV3RW51bVN0cmluZ1Byb3BlcnR5KAoJCQkJImNvbnRhaW5lckJyZWFrQmVmb3JlIixCcmVha1N0eWxlLkFVVE8sZmFsc2UsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5QQVJBR1JBUEhdKQoJCQkJLEJyZWFrU3R5bGUuQVVUTwoJCQkJLEJyZWFrU3R5bGUuQUxXQVlTCgkJCQkpOwoJCQlyZXR1cm4gX2NvbnRhaW5lckJyZWFrQmVmb3JlUHJvcGVydHk7CgkJfQoJCS8qKiBAcHJpdmF0ZSAqLwoJCXN0YXRpYyBwcml2YXRlIHZhciBfY29udGFpbmVyQnJlYWtBZnRlclByb3BlcnR5OlByb3BlcnR5OwoJCXN0YXRpYyBwdWJsaWMgZnVuY3Rpb24gZ2V0IGNvbnRhaW5lckJyZWFrQWZ0ZXJQcm9wZXJ0eSgpOlByb3BlcnR5CgkJewoJCQlpZiAoIV9jb250YWluZXJCcmVha0FmdGVyUHJvcGVydHkpCgkJCQlfY29udGFpbmVyQnJlYWtBZnRlclByb3BlcnR5ID0gUHJvcGVydHkuTmV3RW51bVN0cmluZ1Byb3BlcnR5KAoJCQkJImNvbnRhaW5lckJyZWFrQWZ0ZXIiLEJyZWFrU3R5bGUuQVVUTyxmYWxzZSxWZWN0b3IuPFN0cmluZz4oW0NhdGVnb3J5LlBBUkFHUkFQSF0pCgkJCQksQnJlYWtTdHlsZS5BVVRPCgkJCQksQnJlYWtTdHlsZS5BTFdBWVMKCQkJCSk7CgkJCXJldHVybiBfY29udGFpbmVyQnJlYWtBZnRlclByb3BlcnR5OwoJCX0KCQkvKiogQHByaXZhdGUgKi8KCQlzdGF0aWMgcHJpdmF0ZSB2YXIgX2NvbG9yUHJvcGVydHk6UHJvcGVydHk7CgkJc3RhdGljIHB1YmxpYyBmdW5jdGlvbiBnZXQgY29sb3JQcm9wZXJ0eSgpOlByb3BlcnR5CgkJewoJCQlpZiAoIV9jb2xvclByb3BlcnR5KQoJCQlfY29sb3JQcm9wZXJ0eSA9IFByb3BlcnR5Lk5ld1VpbnRPckVudW1Qcm9wZXJ0eSgKCQkJCSJjb2xvciIsMCx0cnVlLFZlY3Rvci48U3RyaW5nPihbQ2F0ZWdvcnkuQ0hBUkFDVEVSXSkKCQkJCSxDb2xvck5hbWUuQkxBQ0sKCQkJCSxDb2xvck5hbWUuR1JFRU4KCQkJCSxDb2xvck5hbWUuR1JBWQoJCQkJLENvbG9yTmFtZS5CTFVFCgkJCQksQ29sb3JOYW1lLlNJTFZFUgoJCQkJLENvbG9yTmFtZS5MSU1FCgkJCQksQ29sb3JOYW1lLk9MSVZFCgkJCQksQ29sb3JOYW1lLldISVRFCgkJCQksQ29sb3JOYW1lLllFTExPVwoJCQkJLENvbG9yTmFtZS5NQVJPT04KCQkJCSxDb2xvck5hbWUuTkFWWQoJCQkJLENvbG9yTmFtZS5SRUQKCQkJCSxDb2xvck5hbWUuUFVSUExFCgkJCQksQ29sb3JOYW1lLlRFQUwKCQkJCSxDb2xvck5hbWUuRlVDSFNJQQoJCQkJLENvbG9yTmFtZS5BUVVBCgkJCQksQ29sb3JOYW1lLk1BR0VOVEEKCQkJCSxDb2xvck5hbWUuQ1lBTgoJCQkpOwoJCQlyZXR1cm4gX2NvbG9yUHJvcGVydHk7CgkJfQoJCS8qKiBAcHJpdmF0ZSAqLwoJCXN0YXRpYyBwcml2YXRlIHZhciBfYmFja2dyb3VuZENvbG9yUHJvcGVydHk6UHJvcGVydHk7CgkJc3RhdGljIHB1YmxpYyBmdW5jdGlvbiBnZXQgYmFja2dyb3VuZENvbG9yUHJvcGVydHkoKTpQcm9wZXJ0eQoJCXsKCQkJaWYgKCFfYmFja2dyb3VuZENvbG9yUHJvcGVydHkpCgkJCV9iYWNrZ3JvdW5kQ29sb3JQcm9wZXJ0eSA9IFByb3BlcnR5Lk5ld1VpbnRPckVudW1Qcm9wZXJ0eSgKCQkJCSJiYWNrZ3JvdW5kQ29sb3IiLEJhY2tncm91bmRDb2xvci5UUkFOU1BBUkVOVCxmYWxzZSxWZWN0b3IuPFN0cmluZz4oW0NhdGVnb3J5LkNIQVJBQ1RFUixDYXRlZ29yeS5QQVJBR1JBUEgsQ2F0ZWdvcnkuQ09OVEFJTkVSLENhdGVnb3J5LlRBQkxFLENhdGVnb3J5LlRBQkxFUk9XLENhdGVnb3J5LlRBQkxFQ09MVU1OLENhdGVnb3J5LlRBQkxFQ0VMTF0pCgkJCQksQmFja2dyb3VuZENvbG9yLlRSQU5TUEFSRU5UCgkJCSk7CgkJCXJldHVybiBfYmFja2dyb3VuZENvbG9yUHJvcGVydHk7CgkJfQoJCS8qKiBAcHJpdmF0ZSAqLwoJCXN0YXRpYyBwcml2YXRlIHZhciBfbGluZVRocm91Z2hQcm9wZXJ0eTpQcm9wZXJ0eTsKCQlzdGF0aWMgcHVibGljIGZ1bmN0aW9uIGdldCBsaW5lVGhyb3VnaFByb3BlcnR5KCk6UHJvcGVydHkKCQl7CgkJCWlmICghX2xpbmVUaHJvdWdoUHJvcGVydHkpCgkJCV9saW5lVGhyb3VnaFByb3BlcnR5ID0gUHJvcGVydHkuTmV3Qm9vbGVhblByb3BlcnR5KCJsaW5lVGhyb3VnaCIsZmFsc2UsdHJ1ZSxWZWN0b3IuPFN0cmluZz4oW0NhdGVnb3J5LkNIQVJBQ1RFUl0pKTsKCQkJcmV0dXJuIF9saW5lVGhyb3VnaFByb3BlcnR5OwoJCX0KCQkvKiogQHByaXZhdGUgKi8KCQlzdGF0aWMgcHJpdmF0ZSB2YXIgX3RleHRBbHBoYVByb3BlcnR5OlByb3BlcnR5OwoJCXN0YXRpYyBwdWJsaWMgZnVuY3Rpb24gZ2V0IHRleHRBbHBoYVByb3BlcnR5KCk6UHJvcGVydHkKCQl7CgkJCWlmICghX3RleHRBbHBoYVByb3BlcnR5KQoJCQlfdGV4dEFscGhhUHJvcGVydHkgPSBQcm9wZXJ0eS5OZXdOdW1iZXJQcm9wZXJ0eSgidGV4dEFscGhhIiwxLHRydWUsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5DSEFSQUNURVJdKSwwLDEpOwoJCQlyZXR1cm4gX3RleHRBbHBoYVByb3BlcnR5OwoJCX0KCQkvKiogQHByaXZhdGUgKi8KCQlzdGF0aWMgcHJpdmF0ZSB2YXIgX2JhY2tncm91bmRBbHBoYVByb3BlcnR5OlByb3BlcnR5OwoJCXN0YXRpYyBwdWJsaWMgZnVuY3Rpb24gZ2V0IGJhY2tncm91bmRBbHBoYVByb3BlcnR5KCk6UHJvcGVydHkKCQl7CgkJCWlmICghX2JhY2tncm91bmRBbHBoYVByb3BlcnR5KQoJCQlfYmFja2dyb3VuZEFscGhhUHJvcGVydHkgPSBQcm9wZXJ0eS5OZXdOdW1iZXJQcm9wZXJ0eSgiYmFja2dyb3VuZEFscGhhIiwxLGZhbHNlLFZlY3Rvci48U3RyaW5nPihbQ2F0ZWdvcnkuQ0hBUkFDVEVSXSksMCwxKTsKCQkJcmV0dXJuIF9iYWNrZ3JvdW5kQWxwaGFQcm9wZXJ0eTsKCQl9CgkJLyoqIEBwcml2YXRlICovCgkJc3RhdGljIHByaXZhdGUgdmFyIF9mb250U2l6ZVByb3BlcnR5OlByb3BlcnR5OwoJCXN0YXRpYyBwdWJsaWMgZnVuY3Rpb24gZ2V0IGZvbnRTaXplUHJvcGVydHkoKTpQcm9wZXJ0eQoJCXsKCQkJaWYgKCFfZm9udFNpemVQcm9wZXJ0eSkKCQkJX2ZvbnRTaXplUHJvcGVydHkgPSBQcm9wZXJ0eS5OZXdOdW1iZXJQcm9wZXJ0eSgiZm9udFNpemUiLDEyLHRydWUsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5DSEFSQUNURVJdKSwxLDcyMCk7CgkJCXJldHVybiBfZm9udFNpemVQcm9wZXJ0eTsKCQl9CgkJLyoqIEBwcml2YXRlICovCgkJc3RhdGljIHByaXZhdGUgdmFyIF9iYXNlbGluZVNoaWZ0UHJvcGVydHk6UHJvcGVydHk7CgkJc3RhdGljIHB1YmxpYyBmdW5jdGlvbiBnZXQgYmFzZWxpbmVTaGlmdFByb3BlcnR5KCk6UHJvcGVydHkKCQl7CgkJCWlmICghX2Jhc2VsaW5lU2hpZnRQcm9wZXJ0eSkKCQkJX2Jhc2VsaW5lU2hpZnRQcm9wZXJ0eSA9IFByb3BlcnR5Lk5ld051bWJlck9yUGVyY2VudE9yRW51bVByb3BlcnR5KCJiYXNlbGluZVNoaWZ0IiwwLjAsdHJ1ZSxWZWN0b3IuPFN0cmluZz4oW0NhdGVnb3J5LkNIQVJBQ1RFUl0pLC0xMDAwLDEwMDAsIi0xMDAwJSIsIjEwMDAlIgoJCQkJLEJhc2VsaW5lU2hpZnQuU1VQRVJTQ1JJUFQKCQkJCSxCYXNlbGluZVNoaWZ0LlNVQlNDUklQVAoJCQkpOwoJCQlyZXR1cm4gX2Jhc2VsaW5lU2hpZnRQcm9wZXJ0eTsKCQl9CgkJLyoqIEBwcml2YXRlICovCgkJc3RhdGljIHByaXZhdGUgdmFyIF90cmFja2luZ0xlZnRQcm9wZXJ0eTpQcm9wZXJ0eTsKCQlzdGF0aWMgcHVibGljIGZ1bmN0aW9uIGdldCB0cmFja2luZ0xlZnRQcm9wZXJ0eSgpOlByb3BlcnR5CgkJewoJCQlpZiAoIV90cmFja2luZ0xlZnRQcm9wZXJ0eSkKCQkJX3RyYWNraW5nTGVmdFByb3BlcnR5ID0gUHJvcGVydHkuTmV3TnVtYmVyT3JQZXJjZW50UHJvcGVydHkoInRyYWNraW5nTGVmdCIsMCx0cnVlLFZlY3Rvci48U3RyaW5nPihbQ2F0ZWdvcnkuQ0hBUkFDVEVSXSksLTEwMDAsMTAwMCwiLTEwMDAlIiwiMTAwMCUiKQoJCQlyZXR1cm4gX3RyYWNraW5nTGVmdFByb3BlcnR5OwoJCX0KCQkvKiogQHByaXZhdGUgKi8KCQlzdGF0aWMgcHJpdmF0ZSB2YXIgX3RyYWNraW5nUmlnaHRQcm9wZXJ0eTpQcm9wZXJ0eTsKCQlzdGF0aWMgcHVibGljIGZ1bmN0aW9uIGdldCB0cmFja2luZ1JpZ2h0UHJvcGVydHkoKTpQcm9wZXJ0eQoJCXsKCQkJaWYgKCFfdHJhY2tpbmdSaWdodFByb3BlcnR5KQoJCQlfdHJhY2tpbmdSaWdodFByb3BlcnR5ID0gUHJvcGVydHkuTmV3TnVtYmVyT3JQZXJjZW50UHJvcGVydHkoInRyYWNraW5nUmlnaHQiLDAsdHJ1ZSxWZWN0b3IuPFN0cmluZz4oW0NhdGVnb3J5LkNIQVJBQ1RFUl0pLC0xMDAwLDEwMDAsIi0xMDAwJSIsIjEwMDAlIikKCQkJcmV0dXJuIF90cmFja2luZ1JpZ2h0UHJvcGVydHk7CgkJfQoJCS8qKiBAcHJpdmF0ZSAqLwoJCXN0YXRpYyBwcml2YXRlIHZhciBfbGluZUhlaWdodFByb3BlcnR5OlByb3BlcnR5OwoJCXN0YXRpYyBwdWJsaWMgZnVuY3Rpb24gZ2V0IGxpbmVIZWlnaHRQcm9wZXJ0eSgpOlByb3BlcnR5CgkJewoJCQlpZiAoIV9saW5lSGVpZ2h0UHJvcGVydHkpCgkJCV9saW5lSGVpZ2h0UHJvcGVydHkgPSBQcm9wZXJ0eS5OZXdOdW1iZXJPclBlcmNlbnRQcm9wZXJ0eSgibGluZUhlaWdodCIsIjEyMCUiLHRydWUsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5DSEFSQUNURVJdKSwtNzIwLDcyMCwiLTEwMDAlIiwiMTAwMCUiKQoJCQlyZXR1cm4gX2xpbmVIZWlnaHRQcm9wZXJ0eTsKCQl9CgkJLyoqIEBwcml2YXRlICovCgkJc3RhdGljIHByaXZhdGUgdmFyIF9icmVha09wcG9ydHVuaXR5UHJvcGVydHk6UHJvcGVydHk7CgkJc3RhdGljIHB1YmxpYyBmdW5jdGlvbiBnZXQgYnJlYWtPcHBvcnR1bml0eVByb3BlcnR5KCk6UHJvcGVydHkKCQl7CgkJCWlmICghX2JyZWFrT3Bwb3J0dW5pdHlQcm9wZXJ0eSkKCQkJCV9icmVha09wcG9ydHVuaXR5UHJvcGVydHkgPSBQcm9wZXJ0eS5OZXdFbnVtU3RyaW5nUHJvcGVydHkoCgkJCQkiYnJlYWtPcHBvcnR1bml0eSIsQnJlYWtPcHBvcnR1bml0eS5BVVRPLHRydWUsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5DSEFSQUNURVJdKQoJCQkJLEJyZWFrT3Bwb3J0dW5pdHkuQUxMCgkJCQksQnJlYWtPcHBvcnR1bml0eS5BTlkKCQkJCSxCcmVha09wcG9ydHVuaXR5LkFVVE8KCQkJCSxCcmVha09wcG9ydHVuaXR5Lk5PTkUKCQkJCSk7CgkJCXJldHVybiBfYnJlYWtPcHBvcnR1bml0eVByb3BlcnR5OwoJCX0KCQkvKiogQHByaXZhdGUgKi8KCQlzdGF0aWMgcHJpdmF0ZSB2YXIgX2RpZ2l0Q2FzZVByb3BlcnR5OlByb3BlcnR5OwoJCXN0YXRpYyBwdWJsaWMgZnVuY3Rpb24gZ2V0IGRpZ2l0Q2FzZVByb3BlcnR5KCk6UHJvcGVydHkKCQl7CgkJCWlmICghX2RpZ2l0Q2FzZVByb3BlcnR5KQoJCQkJX2RpZ2l0Q2FzZVByb3BlcnR5ID0gUHJvcGVydHkuTmV3RW51bVN0cmluZ1Byb3BlcnR5KAoJCQkJImRpZ2l0Q2FzZSIsRGlnaXRDYXNlLkRFRkFVTFQsdHJ1ZSxWZWN0b3IuPFN0cmluZz4oW0NhdGVnb3J5LkNIQVJBQ1RFUl0pCgkJCQksRGlnaXRDYXNlLkRFRkFVTFQKCQkJCSxEaWdpdENhc2UuTElOSU5HCgkJCQksRGlnaXRDYXNlLk9MRF9TVFlMRQoJCQkJKTsKCQkJcmV0dXJuIF9kaWdpdENhc2VQcm9wZXJ0eTsKCQl9CgkJLyoqIEBwcml2YXRlICovCgkJc3RhdGljIHByaXZhdGUgdmFyIF9kaWdpdFdpZHRoUHJvcGVydHk6UHJvcGVydHk7CgkJc3RhdGljIHB1YmxpYyBmdW5jdGlvbiBnZXQgZGlnaXRXaWR0aFByb3BlcnR5KCk6UHJvcGVydHkKCQl7CgkJCWlmICghX2RpZ2l0V2lkdGhQcm9wZXJ0eSkKCQkJCV9kaWdpdFdpZHRoUHJvcGVydHkgPSBQcm9wZXJ0eS5OZXdFbnVtU3RyaW5nUHJvcGVydHkoCgkJCQkiZGlnaXRXaWR0aCIsRGlnaXRXaWR0aC5ERUZBVUxULHRydWUsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5DSEFSQUNURVJdKQoJCQkJLERpZ2l0V2lkdGguREVGQVVMVAoJCQkJLERpZ2l0V2lkdGguUFJPUE9SVElPTkFMCgkJCQksRGlnaXRXaWR0aC5UQUJVTEFSCgkJCQkpOwoJCQlyZXR1cm4gX2RpZ2l0V2lkdGhQcm9wZXJ0eTsKCQl9CgkJLyoqIEBwcml2YXRlICovCgkJc3RhdGljIHByaXZhdGUgdmFyIF9kb21pbmFudEJhc2VsaW5lUHJvcGVydHk6UHJvcGVydHk7CgkJc3RhdGljIHB1YmxpYyBmdW5jdGlvbiBnZXQgZG9taW5hbnRCYXNlbGluZVByb3BlcnR5KCk6UHJvcGVydHkKCQl7CgkJCWlmICghX2RvbWluYW50QmFzZWxpbmVQcm9wZXJ0eSkKCQkJCV9kb21pbmFudEJhc2VsaW5lUHJvcGVydHkgPSBQcm9wZXJ0eS5OZXdFbnVtU3RyaW5nUHJvcGVydHkoCgkJCQkiZG9taW5hbnRCYXNlbGluZSIsRm9ybWF0VmFsdWUuQVVUTyx0cnVlLFZlY3Rvci48U3RyaW5nPihbQ2F0ZWdvcnkuQ0hBUkFDVEVSXSkKCQkJCSxGb3JtYXRWYWx1ZS5BVVRPCgkJCQksVGV4dEJhc2VsaW5lLlJPTUFOCgkJCQksVGV4dEJhc2VsaW5lLkFTQ0VOVAoJCQkJLFRleHRCYXNlbGluZS5ERVNDRU5UCgkJCQksVGV4dEJhc2VsaW5lLklERU9HUkFQSElDX1RPUAoJCQkJLFRleHRCYXNlbGluZS5JREVPR1JBUEhJQ19DRU5URVIKCQkJCSxUZXh0QmFzZWxpbmUuSURFT0dSQVBISUNfQk9UVE9NCgkJCQkpOwoJCQlyZXR1cm4gX2RvbWluYW50QmFzZWxpbmVQcm9wZXJ0eTsKCQl9CgkJLyoqIEBwcml2YXRlICovCgkJc3RhdGljIHByaXZhdGUgdmFyIF9rZXJuaW5nUHJvcGVydHk6UHJvcGVydHk7CgkJc3RhdGljIHB1YmxpYyBmdW5jdGlvbiBnZXQga2VybmluZ1Byb3BlcnR5KCk6UHJvcGVydHkKCQl7CgkJCWlmICghX2tlcm5pbmdQcm9wZXJ0eSkKCQkJCV9rZXJuaW5nUHJvcGVydHkgPSBQcm9wZXJ0eS5OZXdFbnVtU3RyaW5nUHJvcGVydHkoCgkJCQkia2VybmluZyIsS2VybmluZy5BVVRPLHRydWUsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5DSEFSQUNURVJdKQoJCQkJLEtlcm5pbmcuT04KCQkJCSxLZXJuaW5nLk9GRgoJCQkJLEtlcm5pbmcuQVVUTwoJCQkJKTsKCQkJcmV0dXJuIF9rZXJuaW5nUHJvcGVydHk7CgkJfQoJCS8qKiBAcHJpdmF0ZSAqLwoJCXN0YXRpYyBwcml2YXRlIHZhciBfbGlnYXR1cmVMZXZlbFByb3BlcnR5OlByb3BlcnR5OwoJCXN0YXRpYyBwdWJsaWMgZnVuY3Rpb24gZ2V0IGxpZ2F0dXJlTGV2ZWxQcm9wZXJ0eSgpOlByb3BlcnR5CgkJewoJCQlpZiAoIV9saWdhdHVyZUxldmVsUHJvcGVydHkpCgkJCQlfbGlnYXR1cmVMZXZlbFByb3BlcnR5ID0gUHJvcGVydHkuTmV3RW51bVN0cmluZ1Byb3BlcnR5KAoJCQkJImxpZ2F0dXJlTGV2ZWwiLExpZ2F0dXJlTGV2ZWwuQ09NTU9OLHRydWUsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5DSEFSQUNURVJdKQoJCQkJLExpZ2F0dXJlTGV2ZWwuTUlOSU1VTQoJCQkJLExpZ2F0dXJlTGV2ZWwuQ09NTU9OCgkJCQksTGlnYXR1cmVMZXZlbC5VTkNPTU1PTgoJCQkJLExpZ2F0dXJlTGV2ZWwuRVhPVElDCgkJCQkpOwoJCQlyZXR1cm4gX2xpZ2F0dXJlTGV2ZWxQcm9wZXJ0eTsKCQl9CgkJLyoqIEBwcml2YXRlICovCgkJc3RhdGljIHByaXZhdGUgdmFyIF9hbGlnbm1lbnRCYXNlbGluZVByb3BlcnR5OlByb3BlcnR5OwoJCXN0YXRpYyBwdWJsaWMgZnVuY3Rpb24gZ2V0IGFsaWdubWVudEJhc2VsaW5lUHJvcGVydHkoKTpQcm9wZXJ0eQoJCXsKCQkJaWYgKCFfYWxpZ25tZW50QmFzZWxpbmVQcm9wZXJ0eSkKCQkJCV9hbGlnbm1lbnRCYXNlbGluZVByb3BlcnR5ID0gUHJvcGVydHkuTmV3RW51bVN0cmluZ1Byb3BlcnR5KAoJCQkJImFsaWdubWVudEJhc2VsaW5lIixUZXh0QmFzZWxpbmUuVVNFX0RPTUlOQU5UX0JBU0VMSU5FLHRydWUsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5DSEFSQUNURVJdKQoJCQkJLFRleHRCYXNlbGluZS5ST01BTgoJCQkJLFRleHRCYXNlbGluZS5BU0NFTlQKCQkJCSxUZXh0QmFzZWxpbmUuREVTQ0VOVAoJCQkJLFRleHRCYXNlbGluZS5JREVPR1JBUEhJQ19UT1AKCQkJCSxUZXh0QmFzZWxpbmUuSURFT0dSQVBISUNfQ0VOVEVSCgkJCQksVGV4dEJhc2VsaW5lLklERU9HUkFQSElDX0JPVFRPTQoJCQkJLFRleHRCYXNlbGluZS5VU0VfRE9NSU5BTlRfQkFTRUxJTkUKCQkJCSk7CgkJCXJldHVybiBfYWxpZ25tZW50QmFzZWxpbmVQcm9wZXJ0eTsKCQl9CgkJLyoqIEBwcml2YXRlICovCgkJc3RhdGljIHByaXZhdGUgdmFyIF9sb2NhbGVQcm9wZXJ0eTpQcm9wZXJ0eTsKCQlzdGF0aWMgcHVibGljIGZ1bmN0aW9uIGdldCBsb2NhbGVQcm9wZXJ0eSgpOlByb3BlcnR5CgkJewoJCQlpZiAoIV9sb2NhbGVQcm9wZXJ0eSkKCQkJX2xvY2FsZVByb3BlcnR5ID0gUHJvcGVydHkuTmV3U3RyaW5nUHJvcGVydHkoImxvY2FsZSIsImVuIix0cnVlLFZlY3Rvci48U3RyaW5nPihbQ2F0ZWdvcnkuQ0hBUkFDVEVSLENhdGVnb3J5LlBBUkFHUkFQSF0pKTsKCQkJcmV0dXJuIF9sb2NhbGVQcm9wZXJ0eTsKCQl9CgkJLyoqIEBwcml2YXRlICovCgkJc3RhdGljIHByaXZhdGUgdmFyIF90eXBvZ3JhcGhpY0Nhc2VQcm9wZXJ0eTpQcm9wZXJ0eTsKCQlzdGF0aWMgcHVibGljIGZ1bmN0aW9uIGdldCB0eXBvZ3JhcGhpY0Nhc2VQcm9wZXJ0eSgpOlByb3BlcnR5CgkJewoJCQlpZiAoIV90eXBvZ3JhcGhpY0Nhc2VQcm9wZXJ0eSkKCQkJCV90eXBvZ3JhcGhpY0Nhc2VQcm9wZXJ0eSA9IFByb3BlcnR5Lk5ld0VudW1TdHJpbmdQcm9wZXJ0eSgKCQkJCSJ0eXBvZ3JhcGhpY0Nhc2UiLFRMRlR5cG9ncmFwaGljQ2FzZS5ERUZBVUxULHRydWUsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5DSEFSQUNURVJdKQoJCQkJLFRMRlR5cG9ncmFwaGljQ2FzZS5ERUZBVUxUCgkJCQksVExGVHlwb2dyYXBoaWNDYXNlLkNBUFNfVE9fU01BTExfQ0FQUwoJCQkJLFRMRlR5cG9ncmFwaGljQ2FzZS5VUFBFUkNBU0UKCQkJCSxUTEZUeXBvZ3JhcGhpY0Nhc2UuTE9XRVJDQVNFCgkJCQksVExGVHlwb2dyYXBoaWNDYXNlLkxPV0VSQ0FTRV9UT19TTUFMTF9DQVBTCgkJCQkpOwoJCQlyZXR1cm4gX3R5cG9ncmFwaGljQ2FzZVByb3BlcnR5OwoJCX0KCQkvKiogQHByaXZhdGUgKi8KCQlzdGF0aWMgcHJpdmF0ZSB2YXIgX2ZvbnRGYW1pbHlQcm9wZXJ0eTpQcm9wZXJ0eTsKCQlzdGF0aWMgcHVibGljIGZ1bmN0aW9uIGdldCBmb250RmFtaWx5UHJvcGVydHkoKTpQcm9wZXJ0eQoJCXsKCQkJaWYgKCFfZm9udEZhbWlseVByb3BlcnR5KQoJCQlfZm9udEZhbWlseVByb3BlcnR5ID0gUHJvcGVydHkuTmV3U3RyaW5nUHJvcGVydHkoImZvbnRGYW1pbHkiLCJBcmlhbCIsdHJ1ZSxWZWN0b3IuPFN0cmluZz4oW0NhdGVnb3J5LkNIQVJBQ1RFUl0pKTsKCQkJcmV0dXJuIF9mb250RmFtaWx5UHJvcGVydHk7CgkJfQoJCS8qKiBAcHJpdmF0ZSAqLwoJCXN0YXRpYyBwcml2YXRlIHZhciBfdGV4dERlY29yYXRpb25Qcm9wZXJ0eTpQcm9wZXJ0eTsKCQlzdGF0aWMgcHVibGljIGZ1bmN0aW9uIGdldCB0ZXh0RGVjb3JhdGlvblByb3BlcnR5KCk6UHJvcGVydHkKCQl7CgkJCWlmICghX3RleHREZWNvcmF0aW9uUHJvcGVydHkpCgkJCQlfdGV4dERlY29yYXRpb25Qcm9wZXJ0eSA9IFByb3BlcnR5Lk5ld0VudW1TdHJpbmdQcm9wZXJ0eSgKCQkJCSJ0ZXh0RGVjb3JhdGlvbiIsVGV4dERlY29yYXRpb24uTk9ORSx0cnVlLFZlY3Rvci48U3RyaW5nPihbQ2F0ZWdvcnkuQ0hBUkFDVEVSXSkKCQkJCSxUZXh0RGVjb3JhdGlvbi5OT05FCgkJCQksVGV4dERlY29yYXRpb24uVU5ERVJMSU5FCgkJCQkpOwoJCQlyZXR1cm4gX3RleHREZWNvcmF0aW9uUHJvcGVydHk7CgkJfQoJCS8qKiBAcHJpdmF0ZSAqLwoJCXN0YXRpYyBwcml2YXRlIHZhciBfZm9udFdlaWdodFByb3BlcnR5OlByb3BlcnR5OwoJCXN0YXRpYyBwdWJsaWMgZnVuY3Rpb24gZ2V0IGZvbnRXZWlnaHRQcm9wZXJ0eSgpOlByb3BlcnR5CgkJewoJCQlpZiAoIV9mb250V2VpZ2h0UHJvcGVydHkpCgkJCQlfZm9udFdlaWdodFByb3BlcnR5ID0gUHJvcGVydHkuTmV3RW51bVN0cmluZ1Byb3BlcnR5KAoJCQkJImZvbnRXZWlnaHQiLEZvbnRXZWlnaHQuTk9STUFMLHRydWUsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5DSEFSQUNURVJdKQoJCQkJLEZvbnRXZWlnaHQuTk9STUFMCgkJCQksRm9udFdlaWdodC5CT0xECgkJCQkpOwoJCQlyZXR1cm4gX2ZvbnRXZWlnaHRQcm9wZXJ0eTsKCQl9CgkJLyoqIEBwcml2YXRlICovCgkJc3RhdGljIHByaXZhdGUgdmFyIF9mb250U3R5bGVQcm9wZXJ0eTpQcm9wZXJ0eTsKCQlzdGF0aWMgcHVibGljIGZ1bmN0aW9uIGdldCBmb250U3R5bGVQcm9wZXJ0eSgpOlByb3BlcnR5CgkJewoJCQlpZiAoIV9mb250U3R5bGVQcm9wZXJ0eSkKCQkJCV9mb250U3R5bGVQcm9wZXJ0eSA9IFByb3BlcnR5Lk5ld0VudW1TdHJpbmdQcm9wZXJ0eSgKCQkJCSJmb250U3R5bGUiLEZvbnRQb3N0dXJlLk5PUk1BTCx0cnVlLFZlY3Rvci48U3RyaW5nPihbQ2F0ZWdvcnkuQ0hBUkFDVEVSXSkKCQkJCSxGb250UG9zdHVyZS5OT1JNQUwKCQkJCSxGb250UG9zdHVyZS5JVEFMSUMKCQkJCSk7CgkJCXJldHVybiBfZm9udFN0eWxlUHJvcGVydHk7CgkJfQoJCS8qKiBAcHJpdmF0ZSAqLwoJCXN0YXRpYyBwcml2YXRlIHZhciBfd2hpdGVTcGFjZUNvbGxhcHNlUHJvcGVydHk6UHJvcGVydHk7CgkJc3RhdGljIHB1YmxpYyBmdW5jdGlvbiBnZXQgd2hpdGVTcGFjZUNvbGxhcHNlUHJvcGVydHkoKTpQcm9wZXJ0eQoJCXsKCQkJaWYgKCFfd2hpdGVTcGFjZUNvbGxhcHNlUHJvcGVydHkpCgkJCQlfd2hpdGVTcGFjZUNvbGxhcHNlUHJvcGVydHkgPSBQcm9wZXJ0eS5OZXdFbnVtU3RyaW5nUHJvcGVydHkoCgkJCQkid2hpdGVTcGFjZUNvbGxhcHNlIixXaGl0ZVNwYWNlQ29sbGFwc2UuQ09MTEFQU0UsdHJ1ZSxWZWN0b3IuPFN0cmluZz4oW0NhdGVnb3J5LkNIQVJBQ1RFUl0pCgkJCQksV2hpdGVTcGFjZUNvbGxhcHNlLlBSRVNFUlZFCgkJCQksV2hpdGVTcGFjZUNvbGxhcHNlLkNPTExBUFNFCgkJCQkpOwoJCQlyZXR1cm4gX3doaXRlU3BhY2VDb2xsYXBzZVByb3BlcnR5OwoJCX0KCQkvKiogQHByaXZhdGUgKi8KCQlzdGF0aWMgcHJpdmF0ZSB2YXIgX3JlbmRlcmluZ01vZGVQcm9wZXJ0eTpQcm9wZXJ0eTsKCQlzdGF0aWMgcHVibGljIGZ1bmN0aW9uIGdldCByZW5kZXJpbmdNb2RlUHJvcGVydHkoKTpQcm9wZXJ0eQoJCXsKCQkJaWYgKCFfcmVuZGVyaW5nTW9kZVByb3BlcnR5KQoJCQkJX3JlbmRlcmluZ01vZGVQcm9wZXJ0eSA9IFByb3BlcnR5Lk5ld0VudW1TdHJpbmdQcm9wZXJ0eSgKCQkJCSJyZW5kZXJpbmdNb2RlIixSZW5kZXJpbmdNb2RlLkNGRix0cnVlLFZlY3Rvci48U3RyaW5nPihbQ2F0ZWdvcnkuQ0hBUkFDVEVSXSkKCQkJCSxSZW5kZXJpbmdNb2RlLk5PUk1BTAoJCQkJLFJlbmRlcmluZ01vZGUuQ0ZGCgkJCQkpOwoJCQlyZXR1cm4gX3JlbmRlcmluZ01vZGVQcm9wZXJ0eTsKCQl9CgkJLyoqIEBwcml2YXRlICovCgkJc3RhdGljIHByaXZhdGUgdmFyIF9jZmZIaW50aW5nUHJvcGVydHk6UHJvcGVydHk7CgkJc3RhdGljIHB1YmxpYyBmdW5jdGlvbiBnZXQgY2ZmSGludGluZ1Byb3BlcnR5KCk6UHJvcGVydHkKCQl7CgkJCWlmICghX2NmZkhpbnRpbmdQcm9wZXJ0eSkKCQkJCV9jZmZIaW50aW5nUHJvcGVydHkgPSBQcm9wZXJ0eS5OZXdFbnVtU3RyaW5nUHJvcGVydHkoCgkJCQkiY2ZmSGludGluZyIsQ0ZGSGludGluZy5IT1JJWk9OVEFMX1NURU0sdHJ1ZSxWZWN0b3IuPFN0cmluZz4oW0NhdGVnb3J5LkNIQVJBQ1RFUl0pCgkJCQksQ0ZGSGludGluZy5OT05FCgkJCQksQ0ZGSGludGluZy5IT1JJWk9OVEFMX1NURU0KCQkJCSk7CgkJCXJldHVybiBfY2ZmSGludGluZ1Byb3BlcnR5OwoJCX0KCQkvKiogQHByaXZhdGUgKi8KCQlzdGF0aWMgcHJpdmF0ZSB2YXIgX2ZvbnRMb29rdXBQcm9wZXJ0eTpQcm9wZXJ0eTsKCQlzdGF0aWMgcHVibGljIGZ1bmN0aW9uIGdldCBmb250TG9va3VwUHJvcGVydHkoKTpQcm9wZXJ0eQoJCXsKCQkJaWYgKCFfZm9udExvb2t1cFByb3BlcnR5KQoJCQkJX2ZvbnRMb29rdXBQcm9wZXJ0eSA9IFByb3BlcnR5Lk5ld0VudW1TdHJpbmdQcm9wZXJ0eSgKCQkJCSJmb250TG9va3VwIixGb250TG9va3VwLkRFVklDRSx0cnVlLFZlY3Rvci48U3RyaW5nPihbQ2F0ZWdvcnkuQ0hBUkFDVEVSXSkKCQkJCSxGb250TG9va3VwLkRFVklDRQoJCQkJLEZvbnRMb29rdXAuRU1CRURERURfQ0ZGCgkJCQkpOwoJCQlyZXR1cm4gX2ZvbnRMb29rdXBQcm9wZXJ0eTsKCQl9CgkJLyoqIEBwcml2YXRlICovCgkJc3RhdGljIHByaXZhdGUgdmFyIF90ZXh0Um90YXRpb25Qcm9wZXJ0eTpQcm9wZXJ0eTsKCQlzdGF0aWMgcHVibGljIGZ1bmN0aW9uIGdldCB0ZXh0Um90YXRpb25Qcm9wZXJ0eSgpOlByb3BlcnR5CgkJewoJCQlpZiAoIV90ZXh0Um90YXRpb25Qcm9wZXJ0eSkKCQkJCV90ZXh0Um90YXRpb25Qcm9wZXJ0eSA9IFByb3BlcnR5Lk5ld0VudW1TdHJpbmdQcm9wZXJ0eSgKCQkJCSJ0ZXh0Um90YXRpb24iLFRleHRSb3RhdGlvbi5BVVRPLHRydWUsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5DSEFSQUNURVJdKQoJCQkJLFRleHRSb3RhdGlvbi5ST1RBVEVfMAoJCQkJLFRleHRSb3RhdGlvbi5ST1RBVEVfMTgwCgkJCQksVGV4dFJvdGF0aW9uLlJPVEFURV8yNzAKCQkJCSxUZXh0Um90YXRpb24uUk9UQVRFXzkwCgkJCQksVGV4dFJvdGF0aW9uLkFVVE8KCQkJCSk7CgkJCXJldHVybiBfdGV4dFJvdGF0aW9uUHJvcGVydHk7CgkJfQoJCS8qKiBAcHJpdmF0ZSAqLwoJCXN0YXRpYyBwcml2YXRlIHZhciBfdGV4dEluZGVudFByb3BlcnR5OlByb3BlcnR5OwoJCXN0YXRpYyBwdWJsaWMgZnVuY3Rpb24gZ2V0IHRleHRJbmRlbnRQcm9wZXJ0eSgpOlByb3BlcnR5CgkJewoJCQlpZiAoIV90ZXh0SW5kZW50UHJvcGVydHkpCgkJCV90ZXh0SW5kZW50UHJvcGVydHkgPSBQcm9wZXJ0eS5OZXdOdW1iZXJQcm9wZXJ0eSgidGV4dEluZGVudCIsMCx0cnVlLFZlY3Rvci48U3RyaW5nPihbQ2F0ZWdvcnkuUEFSQUdSQVBIXSksLTgwMDAsODAwMCk7CgkJCXJldHVybiBfdGV4dEluZGVudFByb3BlcnR5OwoJCX0KCQkvKiogQHByaXZhdGUgKi8KCQlzdGF0aWMgcHJpdmF0ZSB2YXIgX3BhcmFncmFwaFN0YXJ0SW5kZW50UHJvcGVydHk6UHJvcGVydHk7CgkJc3RhdGljIHB1YmxpYyBmdW5jdGlvbiBnZXQgcGFyYWdyYXBoU3RhcnRJbmRlbnRQcm9wZXJ0eSgpOlByb3BlcnR5CgkJewoJCQlpZiAoIV9wYXJhZ3JhcGhTdGFydEluZGVudFByb3BlcnR5KQoJCQlfcGFyYWdyYXBoU3RhcnRJbmRlbnRQcm9wZXJ0eSA9IFByb3BlcnR5Lk5ld051bWJlclByb3BlcnR5KCJwYXJhZ3JhcGhTdGFydEluZGVudCIsMCx0cnVlLFZlY3Rvci48U3RyaW5nPihbQ2F0ZWdvcnkuUEFSQUdSQVBIXSksMCw4MDAwKTsKCQkJcmV0dXJuIF9wYXJhZ3JhcGhTdGFydEluZGVudFByb3BlcnR5OwoJCX0KCQkvKiogQHByaXZhdGUgKi8KCQlzdGF0aWMgcHJpdmF0ZSB2YXIgX3BhcmFncmFwaEVuZEluZGVudFByb3BlcnR5OlByb3BlcnR5OwoJCXN0YXRpYyBwdWJsaWMgZnVuY3Rpb24gZ2V0IHBhcmFncmFwaEVuZEluZGVudFByb3BlcnR5KCk6UHJvcGVydHkKCQl7CgkJCWlmICghX3BhcmFncmFwaEVuZEluZGVudFByb3BlcnR5KQoJCQlfcGFyYWdyYXBoRW5kSW5kZW50UHJvcGVydHkgPSBQcm9wZXJ0eS5OZXdOdW1iZXJQcm9wZXJ0eSgicGFyYWdyYXBoRW5kSW5kZW50IiwwLHRydWUsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5QQVJBR1JBUEhdKSwwLDgwMDApOwoJCQlyZXR1cm4gX3BhcmFncmFwaEVuZEluZGVudFByb3BlcnR5OwoJCX0KCQkvKiogQHByaXZhdGUgKi8KCQlzdGF0aWMgcHJpdmF0ZSB2YXIgX3BhcmFncmFwaFNwYWNlQmVmb3JlUHJvcGVydHk6UHJvcGVydHk7CgkJc3RhdGljIHB1YmxpYyBmdW5jdGlvbiBnZXQgcGFyYWdyYXBoU3BhY2VCZWZvcmVQcm9wZXJ0eSgpOlByb3BlcnR5CgkJewoJCQlpZiAoIV9wYXJhZ3JhcGhTcGFjZUJlZm9yZVByb3BlcnR5KQoJCQlfcGFyYWdyYXBoU3BhY2VCZWZvcmVQcm9wZXJ0eSA9IFByb3BlcnR5Lk5ld051bWJlclByb3BlcnR5KCJwYXJhZ3JhcGhTcGFjZUJlZm9yZSIsMCx0cnVlLFZlY3Rvci48U3RyaW5nPihbQ2F0ZWdvcnkuUEFSQUdSQVBIXSksMCw4MDAwKTsKCQkJcmV0dXJuIF9wYXJhZ3JhcGhTcGFjZUJlZm9yZVByb3BlcnR5OwoJCX0KCQkvKiogQHByaXZhdGUgKi8KCQlzdGF0aWMgcHJpdmF0ZSB2YXIgX3BhcmFncmFwaFNwYWNlQWZ0ZXJQcm9wZXJ0eTpQcm9wZXJ0eTsKCQlzdGF0aWMgcHVibGljIGZ1bmN0aW9uIGdldCBwYXJhZ3JhcGhTcGFjZUFmdGVyUHJvcGVydHkoKTpQcm9wZXJ0eQoJCXsKCQkJaWYgKCFfcGFyYWdyYXBoU3BhY2VBZnRlclByb3BlcnR5KQoJCQlfcGFyYWdyYXBoU3BhY2VBZnRlclByb3BlcnR5ID0gUHJvcGVydHkuTmV3TnVtYmVyUHJvcGVydHkoInBhcmFncmFwaFNwYWNlQWZ0ZXIiLDAsdHJ1ZSxWZWN0b3IuPFN0cmluZz4oW0NhdGVnb3J5LlBBUkFHUkFQSF0pLDAsODAwMCk7CgkJCXJldHVybiBfcGFyYWdyYXBoU3BhY2VBZnRlclByb3BlcnR5OwoJCX0KCQkvKiogQHByaXZhdGUgKi8KCQlzdGF0aWMgcHJpdmF0ZSB2YXIgX3RleHRBbGlnblByb3BlcnR5OlByb3BlcnR5OwoJCXN0YXRpYyBwdWJsaWMgZnVuY3Rpb24gZ2V0IHRleHRBbGlnblByb3BlcnR5KCk6UHJvcGVydHkKCQl7CgkJCWlmICghX3RleHRBbGlnblByb3BlcnR5KQoJCQkJX3RleHRBbGlnblByb3BlcnR5ID0gUHJvcGVydHkuTmV3RW51bVN0cmluZ1Byb3BlcnR5KAoJCQkJInRleHRBbGlnbiIsVGV4dEFsaWduLlNUQVJULHRydWUsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5QQVJBR1JBUEgsQ2F0ZWdvcnkuVEFCTEUsQ2F0ZWdvcnkuVEFCTEVDRUxMLENhdGVnb3J5LlRBQkxFUk9XLENhdGVnb3J5LlRBQkxFQ09MVU1OXSkKCQkJCSxUZXh0QWxpZ24uTEVGVAoJCQkJLFRleHRBbGlnbi5SSUdIVAoJCQkJLFRleHRBbGlnbi5DRU5URVIKCQkJCSxUZXh0QWxpZ24uSlVTVElGWQoJCQkJLFRleHRBbGlnbi5TVEFSVAoJCQkJLFRleHRBbGlnbi5FTkQKCQkJCSk7CgkJCXJldHVybiBfdGV4dEFsaWduUHJvcGVydHk7CgkJfQoJCS8qKiBAcHJpdmF0ZSAqLwoJCXN0YXRpYyBwcml2YXRlIHZhciBfdGV4dEFsaWduTGFzdFByb3BlcnR5OlByb3BlcnR5OwoJCXN0YXRpYyBwdWJsaWMgZnVuY3Rpb24gZ2V0IHRleHRBbGlnbkxhc3RQcm9wZXJ0eSgpOlByb3BlcnR5CgkJewoJCQlpZiAoIV90ZXh0QWxpZ25MYXN0UHJvcGVydHkpCgkJCQlfdGV4dEFsaWduTGFzdFByb3BlcnR5ID0gUHJvcGVydHkuTmV3RW51bVN0cmluZ1Byb3BlcnR5KAoJCQkJInRleHRBbGlnbkxhc3QiLFRleHRBbGlnbi5TVEFSVCx0cnVlLFZlY3Rvci48U3RyaW5nPihbQ2F0ZWdvcnkuUEFSQUdSQVBIXSkKCQkJCSxUZXh0QWxpZ24uTEVGVAoJCQkJLFRleHRBbGlnbi5SSUdIVAoJCQkJLFRleHRBbGlnbi5DRU5URVIKCQkJCSxUZXh0QWxpZ24uSlVTVElGWQoJCQkJLFRleHRBbGlnbi5TVEFSVAoJCQkJLFRleHRBbGlnbi5FTkQKCQkJCSk7CgkJCXJldHVybiBfdGV4dEFsaWduTGFzdFByb3BlcnR5OwoJCX0KCQkvKiogQHByaXZhdGUgKi8KCQlzdGF0aWMgcHJpdmF0ZSB2YXIgX3RleHRKdXN0aWZ5UHJvcGVydHk6UHJvcGVydHk7CgkJc3RhdGljIHB1YmxpYyBmdW5jdGlvbiBnZXQgdGV4dEp1c3RpZnlQcm9wZXJ0eSgpOlByb3BlcnR5CgkJewoJCQlpZiAoIV90ZXh0SnVzdGlmeVByb3BlcnR5KQoJCQkJX3RleHRKdXN0aWZ5UHJvcGVydHkgPSBQcm9wZXJ0eS5OZXdFbnVtU3RyaW5nUHJvcGVydHkoCgkJCQkidGV4dEp1c3RpZnkiLFRleHRKdXN0aWZ5LklOVEVSX1dPUkQsdHJ1ZSxWZWN0b3IuPFN0cmluZz4oW0NhdGVnb3J5LlBBUkFHUkFQSF0pCgkJCQksVGV4dEp1c3RpZnkuSU5URVJfV09SRAoJCQkJLFRleHRKdXN0aWZ5LkRJU1RSSUJVVEUKCQkJCSk7CgkJCXJldHVybiBfdGV4dEp1c3RpZnlQcm9wZXJ0eTsKCQl9CgkJLyoqIEBwcml2YXRlICovCgkJc3RhdGljIHByaXZhdGUgdmFyIF9qdXN0aWZpY2F0aW9uUnVsZVByb3BlcnR5OlByb3BlcnR5OwoJCXN0YXRpYyBwdWJsaWMgZnVuY3Rpb24gZ2V0IGp1c3RpZmljYXRpb25SdWxlUHJvcGVydHkoKTpQcm9wZXJ0eQoJCXsKCQkJaWYgKCFfanVzdGlmaWNhdGlvblJ1bGVQcm9wZXJ0eSkKCQkJCV9qdXN0aWZpY2F0aW9uUnVsZVByb3BlcnR5ID0gUHJvcGVydHkuTmV3RW51bVN0cmluZ1Byb3BlcnR5KAoJCQkJImp1c3RpZmljYXRpb25SdWxlIixGb3JtYXRWYWx1ZS5BVVRPLHRydWUsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5QQVJBR1JBUEhdKQoJCQkJLEp1c3RpZmljYXRpb25SdWxlLkVBU1RfQVNJQU4KCQkJCSxKdXN0aWZpY2F0aW9uUnVsZS5TUEFDRQoJCQkJLEZvcm1hdFZhbHVlLkFVVE8KCQkJCSk7CgkJCXJldHVybiBfanVzdGlmaWNhdGlvblJ1bGVQcm9wZXJ0eTsKCQl9CgkJLyoqIEBwcml2YXRlICovCgkJc3RhdGljIHByaXZhdGUgdmFyIF9qdXN0aWZpY2F0aW9uU3R5bGVQcm9wZXJ0eTpQcm9wZXJ0eTsKCQlzdGF0aWMgcHVibGljIGZ1bmN0aW9uIGdldCBqdXN0aWZpY2F0aW9uU3R5bGVQcm9wZXJ0eSgpOlByb3BlcnR5CgkJewoJCQlpZiAoIV9qdXN0aWZpY2F0aW9uU3R5bGVQcm9wZXJ0eSkKCQkJCV9qdXN0aWZpY2F0aW9uU3R5bGVQcm9wZXJ0eSA9IFByb3BlcnR5Lk5ld0VudW1TdHJpbmdQcm9wZXJ0eSgKCQkJCSJqdXN0aWZpY2F0aW9uU3R5bGUiLEZvcm1hdFZhbHVlLkFVVE8sdHJ1ZSxWZWN0b3IuPFN0cmluZz4oW0NhdGVnb3J5LlBBUkFHUkFQSF0pCgkJCQksSnVzdGlmaWNhdGlvblN0eWxlLlBSSU9SSVRJWkVfTEVBU1RfQURKVVNUTUVOVAoJCQkJLEp1c3RpZmljYXRpb25TdHlsZS5QVVNIX0lOX0tJTlNPS1UKCQkJCSxKdXN0aWZpY2F0aW9uU3R5bGUuUFVTSF9PVVRfT05MWQoJCQkJLEZvcm1hdFZhbHVlLkFVVE8KCQkJCSk7CgkJCXJldHVybiBfanVzdGlmaWNhdGlvblN0eWxlUHJvcGVydHk7CgkJfQoJCS8qKiBAcHJpdmF0ZSAqLwoJCXN0YXRpYyBwcml2YXRlIHZhciBfZGlyZWN0aW9uUHJvcGVydHk6UHJvcGVydHk7CgkJc3RhdGljIHB1YmxpYyBmdW5jdGlvbiBnZXQgZGlyZWN0aW9uUHJvcGVydHkoKTpQcm9wZXJ0eQoJCXsKCQkJaWYgKCFfZGlyZWN0aW9uUHJvcGVydHkpCgkJCQlfZGlyZWN0aW9uUHJvcGVydHkgPSBQcm9wZXJ0eS5OZXdFbnVtU3RyaW5nUHJvcGVydHkoCgkJCQkiZGlyZWN0aW9uIixEaXJlY3Rpb24uTFRSLHRydWUsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5QQVJBR1JBUEgsQ2F0ZWdvcnkuVEFCTEUsQ2F0ZWdvcnkuVEFCTEVDRUxMLENhdGVnb3J5LlRBQkxFUk9XLENhdGVnb3J5LlRBQkxFQ09MVU1OXSkKCQkJCSxEaXJlY3Rpb24uTFRSCgkJCQksRGlyZWN0aW9uLlJUTAoJCQkJKTsKCQkJcmV0dXJuIF9kaXJlY3Rpb25Qcm9wZXJ0eTsKCQl9CgkJLyoqIEBwcml2YXRlICovCgkJc3RhdGljIHByaXZhdGUgdmFyIF93b3JkU3BhY2luZ1Byb3BlcnR5OlByb3BlcnR5OwoJCXN0YXRpYyBwdWJsaWMgZnVuY3Rpb24gZ2V0IHdvcmRTcGFjaW5nUHJvcGVydHkoKTpQcm9wZXJ0eQoJCXsKCQkJaWYgKCFfd29yZFNwYWNpbmdQcm9wZXJ0eSkKCQkJX3dvcmRTcGFjaW5nUHJvcGVydHkgPSBQcm9wZXJ0eS5OZXdTcGFjaW5nTGltaXRQcm9wZXJ0eSgid29yZFNwYWNpbmciLCIxMDAlLCA1MCUsIDE1MCUiLHRydWUsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5QQVJBR1JBUEhdKSwiLTEwMDAlIiwiMTAwMCUiKQoJCQlyZXR1cm4gX3dvcmRTcGFjaW5nUHJvcGVydHk7CgkJfQoJCS8qKiBAcHJpdmF0ZSAqLwoJCXN0YXRpYyBwcml2YXRlIHZhciBfdGFiU3RvcHNQcm9wZXJ0eTpQcm9wZXJ0eTsKCQlzdGF0aWMgcHVibGljIGZ1bmN0aW9uIGdldCB0YWJTdG9wc1Byb3BlcnR5KCk6UHJvcGVydHkKCQl7CgkJCWlmICghX3RhYlN0b3BzUHJvcGVydHkpCgkJCV90YWJTdG9wc1Byb3BlcnR5ID0gUHJvcGVydHkuTmV3VGFiU3RvcHNQcm9wZXJ0eSgidGFiU3RvcHMiLG51bGwsdHJ1ZSxWZWN0b3IuPFN0cmluZz4oW0NhdGVnb3J5LlBBUkFHUkFQSF0pKTsKCQkJcmV0dXJuIF90YWJTdG9wc1Byb3BlcnR5OwoJCX0KCQkvKiogQHByaXZhdGUgKi8KCQlzdGF0aWMgcHJpdmF0ZSB2YXIgX2xlYWRpbmdNb2RlbFByb3BlcnR5OlByb3BlcnR5OwoJCXN0YXRpYyBwdWJsaWMgZnVuY3Rpb24gZ2V0IGxlYWRpbmdNb2RlbFByb3BlcnR5KCk6UHJvcGVydHkKCQl7CgkJCWlmICghX2xlYWRpbmdNb2RlbFByb3BlcnR5KQoJCQkJX2xlYWRpbmdNb2RlbFByb3BlcnR5ID0gUHJvcGVydHkuTmV3RW51bVN0cmluZ1Byb3BlcnR5KAoJCQkJImxlYWRpbmdNb2RlbCIsTGVhZGluZ01vZGVsLkFVVE8sdHJ1ZSxWZWN0b3IuPFN0cmluZz4oW0NhdGVnb3J5LlBBUkFHUkFQSF0pCgkJCQksTGVhZGluZ01vZGVsLlJPTUFOX1VQCgkJCQksTGVhZGluZ01vZGVsLklERU9HUkFQSElDX1RPUF9VUAoJCQkJLExlYWRpbmdNb2RlbC5JREVPR1JBUEhJQ19DRU5URVJfVVAKCQkJCSxMZWFkaW5nTW9kZWwuSURFT0dSQVBISUNfVE9QX0RPV04KCQkJCSxMZWFkaW5nTW9kZWwuSURFT0dSQVBISUNfQ0VOVEVSX0RPV04KCQkJCSxMZWFkaW5nTW9kZWwuQVBQUk9YSU1BVEVfVEVYVF9GSUVMRAoJCQkJLExlYWRpbmdNb2RlbC5BU0NFTlRfREVTQ0VOVF9VUAoJCQkJLExlYWRpbmdNb2RlbC5CT1gKCQkJCSxMZWFkaW5nTW9kZWwuQVVUTwoJCQkJKTsKCQkJcmV0dXJuIF9sZWFkaW5nTW9kZWxQcm9wZXJ0eTsKCQl9CgkJLyoqIEBwcml2YXRlICovCgkJc3RhdGljIHByaXZhdGUgdmFyIF9jb2x1bW5HYXBQcm9wZXJ0eTpQcm9wZXJ0eTsKCQlzdGF0aWMgcHVibGljIGZ1bmN0aW9uIGdldCBjb2x1bW5HYXBQcm9wZXJ0eSgpOlByb3BlcnR5CgkJewoJCQlpZiAoIV9jb2x1bW5HYXBQcm9wZXJ0eSkKCQkJX2NvbHVtbkdhcFByb3BlcnR5ID0gUHJvcGVydHkuTmV3TnVtYmVyUHJvcGVydHkoImNvbHVtbkdhcCIsMjAsZmFsc2UsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5DT05UQUlORVJdKSwwLDEwMDApOwoJCQlyZXR1cm4gX2NvbHVtbkdhcFByb3BlcnR5OwoJCX0KCQkvKiogQHByaXZhdGUgKi8KCQlzdGF0aWMgcHJpdmF0ZSB2YXIgX3BhZGRpbmdMZWZ0UHJvcGVydHk6UHJvcGVydHk7CgkJc3RhdGljIHB1YmxpYyBmdW5jdGlvbiBnZXQgcGFkZGluZ0xlZnRQcm9wZXJ0eSgpOlByb3BlcnR5CgkJewoJCQlpZiAoIV9wYWRkaW5nTGVmdFByb3BlcnR5KQoJCQlfcGFkZGluZ0xlZnRQcm9wZXJ0eSA9IFByb3BlcnR5Lk5ld051bWJlck9yRW51bVByb3BlcnR5KAoJCQkJInBhZGRpbmdMZWZ0IixGb3JtYXRWYWx1ZS5BVVRPLGZhbHNlLFZlY3Rvci48U3RyaW5nPihbQ2F0ZWdvcnkuQ09OVEFJTkVSLENhdGVnb3J5LlBBUkFHUkFQSF0pLC04MDAwLDgwMDAKCQkJCSxGb3JtYXRWYWx1ZS5BVVRPCgkJCSk7CgkJCQlyZXR1cm4gX3BhZGRpbmdMZWZ0UHJvcGVydHk7CgkJfQoJCS8qKiBAcHJpdmF0ZSAqLwoJCXN0YXRpYyBwcml2YXRlIHZhciBfcGFkZGluZ1RvcFByb3BlcnR5OlByb3BlcnR5OwoJCXN0YXRpYyBwdWJsaWMgZnVuY3Rpb24gZ2V0IHBhZGRpbmdUb3BQcm9wZXJ0eSgpOlByb3BlcnR5CgkJewoJCQlpZiAoIV9wYWRkaW5nVG9wUHJvcGVydHkpCgkJCV9wYWRkaW5nVG9wUHJvcGVydHkgPSBQcm9wZXJ0eS5OZXdOdW1iZXJPckVudW1Qcm9wZXJ0eSgKCQkJCSJwYWRkaW5nVG9wIixGb3JtYXRWYWx1ZS5BVVRPLGZhbHNlLFZlY3Rvci48U3RyaW5nPihbQ2F0ZWdvcnkuQ09OVEFJTkVSLENhdGVnb3J5LlBBUkFHUkFQSF0pLC04MDAwLDgwMDAKCQkJCSxGb3JtYXRWYWx1ZS5BVVRPCgkJCSk7CgkJCQlyZXR1cm4gX3BhZGRpbmdUb3BQcm9wZXJ0eTsKCQl9CgkJLyoqIEBwcml2YXRlICovCgkJc3RhdGljIHByaXZhdGUgdmFyIF9wYWRkaW5nUmlnaHRQcm9wZXJ0eTpQcm9wZXJ0eTsKCQlzdGF0aWMgcHVibGljIGZ1bmN0aW9uIGdldCBwYWRkaW5nUmlnaHRQcm9wZXJ0eSgpOlByb3BlcnR5CgkJewoJCQlpZiAoIV9wYWRkaW5nUmlnaHRQcm9wZXJ0eSkKCQkJX3BhZGRpbmdSaWdodFByb3BlcnR5ID0gUHJvcGVydHkuTmV3TnVtYmVyT3JFbnVtUHJvcGVydHkoCgkJCQkicGFkZGluZ1JpZ2h0IixGb3JtYXRWYWx1ZS5BVVRPLGZhbHNlLFZlY3Rvci48U3RyaW5nPihbQ2F0ZWdvcnkuQ09OVEFJTkVSLENhdGVnb3J5LlBBUkFHUkFQSF0pLC04MDAwLDgwMDAKCQkJCSxGb3JtYXRWYWx1ZS5BVVRPCgkJCSk7CgkJCQlyZXR1cm4gX3BhZGRpbmdSaWdodFByb3BlcnR5OwoJCX0KCQkvKiogQHByaXZhdGUgKi8KCQlzdGF0aWMgcHJpdmF0ZSB2YXIgX3BhZGRpbmdCb3R0b21Qcm9wZXJ0eTpQcm9wZXJ0eTsKCQlzdGF0aWMgcHVibGljIGZ1bmN0aW9uIGdldCBwYWRkaW5nQm90dG9tUHJvcGVydHkoKTpQcm9wZXJ0eQoJCXsKCQkJaWYgKCFfcGFkZGluZ0JvdHRvbVByb3BlcnR5KQoJCQlfcGFkZGluZ0JvdHRvbVByb3BlcnR5ID0gUHJvcGVydHkuTmV3TnVtYmVyT3JFbnVtUHJvcGVydHkoCgkJCQkicGFkZGluZ0JvdHRvbSIsRm9ybWF0VmFsdWUuQVVUTyxmYWxzZSxWZWN0b3IuPFN0cmluZz4oW0NhdGVnb3J5LkNPTlRBSU5FUixDYXRlZ29yeS5QQVJBR1JBUEhdKSwtODAwMCw4MDAwCgkJCQksRm9ybWF0VmFsdWUuQVVUTwoJCQkpOwoJCQkJcmV0dXJuIF9wYWRkaW5nQm90dG9tUHJvcGVydHk7CgkJfQoJCS8qKiBAcHJpdmF0ZSAqLwoJCXN0YXRpYyBwcml2YXRlIHZhciBfY29sdW1uQ291bnRQcm9wZXJ0eTpQcm9wZXJ0eTsKCQlzdGF0aWMgcHVibGljIGZ1bmN0aW9uIGdldCBjb2x1bW5Db3VudFByb3BlcnR5KCk6UHJvcGVydHkKCQl7CgkJCWlmICghX2NvbHVtbkNvdW50UHJvcGVydHkpCgkJCV9jb2x1bW5Db3VudFByb3BlcnR5ID0gUHJvcGVydHkuTmV3SW50T3JFbnVtUHJvcGVydHkoCgkJCQkiY29sdW1uQ291bnQiLEZvcm1hdFZhbHVlLkFVVE8sZmFsc2UsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5DT05UQUlORVJdKSwxLDUwCgkJCQksRm9ybWF0VmFsdWUuQVVUTwoJCQkpOwoJCQlyZXR1cm4gX2NvbHVtbkNvdW50UHJvcGVydHk7CgkJfQoJCS8qKiBAcHJpdmF0ZSAqLwoJCXN0YXRpYyBwcml2YXRlIHZhciBfY29sdW1uV2lkdGhQcm9wZXJ0eTpQcm9wZXJ0eTsKCQlzdGF0aWMgcHVibGljIGZ1bmN0aW9uIGdldCBjb2x1bW5XaWR0aFByb3BlcnR5KCk6UHJvcGVydHkKCQl7CgkJCWlmICghX2NvbHVtbldpZHRoUHJvcGVydHkpCgkJCV9jb2x1bW5XaWR0aFByb3BlcnR5ID0gUHJvcGVydHkuTmV3TnVtYmVyT3JFbnVtUHJvcGVydHkoCgkJCQkiY29sdW1uV2lkdGgiLEZvcm1hdFZhbHVlLkFVVE8sZmFsc2UsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5DT05UQUlORVJdKSwwLDgwMDAKCQkJCSxGb3JtYXRWYWx1ZS5BVVRPCgkJCSk7CgkJCQlyZXR1cm4gX2NvbHVtbldpZHRoUHJvcGVydHk7CgkJfQoJCS8qKiBAcHJpdmF0ZSAqLwoJCXN0YXRpYyBwcml2YXRlIHZhciBfZmlyc3RCYXNlbGluZU9mZnNldFByb3BlcnR5OlByb3BlcnR5OwoJCXN0YXRpYyBwdWJsaWMgZnVuY3Rpb24gZ2V0IGZpcnN0QmFzZWxpbmVPZmZzZXRQcm9wZXJ0eSgpOlByb3BlcnR5CgkJewoJCQlpZiAoIV9maXJzdEJhc2VsaW5lT2Zmc2V0UHJvcGVydHkpCgkJCV9maXJzdEJhc2VsaW5lT2Zmc2V0UHJvcGVydHkgPSBQcm9wZXJ0eS5OZXdOdW1iZXJPckVudW1Qcm9wZXJ0eSgKCQkJCSJmaXJzdEJhc2VsaW5lT2Zmc2V0IixCYXNlbGluZU9mZnNldC5BVVRPLHRydWUsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5DT05UQUlORVJdKSwwLDEwMDAKCQkJCSxCYXNlbGluZU9mZnNldC5BVVRPCgkJCQksQmFzZWxpbmVPZmZzZXQuQVNDRU5UCgkJCQksQmFzZWxpbmVPZmZzZXQuTElORV9IRUlHSFQKCQkJKTsKCQkJCXJldHVybiBfZmlyc3RCYXNlbGluZU9mZnNldFByb3BlcnR5OwoJCX0KCQkvKiogQHByaXZhdGUgKi8KCQlzdGF0aWMgcHJpdmF0ZSB2YXIgX3ZlcnRpY2FsQWxpZ25Qcm9wZXJ0eTpQcm9wZXJ0eTsKCQlzdGF0aWMgcHVibGljIGZ1bmN0aW9uIGdldCB2ZXJ0aWNhbEFsaWduUHJvcGVydHkoKTpQcm9wZXJ0eQoJCXsKCQkJaWYgKCFfdmVydGljYWxBbGlnblByb3BlcnR5KQoJCQkJX3ZlcnRpY2FsQWxpZ25Qcm9wZXJ0eSA9IFByb3BlcnR5Lk5ld0VudW1TdHJpbmdQcm9wZXJ0eSgKCQkJCSJ2ZXJ0aWNhbEFsaWduIixWZXJ0aWNhbEFsaWduLlRPUCxmYWxzZSxWZWN0b3IuPFN0cmluZz4oW0NhdGVnb3J5LkNPTlRBSU5FUixDYXRlZ29yeS5UQUJMRUNFTEwsQ2F0ZWdvcnkuVEFCTEUsQ2F0ZWdvcnkuVEFCTEVST1csQ2F0ZWdvcnkuVEFCTEVDT0xVTU5dKQoJCQkJLFZlcnRpY2FsQWxpZ24uVE9QCgkJCQksVmVydGljYWxBbGlnbi5NSURETEUKCQkJCSxWZXJ0aWNhbEFsaWduLkJPVFRPTQoJCQkJLFZlcnRpY2FsQWxpZ24uSlVTVElGWQoJCQkJKTsKCQkJcmV0dXJuIF92ZXJ0aWNhbEFsaWduUHJvcGVydHk7CgkJfQoJCS8qKiBAcHJpdmF0ZSAqLwoJCXN0YXRpYyBwcml2YXRlIHZhciBfYmxvY2tQcm9ncmVzc2lvblByb3BlcnR5OlByb3BlcnR5OwoJCXN0YXRpYyBwdWJsaWMgZnVuY3Rpb24gZ2V0IGJsb2NrUHJvZ3Jlc3Npb25Qcm9wZXJ0eSgpOlByb3BlcnR5CgkJewoJCQlpZiAoIV9ibG9ja1Byb2dyZXNzaW9uUHJvcGVydHkpCgkJCQlfYmxvY2tQcm9ncmVzc2lvblByb3BlcnR5ID0gUHJvcGVydHkuTmV3RW51bVN0cmluZ1Byb3BlcnR5KAoJCQkJImJsb2NrUHJvZ3Jlc3Npb24iLEJsb2NrUHJvZ3Jlc3Npb24uVEIsdHJ1ZSxWZWN0b3IuPFN0cmluZz4oW0NhdGVnb3J5LkNPTlRBSU5FUl0pCgkJCQksQmxvY2tQcm9ncmVzc2lvbi5STAoJCQkJLEJsb2NrUHJvZ3Jlc3Npb24uVEIKCQkJCSk7CgkJCXJldHVybiBfYmxvY2tQcm9ncmVzc2lvblByb3BlcnR5OwoJCX0KCQkvKiogQHByaXZhdGUgKi8KCQlzdGF0aWMgcHJpdmF0ZSB2YXIgX2xpbmVCcmVha1Byb3BlcnR5OlByb3BlcnR5OwoJCXN0YXRpYyBwdWJsaWMgZnVuY3Rpb24gZ2V0IGxpbmVCcmVha1Byb3BlcnR5KCk6UHJvcGVydHkKCQl7CgkJCWlmICghX2xpbmVCcmVha1Byb3BlcnR5KQoJCQkJX2xpbmVCcmVha1Byb3BlcnR5ID0gUHJvcGVydHkuTmV3RW51bVN0cmluZ1Byb3BlcnR5KAoJCQkJImxpbmVCcmVhayIsTGluZUJyZWFrLlRPX0ZJVCxmYWxzZSxWZWN0b3IuPFN0cmluZz4oW0NhdGVnb3J5LkNPTlRBSU5FUixDYXRlZ29yeS5UQUJMRUNFTExdKQoJCQkJLExpbmVCcmVhay5FWFBMSUNJVAoJCQkJLExpbmVCcmVhay5UT19GSVQKCQkJCSk7CgkJCXJldHVybiBfbGluZUJyZWFrUHJvcGVydHk7CgkJfQoJCS8qKiBAcHJpdmF0ZSAqLwoJCXN0YXRpYyBwcml2YXRlIHZhciBfbGlzdFN0eWxlVHlwZVByb3BlcnR5OlByb3BlcnR5OwoJCXN0YXRpYyBwdWJsaWMgZnVuY3Rpb24gZ2V0IGxpc3RTdHlsZVR5cGVQcm9wZXJ0eSgpOlByb3BlcnR5CgkJewoJCQlpZiAoIV9saXN0U3R5bGVUeXBlUHJvcGVydHkpCgkJCQlfbGlzdFN0eWxlVHlwZVByb3BlcnR5ID0gUHJvcGVydHkuTmV3RW51bVN0cmluZ1Byb3BlcnR5KAoJCQkJImxpc3RTdHlsZVR5cGUiLExpc3RTdHlsZVR5cGUuRElTQyx0cnVlLFZlY3Rvci48U3RyaW5nPihbQ2F0ZWdvcnkuTElTVF0pCgkJCQksTGlzdFN0eWxlVHlwZS5VUFBFUl9BTFBIQQoJCQkJLExpc3RTdHlsZVR5cGUuTE9XRVJfQUxQSEEKCQkJCSxMaXN0U3R5bGVUeXBlLlVQUEVSX1JPTUFOCgkJCQksTGlzdFN0eWxlVHlwZS5MT1dFUl9ST01BTgoJCQkJLExpc3RTdHlsZVR5cGUuTk9ORQoJCQkJLExpc3RTdHlsZVR5cGUuRElTQwoJCQkJLExpc3RTdHlsZVR5cGUuQ0lSQ0xFCgkJCQksTGlzdFN0eWxlVHlwZS5TUVVBUkUKCQkJCSxMaXN0U3R5bGVUeXBlLkJPWAoJCQkJLExpc3RTdHlsZVR5cGUuQ0hFQ0sKCQkJCSxMaXN0U3R5bGVUeXBlLkRJQU1PTkQKCQkJCSxMaXN0U3R5bGVUeXBlLkhZUEhFTgoJCQkJLExpc3RTdHlsZVR5cGUuQVJBQklDX0lORElDCgkJCQksTGlzdFN0eWxlVHlwZS5CRU5HQUxJCgkJCQksTGlzdFN0eWxlVHlwZS5ERUNJTUFMCgkJCQksTGlzdFN0eWxlVHlwZS5ERUNJTUFMX0xFQURJTkdfWkVSTwoJCQkJLExpc3RTdHlsZVR5cGUuREVWQU5BR0FSSQoJCQkJLExpc3RTdHlsZVR5cGUuR1VKQVJBVEkKCQkJCSxMaXN0U3R5bGVUeXBlLkdVUk1VS0hJCgkJCQksTGlzdFN0eWxlVHlwZS5LQU5OQURBCgkJCQksTGlzdFN0eWxlVHlwZS5QRVJTSUFOCgkJCQksTGlzdFN0eWxlVHlwZS5USEFJCgkJCQksTGlzdFN0eWxlVHlwZS5VUkRVCgkJCQksTGlzdFN0eWxlVHlwZS5DSktfRUFSVEhMWV9CUkFOQ0gKCQkJCSxMaXN0U3R5bGVUeXBlLkNKS19IRUFWRU5MWV9TVEVNCgkJCQksTGlzdFN0eWxlVHlwZS5IQU5HVUwKCQkJCSxMaXN0U3R5bGVUeXBlLkhBTkdVTF9DT05TVEFOVAoJCQkJLExpc3RTdHlsZVR5cGUuSElSQUdBTkEKCQkJCSxMaXN0U3R5bGVUeXBlLkhJUkFHQU5BX0lST0hBCgkJCQksTGlzdFN0eWxlVHlwZS5LQVRBS0FOQQoJCQkJLExpc3RTdHlsZVR5cGUuS0FUQUtBTkFfSVJPSEEKCQkJCSxMaXN0U3R5bGVUeXBlLkxPV0VSX0FMUEhBCgkJCQksTGlzdFN0eWxlVHlwZS5MT1dFUl9HUkVFSwoJCQkJLExpc3RTdHlsZVR5cGUuTE9XRVJfTEFUSU4KCQkJCSxMaXN0U3R5bGVUeXBlLlVQUEVSX0FMUEhBCgkJCQksTGlzdFN0eWxlVHlwZS5VUFBFUl9HUkVFSwoJCQkJLExpc3RTdHlsZVR5cGUuVVBQRVJfTEFUSU4KCQkJCSk7CgkJCXJldHVybiBfbGlzdFN0eWxlVHlwZVByb3BlcnR5OwoJCX0KCQkvKiogQHByaXZhdGUgKi8KCQlzdGF0aWMgcHJpdmF0ZSB2YXIgX2xpc3RTdHlsZVBvc2l0aW9uUHJvcGVydHk6UHJvcGVydHk7CgkJc3RhdGljIHB1YmxpYyBmdW5jdGlvbiBnZXQgbGlzdFN0eWxlUG9zaXRpb25Qcm9wZXJ0eSgpOlByb3BlcnR5CgkJewoJCQlpZiAoIV9saXN0U3R5bGVQb3NpdGlvblByb3BlcnR5KQoJCQkJX2xpc3RTdHlsZVBvc2l0aW9uUHJvcGVydHkgPSBQcm9wZXJ0eS5OZXdFbnVtU3RyaW5nUHJvcGVydHkoCgkJCQkibGlzdFN0eWxlUG9zaXRpb24iLExpc3RTdHlsZVBvc2l0aW9uLk9VVFNJREUsdHJ1ZSxWZWN0b3IuPFN0cmluZz4oW0NhdGVnb3J5LkxJU1RdKQoJCQkJLExpc3RTdHlsZVBvc2l0aW9uLklOU0lERQoJCQkJLExpc3RTdHlsZVBvc2l0aW9uLk9VVFNJREUKCQkJCSk7CgkJCXJldHVybiBfbGlzdFN0eWxlUG9zaXRpb25Qcm9wZXJ0eTsKCQl9CgkJLyoqIEBwcml2YXRlICovCgkJc3RhdGljIHByaXZhdGUgdmFyIF9saXN0QXV0b1BhZGRpbmdQcm9wZXJ0eTpQcm9wZXJ0eTsKCQlzdGF0aWMgcHVibGljIGZ1bmN0aW9uIGdldCBsaXN0QXV0b1BhZGRpbmdQcm9wZXJ0eSgpOlByb3BlcnR5CgkJewoJCQlpZiAoIV9saXN0QXV0b1BhZGRpbmdQcm9wZXJ0eSkKCQkJX2xpc3RBdXRvUGFkZGluZ1Byb3BlcnR5ID0gUHJvcGVydHkuTmV3TnVtYmVyUHJvcGVydHkoImxpc3RBdXRvUGFkZGluZyIsNDAsdHJ1ZSxWZWN0b3IuPFN0cmluZz4oW0NhdGVnb3J5LkNPTlRBSU5FUl0pLC0xMDAwLDEwMDApOwoJCQlyZXR1cm4gX2xpc3RBdXRvUGFkZGluZ1Byb3BlcnR5OwoJCX0KCQkvKiogQHByaXZhdGUgKi8KCQlzdGF0aWMgcHJpdmF0ZSB2YXIgX2NsZWFyRmxvYXRzUHJvcGVydHk6UHJvcGVydHk7CgkJc3RhdGljIHB1YmxpYyBmdW5jdGlvbiBnZXQgY2xlYXJGbG9hdHNQcm9wZXJ0eSgpOlByb3BlcnR5CgkJewoJCQlpZiAoIV9jbGVhckZsb2F0c1Byb3BlcnR5KQoJCQkJX2NsZWFyRmxvYXRzUHJvcGVydHkgPSBQcm9wZXJ0eS5OZXdFbnVtU3RyaW5nUHJvcGVydHkoCgkJCQkiY2xlYXJGbG9hdHMiLENsZWFyRmxvYXRzLk5PTkUsZmFsc2UsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5QQVJBR1JBUEhdKQoJCQkJLENsZWFyRmxvYXRzLlNUQVJUCgkJCQksQ2xlYXJGbG9hdHMuRU5ECgkJCQksQ2xlYXJGbG9hdHMuTEVGVAoJCQkJLENsZWFyRmxvYXRzLlJJR0hUCgkJCQksQ2xlYXJGbG9hdHMuQk9USAoJCQkJLENsZWFyRmxvYXRzLk5PTkUKCQkJCSk7CgkJCXJldHVybiBfY2xlYXJGbG9hdHNQcm9wZXJ0eTsKCQl9CgkJLyoqIEBwcml2YXRlICovCgkJc3RhdGljIHByaXZhdGUgdmFyIF9zdHlsZU5hbWVQcm9wZXJ0eTpQcm9wZXJ0eTsKCQlzdGF0aWMgcHVibGljIGZ1bmN0aW9uIGdldCBzdHlsZU5hbWVQcm9wZXJ0eSgpOlByb3BlcnR5CgkJewoJCQlpZiAoIV9zdHlsZU5hbWVQcm9wZXJ0eSkKCQkJX3N0eWxlTmFtZVByb3BlcnR5ID0gUHJvcGVydHkuTmV3U3RyaW5nUHJvcGVydHkoInN0eWxlTmFtZSIsbnVsbCxmYWxzZSxWZWN0b3IuPFN0cmluZz4oW0NhdGVnb3J5LlNUWUxFXSkpOwoJCQlyZXR1cm4gX3N0eWxlTmFtZVByb3BlcnR5OwoJCX0KCQkvKiogQHByaXZhdGUgKi8KCQlzdGF0aWMgcHJpdmF0ZSB2YXIgX2xpbmtOb3JtYWxGb3JtYXRQcm9wZXJ0eTpQcm9wZXJ0eTsKCQlzdGF0aWMgcHVibGljIGZ1bmN0aW9uIGdldCBsaW5rTm9ybWFsRm9ybWF0UHJvcGVydHkoKTpQcm9wZXJ0eQoJCXsKCQkJaWYgKCFfbGlua05vcm1hbEZvcm1hdFByb3BlcnR5KQoJCQlfbGlua05vcm1hbEZvcm1hdFByb3BlcnR5ID0gUHJvcGVydHkuTmV3VGV4dExheW91dEZvcm1hdFByb3BlcnR5KCJsaW5rTm9ybWFsRm9ybWF0IixudWxsLHRydWUsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5TVFlMRV0pKTsKCQkJcmV0dXJuIF9saW5rTm9ybWFsRm9ybWF0UHJvcGVydHk7CgkJfQoJCS8qKiBAcHJpdmF0ZSAqLwoJCXN0YXRpYyBwcml2YXRlIHZhciBfbGlua0FjdGl2ZUZvcm1hdFByb3BlcnR5OlByb3BlcnR5OwoJCXN0YXRpYyBwdWJsaWMgZnVuY3Rpb24gZ2V0IGxpbmtBY3RpdmVGb3JtYXRQcm9wZXJ0eSgpOlByb3BlcnR5CgkJewoJCQlpZiAoIV9saW5rQWN0aXZlRm9ybWF0UHJvcGVydHkpCgkJCV9saW5rQWN0aXZlRm9ybWF0UHJvcGVydHkgPSBQcm9wZXJ0eS5OZXdUZXh0TGF5b3V0Rm9ybWF0UHJvcGVydHkoImxpbmtBY3RpdmVGb3JtYXQiLG51bGwsdHJ1ZSxWZWN0b3IuPFN0cmluZz4oW0NhdGVnb3J5LlNUWUxFXSkpOwoJCQlyZXR1cm4gX2xpbmtBY3RpdmVGb3JtYXRQcm9wZXJ0eTsKCQl9CgkJLyoqIEBwcml2YXRlICovCgkJc3RhdGljIHByaXZhdGUgdmFyIF9saW5rSG92ZXJGb3JtYXRQcm9wZXJ0eTpQcm9wZXJ0eTsKCQlzdGF0aWMgcHVibGljIGZ1bmN0aW9uIGdldCBsaW5rSG92ZXJGb3JtYXRQcm9wZXJ0eSgpOlByb3BlcnR5CgkJewoJCQlpZiAoIV9saW5rSG92ZXJGb3JtYXRQcm9wZXJ0eSkKCQkJX2xpbmtIb3ZlckZvcm1hdFByb3BlcnR5ID0gUHJvcGVydHkuTmV3VGV4dExheW91dEZvcm1hdFByb3BlcnR5KCJsaW5rSG92ZXJGb3JtYXQiLG51bGwsdHJ1ZSxWZWN0b3IuPFN0cmluZz4oW0NhdGVnb3J5LlNUWUxFXSkpOwoJCQlyZXR1cm4gX2xpbmtIb3ZlckZvcm1hdFByb3BlcnR5OwoJCX0KCQkvKiogQHByaXZhdGUgKi8KCQlzdGF0aWMgcHJpdmF0ZSB2YXIgX2xpc3RNYXJrZXJGb3JtYXRQcm9wZXJ0eTpQcm9wZXJ0eTsKCQlzdGF0aWMgcHVibGljIGZ1bmN0aW9uIGdldCBsaXN0TWFya2VyRm9ybWF0UHJvcGVydHkoKTpQcm9wZXJ0eQoJCXsKCQkJaWYgKCFfbGlzdE1hcmtlckZvcm1hdFByb3BlcnR5KQoJCQlfbGlzdE1hcmtlckZvcm1hdFByb3BlcnR5ID0gUHJvcGVydHkuTmV3TGlzdE1hcmtlckZvcm1hdFByb3BlcnR5KCJsaXN0TWFya2VyRm9ybWF0IixudWxsLHRydWUsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5TVFlMRV0pKTsKCQkJcmV0dXJuIF9saXN0TWFya2VyRm9ybWF0UHJvcGVydHk7CgkJfQoJCS8qKiBAcHJpdmF0ZSAqLwoJCXN0YXRpYyBwcml2YXRlIHZhciBfYm9yZGVyTGVmdFdpZHRoUHJvcGVydHk6UHJvcGVydHk7CgkJc3RhdGljIHB1YmxpYyBmdW5jdGlvbiBnZXQgYm9yZGVyTGVmdFdpZHRoUHJvcGVydHkoKTpQcm9wZXJ0eQoJCXsKCQkJaWYgKCFfYm9yZGVyTGVmdFdpZHRoUHJvcGVydHkpCgkJCV9ib3JkZXJMZWZ0V2lkdGhQcm9wZXJ0eSA9IFByb3BlcnR5Lk5ld051bWJlclByb3BlcnR5KCJib3JkZXJMZWZ0V2lkdGgiLDAsZmFsc2UsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5DT05UQUlORVIsQ2F0ZWdvcnkuUEFSQUdSQVBIXSksMCwxMjgpOwoJCQlyZXR1cm4gX2JvcmRlckxlZnRXaWR0aFByb3BlcnR5OwoJCX0KCQkvKiogQHByaXZhdGUgKi8KCQlzdGF0aWMgcHJpdmF0ZSB2YXIgX2JvcmRlclJpZ2h0V2lkdGhQcm9wZXJ0eTpQcm9wZXJ0eTsKCQlzdGF0aWMgcHVibGljIGZ1bmN0aW9uIGdldCBib3JkZXJSaWdodFdpZHRoUHJvcGVydHkoKTpQcm9wZXJ0eQoJCXsKCQkJaWYgKCFfYm9yZGVyUmlnaHRXaWR0aFByb3BlcnR5KQoJCQlfYm9yZGVyUmlnaHRXaWR0aFByb3BlcnR5ID0gUHJvcGVydHkuTmV3TnVtYmVyUHJvcGVydHkoImJvcmRlclJpZ2h0V2lkdGgiLDAsZmFsc2UsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5DT05UQUlORVIsQ2F0ZWdvcnkuUEFSQUdSQVBIXSksMCwxMjgpOwoJCQlyZXR1cm4gX2JvcmRlclJpZ2h0V2lkdGhQcm9wZXJ0eTsKCQl9CgkJLyoqIEBwcml2YXRlICovCgkJc3RhdGljIHByaXZhdGUgdmFyIF9ib3JkZXJUb3BXaWR0aFByb3BlcnR5OlByb3BlcnR5OwoJCXN0YXRpYyBwdWJsaWMgZnVuY3Rpb24gZ2V0IGJvcmRlclRvcFdpZHRoUHJvcGVydHkoKTpQcm9wZXJ0eQoJCXsKCQkJaWYgKCFfYm9yZGVyVG9wV2lkdGhQcm9wZXJ0eSkKCQkJX2JvcmRlclRvcFdpZHRoUHJvcGVydHkgPSBQcm9wZXJ0eS5OZXdOdW1iZXJQcm9wZXJ0eSgiYm9yZGVyVG9wV2lkdGgiLDAsZmFsc2UsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5DT05UQUlORVIsQ2F0ZWdvcnkuUEFSQUdSQVBIXSksMCwxMjgpOwoJCQlyZXR1cm4gX2JvcmRlclRvcFdpZHRoUHJvcGVydHk7CgkJfQoJCS8qKiBAcHJpdmF0ZSAqLwoJCXN0YXRpYyBwcml2YXRlIHZhciBfYm9yZGVyQm90dG9tV2lkdGhQcm9wZXJ0eTpQcm9wZXJ0eTsKCQlzdGF0aWMgcHVibGljIGZ1bmN0aW9uIGdldCBib3JkZXJCb3R0b21XaWR0aFByb3BlcnR5KCk6UHJvcGVydHkKCQl7CgkJCWlmICghX2JvcmRlckJvdHRvbVdpZHRoUHJvcGVydHkpCgkJCV9ib3JkZXJCb3R0b21XaWR0aFByb3BlcnR5ID0gUHJvcGVydHkuTmV3TnVtYmVyUHJvcGVydHkoImJvcmRlckJvdHRvbVdpZHRoIiwwLGZhbHNlLFZlY3Rvci48U3RyaW5nPihbQ2F0ZWdvcnkuQ09OVEFJTkVSLENhdGVnb3J5LlBBUkFHUkFQSF0pLDAsMTI4KTsKCQkJcmV0dXJuIF9ib3JkZXJCb3R0b21XaWR0aFByb3BlcnR5OwoJCX0KCQkvKiogQHByaXZhdGUgKi8KCQlzdGF0aWMgcHJpdmF0ZSB2YXIgX2JvcmRlckxlZnRDb2xvclByb3BlcnR5OlByb3BlcnR5OwoJCXN0YXRpYyBwdWJsaWMgZnVuY3Rpb24gZ2V0IGJvcmRlckxlZnRDb2xvclByb3BlcnR5KCk6UHJvcGVydHkKCQl7CgkJCWlmICghX2JvcmRlckxlZnRDb2xvclByb3BlcnR5KQoJCQlfYm9yZGVyTGVmdENvbG9yUHJvcGVydHkgPSBQcm9wZXJ0eS5OZXdVaW50T3JFbnVtUHJvcGVydHkoCgkJCQkiYm9yZGVyTGVmdENvbG9yIixCb3JkZXJDb2xvci5UUkFOU1BBUkVOVCxmYWxzZSxWZWN0b3IuPFN0cmluZz4oW0NhdGVnb3J5LkNPTlRBSU5FUixDYXRlZ29yeS5QQVJBR1JBUEhdKQoJCQkJLEJvcmRlckNvbG9yLlRSQU5TUEFSRU5UCgkJCSk7CgkJCXJldHVybiBfYm9yZGVyTGVmdENvbG9yUHJvcGVydHk7CgkJfQoJCS8qKiBAcHJpdmF0ZSAqLwoJCXN0YXRpYyBwcml2YXRlIHZhciBfYm9yZGVyUmlnaHRDb2xvclByb3BlcnR5OlByb3BlcnR5OwoJCXN0YXRpYyBwdWJsaWMgZnVuY3Rpb24gZ2V0IGJvcmRlclJpZ2h0Q29sb3JQcm9wZXJ0eSgpOlByb3BlcnR5CgkJewoJCQlpZiAoIV9ib3JkZXJSaWdodENvbG9yUHJvcGVydHkpCgkJCV9ib3JkZXJSaWdodENvbG9yUHJvcGVydHkgPSBQcm9wZXJ0eS5OZXdVaW50T3JFbnVtUHJvcGVydHkoCgkJCQkiYm9yZGVyUmlnaHRDb2xvciIsQm9yZGVyQ29sb3IuVFJBTlNQQVJFTlQsZmFsc2UsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5DT05UQUlORVIsQ2F0ZWdvcnkuUEFSQUdSQVBIXSkKCQkJCSxCb3JkZXJDb2xvci5UUkFOU1BBUkVOVAoJCQkpOwoJCQlyZXR1cm4gX2JvcmRlclJpZ2h0Q29sb3JQcm9wZXJ0eTsKCQl9CgkJLyoqIEBwcml2YXRlICovCgkJc3RhdGljIHByaXZhdGUgdmFyIF9ib3JkZXJUb3BDb2xvclByb3BlcnR5OlByb3BlcnR5OwoJCXN0YXRpYyBwdWJsaWMgZnVuY3Rpb24gZ2V0IGJvcmRlclRvcENvbG9yUHJvcGVydHkoKTpQcm9wZXJ0eQoJCXsKCQkJaWYgKCFfYm9yZGVyVG9wQ29sb3JQcm9wZXJ0eSkKCQkJX2JvcmRlclRvcENvbG9yUHJvcGVydHkgPSBQcm9wZXJ0eS5OZXdVaW50T3JFbnVtUHJvcGVydHkoCgkJCQkiYm9yZGVyVG9wQ29sb3IiLEJvcmRlckNvbG9yLlRSQU5TUEFSRU5ULGZhbHNlLFZlY3Rvci48U3RyaW5nPihbQ2F0ZWdvcnkuQ09OVEFJTkVSLENhdGVnb3J5LlBBUkFHUkFQSF0pCgkJCQksQm9yZGVyQ29sb3IuVFJBTlNQQVJFTlQKCQkJKTsKCQkJcmV0dXJuIF9ib3JkZXJUb3BDb2xvclByb3BlcnR5OwoJCX0KCQkvKiogQHByaXZhdGUgKi8KCQlzdGF0aWMgcHJpdmF0ZSB2YXIgX2JvcmRlckJvdHRvbUNvbG9yUHJvcGVydHk6UHJvcGVydHk7CgkJc3RhdGljIHB1YmxpYyBmdW5jdGlvbiBnZXQgYm9yZGVyQm90dG9tQ29sb3JQcm9wZXJ0eSgpOlByb3BlcnR5CgkJewoJCQlpZiAoIV9ib3JkZXJCb3R0b21Db2xvclByb3BlcnR5KQoJCQlfYm9yZGVyQm90dG9tQ29sb3JQcm9wZXJ0eSA9IFByb3BlcnR5Lk5ld1VpbnRPckVudW1Qcm9wZXJ0eSgKCQkJCSJib3JkZXJCb3R0b21Db2xvciIsQm9yZGVyQ29sb3IuVFJBTlNQQVJFTlQsZmFsc2UsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5DT05UQUlORVIsQ2F0ZWdvcnkuUEFSQUdSQVBIXSkKCQkJCSxCb3JkZXJDb2xvci5UUkFOU1BBUkVOVAoJCQkpOwoJCQlyZXR1cm4gX2JvcmRlckJvdHRvbUNvbG9yUHJvcGVydHk7CgkJfQoJCS8qKiBAcHJpdmF0ZSAqLwoJCXN0YXRpYyBwcml2YXRlIHZhciBfbWFyZ2luTGVmdFByb3BlcnR5OlByb3BlcnR5OwoJCXN0YXRpYyBwdWJsaWMgZnVuY3Rpb24gZ2V0IG1hcmdpbkxlZnRQcm9wZXJ0eSgpOlByb3BlcnR5CgkJewoJCQlpZiAoIV9tYXJnaW5MZWZ0UHJvcGVydHkpCgkJCV9tYXJnaW5MZWZ0UHJvcGVydHkgPSBQcm9wZXJ0eS5OZXdOdW1iZXJQcm9wZXJ0eSgibWFyZ2luTGVmdCIsMCxmYWxzZSxWZWN0b3IuPFN0cmluZz4oW0NhdGVnb3J5LkNPTlRBSU5FUixDYXRlZ29yeS5QQVJBR1JBUEhdKSwtODAwMCw4MDAwKTsKCQkJcmV0dXJuIF9tYXJnaW5MZWZ0UHJvcGVydHk7CgkJfQoJCS8qKiBAcHJpdmF0ZSAqLwoJCXN0YXRpYyBwcml2YXRlIHZhciBfbWFyZ2luUmlnaHRQcm9wZXJ0eTpQcm9wZXJ0eTsKCQlzdGF0aWMgcHVibGljIGZ1bmN0aW9uIGdldCBtYXJnaW5SaWdodFByb3BlcnR5KCk6UHJvcGVydHkKCQl7CgkJCWlmICghX21hcmdpblJpZ2h0UHJvcGVydHkpCgkJCV9tYXJnaW5SaWdodFByb3BlcnR5ID0gUHJvcGVydHkuTmV3TnVtYmVyUHJvcGVydHkoIm1hcmdpblJpZ2h0IiwwLGZhbHNlLFZlY3Rvci48U3RyaW5nPihbQ2F0ZWdvcnkuQ09OVEFJTkVSLENhdGVnb3J5LlBBUkFHUkFQSF0pLC04MDAwLDgwMDApOwoJCQlyZXR1cm4gX21hcmdpblJpZ2h0UHJvcGVydHk7CgkJfQoJCS8qKiBAcHJpdmF0ZSAqLwoJCXN0YXRpYyBwcml2YXRlIHZhciBfbWFyZ2luVG9wUHJvcGVydHk6UHJvcGVydHk7CgkJc3RhdGljIHB1YmxpYyBmdW5jdGlvbiBnZXQgbWFyZ2luVG9wUHJvcGVydHkoKTpQcm9wZXJ0eQoJCXsKCQkJaWYgKCFfbWFyZ2luVG9wUHJvcGVydHkpCgkJCV9tYXJnaW5Ub3BQcm9wZXJ0eSA9IFByb3BlcnR5Lk5ld051bWJlclByb3BlcnR5KCJtYXJnaW5Ub3AiLDAsZmFsc2UsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5DT05UQUlORVIsQ2F0ZWdvcnkuUEFSQUdSQVBIXSksLTgwMDAsODAwMCk7CgkJCXJldHVybiBfbWFyZ2luVG9wUHJvcGVydHk7CgkJfQoJCS8qKiBAcHJpdmF0ZSAqLwoJCXN0YXRpYyBwcml2YXRlIHZhciBfbWFyZ2luQm90dG9tUHJvcGVydHk6UHJvcGVydHk7CgkJc3RhdGljIHB1YmxpYyBmdW5jdGlvbiBnZXQgbWFyZ2luQm90dG9tUHJvcGVydHkoKTpQcm9wZXJ0eQoJCXsKCQkJaWYgKCFfbWFyZ2luQm90dG9tUHJvcGVydHkpCgkJCV9tYXJnaW5Cb3R0b21Qcm9wZXJ0eSA9IFByb3BlcnR5Lk5ld051bWJlclByb3BlcnR5KCJtYXJnaW5Cb3R0b20iLDAsZmFsc2UsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5DT05UQUlORVIsQ2F0ZWdvcnkuUEFSQUdSQVBIXSksLTgwMDAsODAwMCk7CgkJCXJldHVybiBfbWFyZ2luQm90dG9tUHJvcGVydHk7CgkJfQoJCS8qKiBAcHJpdmF0ZSAqLwoJCXN0YXRpYyBwcml2YXRlIHZhciBfY2VsbFNwYWNpbmdQcm9wZXJ0eTpQcm9wZXJ0eTsKCQlzdGF0aWMgcHVibGljIGZ1bmN0aW9uIGdldCBjZWxsU3BhY2luZ1Byb3BlcnR5KCk6UHJvcGVydHkKCQl7CgkJCWlmICghX2NlbGxTcGFjaW5nUHJvcGVydHkpCgkJCV9jZWxsU3BhY2luZ1Byb3BlcnR5ID0gUHJvcGVydHkuTmV3TnVtYmVyUHJvcGVydHkoImNlbGxTcGFjaW5nIiwwLGZhbHNlLFZlY3Rvci48U3RyaW5nPihbQ2F0ZWdvcnkuVEFCTEVdKSwwLDEwMDApOwoJCQlyZXR1cm4gX2NlbGxTcGFjaW5nUHJvcGVydHk7CgkJfQoJCS8qKiBAcHJpdmF0ZSAqLwoJCXN0YXRpYyBwcml2YXRlIHZhciBfY2VsbFBhZGRpbmdQcm9wZXJ0eTpQcm9wZXJ0eTsKCQlzdGF0aWMgcHVibGljIGZ1bmN0aW9uIGdldCBjZWxsUGFkZGluZ1Byb3BlcnR5KCk6UHJvcGVydHkKCQl7CgkJCWlmICghX2NlbGxQYWRkaW5nUHJvcGVydHkpCgkJCV9jZWxsUGFkZGluZ1Byb3BlcnR5ID0gUHJvcGVydHkuTmV3TnVtYmVyT3JQZXJjZW50UHJvcGVydHkoImNlbGxQYWRkaW5nIiwwLHRydWUsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5UQUJMRV0pLDAsMTAwMCwiMCUiLCIxMDAlIikKCQkJcmV0dXJuIF9jZWxsUGFkZGluZ1Byb3BlcnR5OwoJCX0KCQkvKiogQHByaXZhdGUgKi8KCQlzdGF0aWMgcHJpdmF0ZSB2YXIgX3RhYmxlV2lkdGhQcm9wZXJ0eTpQcm9wZXJ0eTsKCQlzdGF0aWMgcHVibGljIGZ1bmN0aW9uIGdldCB0YWJsZVdpZHRoUHJvcGVydHkoKTpQcm9wZXJ0eQoJCXsKCQkJaWYgKCFfdGFibGVXaWR0aFByb3BlcnR5KQoJCQlfdGFibGVXaWR0aFByb3BlcnR5ID0gUHJvcGVydHkuTmV3TnVtYmVyT3JQZXJjZW50UHJvcGVydHkoInRhYmxlV2lkdGgiLCIxMDAlIixmYWxzZSxWZWN0b3IuPFN0cmluZz4oW0NhdGVnb3J5LlRBQkxFXSksMCw4MDAwLCIwJSIsIjEwMCUiKQoJCQlyZXR1cm4gX3RhYmxlV2lkdGhQcm9wZXJ0eTsKCQl9CgkJLyoqIEBwcml2YXRlICovCgkJc3RhdGljIHByaXZhdGUgdmFyIF90YWJsZUNvbHVtbldpZHRoUHJvcGVydHk6UHJvcGVydHk7CgkJc3RhdGljIHB1YmxpYyBmdW5jdGlvbiBnZXQgdGFibGVDb2x1bW5XaWR0aFByb3BlcnR5KCk6UHJvcGVydHkKCQl7CgkJCWlmICghX3RhYmxlQ29sdW1uV2lkdGhQcm9wZXJ0eSkKCQkJX3RhYmxlQ29sdW1uV2lkdGhQcm9wZXJ0eSA9IFByb3BlcnR5Lk5ld051bWJlck9yUGVyY2VudFByb3BlcnR5KCJ0YWJsZUNvbHVtbldpZHRoIiwwLGZhbHNlLFZlY3Rvci48U3RyaW5nPihbQ2F0ZWdvcnkuVEFCTEVDT0xVTU5dKSwwLDgwMDAsIjAlIiwiMTAwJSIpCgkJCXJldHVybiBfdGFibGVDb2x1bW5XaWR0aFByb3BlcnR5OwoJCX0KCQkvKiogQHByaXZhdGUgKi8KCQlzdGF0aWMgcHJpdmF0ZSB2YXIgX2ZyYW1lUHJvcGVydHk6UHJvcGVydHk7CgkJc3RhdGljIHB1YmxpYyBmdW5jdGlvbiBnZXQgZnJhbWVQcm9wZXJ0eSgpOlByb3BlcnR5CgkJewoJCQlpZiAoIV9mcmFtZVByb3BlcnR5KQoJCQkJX2ZyYW1lUHJvcGVydHkgPSBQcm9wZXJ0eS5OZXdFbnVtU3RyaW5nUHJvcGVydHkoCgkJCQkiZnJhbWUiLFRhYmxlRnJhbWUuVk9JRCxmYWxzZSxWZWN0b3IuPFN0cmluZz4oW0NhdGVnb3J5LlRBQkxFXSkKCQkJCSxUYWJsZUZyYW1lLlZPSUQKCQkJCSxUYWJsZUZyYW1lLkFCT1ZFCgkJCQksVGFibGVGcmFtZS5CRUxPVwoJCQkJLFRhYmxlRnJhbWUuSFNJREVTCgkJCQksVGFibGVGcmFtZS5WU0lERVMKCQkJCSxUYWJsZUZyYW1lLkxIUwoJCQkJLFRhYmxlRnJhbWUuUkhTCgkJCQksVGFibGVGcmFtZS5CT1gKCQkJCSxUYWJsZUZyYW1lLkJPUkRFUgoJCQkJKTsKCQkJcmV0dXJuIF9mcmFtZVByb3BlcnR5OwoJCX0KCQkvKiogQHByaXZhdGUgKi8KCQlzdGF0aWMgcHJpdmF0ZSB2YXIgX3J1bGVzUHJvcGVydHk6UHJvcGVydHk7CgkJc3RhdGljIHB1YmxpYyBmdW5jdGlvbiBnZXQgcnVsZXNQcm9wZXJ0eSgpOlByb3BlcnR5CgkJewoJCQlpZiAoIV9ydWxlc1Byb3BlcnR5KQoJCQkJX3J1bGVzUHJvcGVydHkgPSBQcm9wZXJ0eS5OZXdFbnVtU3RyaW5nUHJvcGVydHkoCgkJCQkicnVsZXMiLFRhYmxlUnVsZXMuTk9ORSxmYWxzZSxWZWN0b3IuPFN0cmluZz4oW0NhdGVnb3J5LlRBQkxFXSkKCQkJCSxUYWJsZVJ1bGVzLk5PTkUKCQkJCSxUYWJsZVJ1bGVzLkdST1VQUwoJCQkJLFRhYmxlUnVsZXMuUk9XUwoJCQkJLFRhYmxlUnVsZXMuQ09MUwoJCQkJLFRhYmxlUnVsZXMuQUxMCgkJCQkpOwoJCQlyZXR1cm4gX3J1bGVzUHJvcGVydHk7CgkJfQoKCQlzdGF0aWMgcHJpdmF0ZSB2YXIgX2Rlc2NyaXB0aW9uOk9iamVjdCA9IHsKCQkJICBjb2x1bW5CcmVha0JlZm9yZTpjb2x1bW5CcmVha0JlZm9yZVByb3BlcnR5CgkJCSwgY29sdW1uQnJlYWtBZnRlcjpjb2x1bW5CcmVha0FmdGVyUHJvcGVydHkKCQkJLCBjb250YWluZXJCcmVha0JlZm9yZTpjb250YWluZXJCcmVha0JlZm9yZVByb3BlcnR5CgkJCSwgY29udGFpbmVyQnJlYWtBZnRlcjpjb250YWluZXJCcmVha0FmdGVyUHJvcGVydHkKCQkJLCBjb2xvcjpjb2xvclByb3BlcnR5CgkJCSwgYmFja2dyb3VuZENvbG9yOmJhY2tncm91bmRDb2xvclByb3BlcnR5CgkJCSwgbGluZVRocm91Z2g6bGluZVRocm91Z2hQcm9wZXJ0eQoJCQksIHRleHRBbHBoYTp0ZXh0QWxwaGFQcm9wZXJ0eQoJCQksIGJhY2tncm91bmRBbHBoYTpiYWNrZ3JvdW5kQWxwaGFQcm9wZXJ0eQoJCQksIGZvbnRTaXplOmZvbnRTaXplUHJvcGVydHkKCQkJLCBiYXNlbGluZVNoaWZ0OmJhc2VsaW5lU2hpZnRQcm9wZXJ0eQoJCQksIHRyYWNraW5nTGVmdDp0cmFja2luZ0xlZnRQcm9wZXJ0eQoJCQksIHRyYWNraW5nUmlnaHQ6dHJhY2tpbmdSaWdodFByb3BlcnR5CgkJCSwgbGluZUhlaWdodDpsaW5lSGVpZ2h0UHJvcGVydHkKCQkJLCBicmVha09wcG9ydHVuaXR5OmJyZWFrT3Bwb3J0dW5pdHlQcm9wZXJ0eQoJCQksIGRpZ2l0Q2FzZTpkaWdpdENhc2VQcm9wZXJ0eQoJCQksIGRpZ2l0V2lkdGg6ZGlnaXRXaWR0aFByb3BlcnR5CgkJCSwgZG9taW5hbnRCYXNlbGluZTpkb21pbmFudEJhc2VsaW5lUHJvcGVydHkKCQkJLCBrZXJuaW5nOmtlcm5pbmdQcm9wZXJ0eQoJCQksIGxpZ2F0dXJlTGV2ZWw6bGlnYXR1cmVMZXZlbFByb3BlcnR5CgkJCSwgYWxpZ25tZW50QmFzZWxpbmU6YWxpZ25tZW50QmFzZWxpbmVQcm9wZXJ0eQoJCQksIGxvY2FsZTpsb2NhbGVQcm9wZXJ0eQoJCQksIHR5cG9ncmFwaGljQ2FzZTp0eXBvZ3JhcGhpY0Nhc2VQcm9wZXJ0eQoJCQksIGZvbnRGYW1pbHk6Zm9udEZhbWlseVByb3BlcnR5CgkJCSwgdGV4dERlY29yYXRpb246dGV4dERlY29yYXRpb25Qcm9wZXJ0eQoJCQksIGZvbnRXZWlnaHQ6Zm9udFdlaWdodFByb3BlcnR5CgkJCSwgZm9udFN0eWxlOmZvbnRTdHlsZVByb3BlcnR5CgkJCSwgd2hpdGVTcGFjZUNvbGxhcHNlOndoaXRlU3BhY2VDb2xsYXBzZVByb3BlcnR5CgkJCSwgcmVuZGVyaW5nTW9kZTpyZW5kZXJpbmdNb2RlUHJvcGVydHkKCQkJLCBjZmZIaW50aW5nOmNmZkhpbnRpbmdQcm9wZXJ0eQoJCQksIGZvbnRMb29rdXA6Zm9udExvb2t1cFByb3BlcnR5CgkJCSwgdGV4dFJvdGF0aW9uOnRleHRSb3RhdGlvblByb3BlcnR5CgkJCSwgdGV4dEluZGVudDp0ZXh0SW5kZW50UHJvcGVydHkKCQkJLCBwYXJhZ3JhcGhTdGFydEluZGVudDpwYXJhZ3JhcGhTdGFydEluZGVudFByb3BlcnR5CgkJCSwgcGFyYWdyYXBoRW5kSW5kZW50OnBhcmFncmFwaEVuZEluZGVudFByb3BlcnR5CgkJCSwgcGFyYWdyYXBoU3BhY2VCZWZvcmU6cGFyYWdyYXBoU3BhY2VCZWZvcmVQcm9wZXJ0eQoJCQksIHBhcmFncmFwaFNwYWNlQWZ0ZXI6cGFyYWdyYXBoU3BhY2VBZnRlclByb3BlcnR5CgkJCSwgdGV4dEFsaWduOnRleHRBbGlnblByb3BlcnR5CgkJCSwgdGV4dEFsaWduTGFzdDp0ZXh0QWxpZ25MYXN0UHJvcGVydHkKCQkJLCB0ZXh0SnVzdGlmeTp0ZXh0SnVzdGlmeVByb3BlcnR5CgkJCSwganVzdGlmaWNhdGlvblJ1bGU6anVzdGlmaWNhdGlvblJ1bGVQcm9wZXJ0eQoJCQksIGp1c3RpZmljYXRpb25TdHlsZTpqdXN0aWZpY2F0aW9uU3R5bGVQcm9wZXJ0eQoJCQksIGRpcmVjdGlvbjpkaXJlY3Rpb25Qcm9wZXJ0eQoJCQksIHdvcmRTcGFjaW5nOndvcmRTcGFjaW5nUHJvcGVydHkKCQkJLCB0YWJTdG9wczp0YWJTdG9wc1Byb3BlcnR5CgkJCSwgbGVhZGluZ01vZGVsOmxlYWRpbmdNb2RlbFByb3BlcnR5CgkJCSwgY29sdW1uR2FwOmNvbHVtbkdhcFByb3BlcnR5CgkJCSwgcGFkZGluZ0xlZnQ6cGFkZGluZ0xlZnRQcm9wZXJ0eQoJCQksIHBhZGRpbmdUb3A6cGFkZGluZ1RvcFByb3BlcnR5CgkJCSwgcGFkZGluZ1JpZ2h0OnBhZGRpbmdSaWdodFByb3BlcnR5CgkJCSwgcGFkZGluZ0JvdHRvbTpwYWRkaW5nQm90dG9tUHJvcGVydHkKCQkJLCBjb2x1bW5Db3VudDpjb2x1bW5Db3VudFByb3BlcnR5CgkJCSwgY29sdW1uV2lkdGg6Y29sdW1uV2lkdGhQcm9wZXJ0eQoJCQksIGZpcnN0QmFzZWxpbmVPZmZzZXQ6Zmlyc3RCYXNlbGluZU9mZnNldFByb3BlcnR5CgkJCSwgdmVydGljYWxBbGlnbjp2ZXJ0aWNhbEFsaWduUHJvcGVydHkKCQkJLCBibG9ja1Byb2dyZXNzaW9uOmJsb2NrUHJvZ3Jlc3Npb25Qcm9wZXJ0eQoJCQksIGxpbmVCcmVhazpsaW5lQnJlYWtQcm9wZXJ0eQoJCQksIGxpc3RTdHlsZVR5cGU6bGlzdFN0eWxlVHlwZVByb3BlcnR5CgkJCSwgbGlzdFN0eWxlUG9zaXRpb246bGlzdFN0eWxlUG9zaXRpb25Qcm9wZXJ0eQoJCQksIGxpc3RBdXRvUGFkZGluZzpsaXN0QXV0b1BhZGRpbmdQcm9wZXJ0eQoJCQksIGNsZWFyRmxvYXRzOmNsZWFyRmxvYXRzUHJvcGVydHkKCQkJLCBzdHlsZU5hbWU6c3R5bGVOYW1lUHJvcGVydHkKCQkJLCBsaW5rTm9ybWFsRm9ybWF0OmxpbmtOb3JtYWxGb3JtYXRQcm9wZXJ0eQoJCQksIGxpbmtBY3RpdmVGb3JtYXQ6bGlua0FjdGl2ZUZvcm1hdFByb3BlcnR5CgkJCSwgbGlua0hvdmVyRm9ybWF0OmxpbmtIb3ZlckZvcm1hdFByb3BlcnR5CgkJCSwgbGlzdE1hcmtlckZvcm1hdDpsaXN0TWFya2VyRm9ybWF0UHJvcGVydHkKCQkJLCBib3JkZXJMZWZ0V2lkdGg6Ym9yZGVyTGVmdFdpZHRoUHJvcGVydHkKCQkJLCBib3JkZXJSaWdodFdpZHRoOmJvcmRlclJpZ2h0V2lkdGhQcm9wZXJ0eQoJCQksIGJvcmRlclRvcFdpZHRoOmJvcmRlclRvcFdpZHRoUHJvcGVydHkKCQkJLCBib3JkZXJCb3R0b21XaWR0aDpib3JkZXJCb3R0b21XaWR0aFByb3BlcnR5CgkJCSwgYm9yZGVyTGVmdENvbG9yOmJvcmRlckxlZnRDb2xvclByb3BlcnR5CgkJCSwgYm9yZGVyUmlnaHRDb2xvcjpib3JkZXJSaWdodENvbG9yUHJvcGVydHkKCQkJLCBib3JkZXJUb3BDb2xvcjpib3JkZXJUb3BDb2xvclByb3BlcnR5CgkJCSwgYm9yZGVyQm90dG9tQ29sb3I6Ym9yZGVyQm90dG9tQ29sb3JQcm9wZXJ0eQoJCQksIG1hcmdpbkxlZnQ6bWFyZ2luTGVmdFByb3BlcnR5CgkJCSwgbWFyZ2luUmlnaHQ6bWFyZ2luUmlnaHRQcm9wZXJ0eQoJCQksIG1hcmdpblRvcDptYXJnaW5Ub3BQcm9wZXJ0eQoJCQksIG1hcmdpbkJvdHRvbTptYXJnaW5Cb3R0b21Qcm9wZXJ0eQoJCQksIGNlbGxTcGFjaW5nOmNlbGxTcGFjaW5nUHJvcGVydHkKCQkJLCBjZWxsUGFkZGluZzpjZWxsUGFkZGluZ1Byb3BlcnR5CgkJCSwgdGFibGVXaWR0aDp0YWJsZVdpZHRoUHJvcGVydHkKCQkJLCB0YWJsZUNvbHVtbldpZHRoOnRhYmxlQ29sdW1uV2lkdGhQcm9wZXJ0eQoJCQksIGZyYW1lOmZyYW1lUHJvcGVydHkKCQkJLCBydWxlczpydWxlc1Byb3BlcnR5CgkJfQoKCQkvKiogUHJvcGVydHkgZGVzY3JpcHRpb25zIGFjY2Vzc2libGUgYnkgbmFtZS4gQHByaXZhdGUgKi8KCQlzdGF0aWMgdGxmX2ludGVybmFsIGZ1bmN0aW9uIGdldCBkZXNjcmlwdGlvbigpOk9iamVjdAoJCXsgcmV0dXJuIF9kZXNjcmlwdGlvbjsgfQoKCQkvKiogQHByaXZhdGUgKi8KCQlzdGF0aWMgcHJpdmF0ZSB2YXIgX2VtcHR5VGV4dExheW91dEZvcm1hdDpJVGV4dExheW91dEZvcm1hdDsKCQkvKioKCQkgKiBSZXR1cm5zIGFuIElUZXh0TGF5b3V0Rm9ybWF0IGluc3RhbmNlIHdpdGggYWxsIHByb3BlcnRpZXMgc2V0IHRvIDxjb2RlPnVuZGVmaW5lZDwvY29kZT4uCgkJICogQHByaXZhdGUKCQkgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKCQkgKiBAbGFuZ3ZlcnNpb24gMy4wCgkJICovCgkJc3RhdGljIHRsZl9pbnRlcm5hbCBmdW5jdGlvbiBnZXQgZW1wdHlUZXh0TGF5b3V0Rm9ybWF0KCk6SVRleHRMYXlvdXRGb3JtYXQKCQl7CgkJCWlmIChfZW1wdHlUZXh0TGF5b3V0Rm9ybWF0ID09IG51bGwpCgkJCQlfZW1wdHlUZXh0TGF5b3V0Rm9ybWF0ID0gbmV3IFRleHRMYXlvdXRGb3JtYXQoKTsKCQkJcmV0dXJuIF9lbXB0eVRleHRMYXlvdXRGb3JtYXQ7CgkJfQoKCgkJcHJpdmF0ZSBzdGF0aWMgY29uc3QgX2VtcHR5U3R5bGVzOk9iamVjdCA9IG5ldyBPYmplY3QoKTsKCQkvKiogX3N0eWxlcyBpcyBuZXZlciBudWxsICovCgkJcHJpdmF0ZSB2YXIgX3N0eWxlczpPYmplY3Q7CgkJcHJpdmF0ZSB2YXIgX3NoYXJlZFN0eWxlczpCb29sZWFuOwoKCQkvKioKCQkgKiBDcmVhdGVzIGEgbmV3IFRleHRMYXlvdXRGb3JtYXQgb2JqZWN0LiBBbGwgc2V0dGluZ3MgYXJlIGVtcHR5IG9yLCBvcHRpb25hbGx5LCBhcmUgaW5pdGlhbGl6ZWQgZnJvbSB0aGUKCQkgKiBzdXBwbGllZCA8Y29kZT5pbml0aWFsVmFsdWVzPC9jb2RlPiBvYmplY3QuCgkJICogCgkJICogQHBhcmFtIGluaXRpYWxWYWx1ZXMgb3B0aW9uYWwgaW5zdGFuY2UgZnJvbSB3aGljaCB0byBjb3B5IGluaXRpYWwgdmFsdWVzLgoJCSAqIAoJCSAqIEBzZWUgI2RlZmF1bHRGb3JtYXQKCQkgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKCQkgKiBAbGFuZ3ZlcnNpb24gMy4wCgkJICovCgkJcHVibGljIGZ1bmN0aW9uIFRleHRMYXlvdXRGb3JtYXQoaW5pdGlhbFZhbHVlczpJVGV4dExheW91dEZvcm1hdCA9IG51bGwpCgkJewoJCQl0aGlzLmNvcHkoaW5pdGlhbFZhbHVlcyk7CgkJfQoKCQlwcml2YXRlIGZ1bmN0aW9uIHdyaXRhYmxlU3R5bGVzKCk6dm9pZAoJCXsKCQkJaWYgKF9zaGFyZWRTdHlsZXMpCgkJCXsKCQkJCV9zdHlsZXMgPSBfc3R5bGVzID09IF9lbXB0eVN0eWxlcyA/IG5ldyBPYmplY3QoKSA6IFByb3BlcnR5LmNyZWF0ZU9iamVjdFdpdGhQcm90b3R5cGUoX3N0eWxlcyk7CgkJCQlfc2hhcmVkU3R5bGVzID0gZmFsc2U7CgkJCX0KCQl9CgoJCS8qKiBAcHJpdmF0ZSBSZXR1cm5zIHRoZSBpbnRlcm5hbCBzdHlsZXMgb2JqZWN0LiAqLwoJCXRsZl9pbnRlcm5hbCBmdW5jdGlvbiBnZXRTdHlsZXMoKTpPYmplY3QKCQl7IHJldHVybiBfc3R5bGVzID09IF9lbXB0eVN0eWxlcyA/IG51bGwgOiBfc3R5bGVzOyB9CgkJLyoqIEBwcml2YXRlICovCgkJdGxmX2ludGVybmFsIGZ1bmN0aW9uIHNldFN0eWxlcyh2YWw6T2JqZWN0LHNoYXJlZDpCb29sZWFuKTp2b2lkCgkJewoJCQlDT05GSUc6OmRlYnVnIHsgYXNzZXJ0KHZhbCwiQkFEIHNldFN0eWxlcyBjYWxsIik7IH0KCQkJaWYgKF9zdHlsZXMgIT0gdmFsKQoJCQl7CgkJCQlfc3R5bGVzID0gdmFsOwoJCQkJX3NoYXJlZFN0eWxlcyA9IHNoYXJlZDsKCQkJfQoJCX0KCQkvKiogQHByaXZhdGUgKi8KCQl0bGZfaW50ZXJuYWwgZnVuY3Rpb24gY2xlYXJTdHlsZXMoKTp2b2lkCgkJewoJCQlfc3R5bGVzID0gX2VtcHR5U3R5bGVzOwoJCQlfc2hhcmVkU3R5bGVzID0gdHJ1ZTsKCQl9CgoJCS8qKiBSZXR1cm5zIHRoZSA8Y29kZT5jb3JlU3R5bGVzPC9jb2RlPiBvbiB0aGlzIFRleHRMYXlvdXRGb3JtYXQuICAKCQkgKiBUaGUgY29yZVN0eWxlcyBvYmplY3QgaW5jbHVkZXMgdGhlIGZvcm1hdHMgdGhhdCBhcmUgZGVmaW5lZCBieSBUZXh0TGF5b3V0Rm9ybWF0IGFuZCBhcmUgaW4gVGV4dExheW91dEZvcm1hdC5kZXNjcmlwdGlvbi4gVGhlCgkJICogcmV0dXJuZWQgPGNvZGU+Y29yZVN0eWxlczwvY29kZT4gb2JqZWN0IGNvbnNpc3RzIG9mIGFuIGFycmF5IG9mIDxlbT5zdHlsZW5hbWUtdmFsdWU8L2VtPiBwYWlycy4KCQkgKiAKCQkgKiBAc2VlIGZsYXNoeC50ZXh0TGF5b3V0LmZvcm1hdHMuVGV4dExheW91dEZvcm1hdAoJCSAqIAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCgkJICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQoJCSAqIEBsYW5ndmVyc2lvbiAzLjAKCQkgKi8KCQlwdWJsaWMgZnVuY3Rpb24gZ2V0IGNvcmVTdHlsZXMoKTpPYmplY3QKCQl7CgkJCXJldHVybiBfc3R5bGVzID09IF9lbXB0eVN0eWxlcyA/IG51bGwgOiBQcm9wZXJ0eS5zaGFsbG93Q29weUluRmlsdGVyKF9zdHlsZXMsZGVzY3JpcHRpb24pOwoJCX0KCgkJLyoqIFJldHVybnMgdGhlIDxjb2RlPnVzZXJTdHlsZXM8L2NvZGU+IG9uIHRoaXMgVGV4dExheW91dEZvcm1hdC4gIAoJCSAqIFRoZSB1c2VyU3R5bGVzIG9iamVjdCBpbmNsdWRlcyB0aGUgZm9ybWF0cyB0aGF0IGFyZSBkZWZpbmVkIGJ5IFRleHRMYXlvdXRGb3JtYXQgYW5kIGFyZSBub3QgaW4gVGV4dExheW91dEZvcm1hdC5kZXNjcmlwdGlvbi4gVGhlCgkJICogcmV0dXJuZWQgPGNvZGU+dXNlclN0eWxlczwvY29kZT4gb2JqZWN0IGNvbnNpc3RzIG9mIGFuIGFycmF5IG9mIDxlbT5zdHlsZW5hbWUtdmFsdWU8L2VtPiBwYWlycy4KCQkgKiAKCQkgKiBAc2VlIGZsYXNoeC50ZXh0TGF5b3V0LmZvcm1hdHMuVGV4dExheW91dEZvcm1hdAoJCSAqIAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCgkJICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQoJCSAqIEBsYW5ndmVyc2lvbiAzLjAKCQkgKi8KCQlwdWJsaWMgZnVuY3Rpb24gZ2V0IHVzZXJTdHlsZXMoKTpPYmplY3QKCQl7CgkJCXJldHVybiBfc3R5bGVzID09IF9lbXB0eVN0eWxlcyA/IG51bGwgOiBQcm9wZXJ0eS5zaGFsbG93Q29weU5vdEluRmlsdGVyKF9zdHlsZXMsZGVzY3JpcHRpb24pOwoJCX0KCgkJLyoqIFJldHVybnMgdGhlIHN0eWxlcyBvbiB0aGlzIFRleHRMYXlvdXRGb3JtYXQuICBOb3RlIHRoYXQgdGhlIGdldHRlciBtYWtlcyBhIGNvcHkgb2YgdGhlICAKCQkgKiBzdHlsZXMgZGljdGlvbmFyeS4gVGhlIGNvcmVTdHlsZXMgb2JqZWN0IGVuY2Fwc3VsYXRlcyBhbGwgc3R5bGVzIHNldCBpbiB0aGUgZm9ybWF0IHByb3BlcnR5IGluY2x1ZGluZyBjb3JlIGFuZCB1c2VyIHN0eWxlcy4gVGhlCgkJICogcmV0dXJuZWQgb2JqZWN0IGNvbnNpc3RzIG9mIGFuIGFycmF5IG9mIDxlbT5zdHlsZW5hbWUtdmFsdWU8L2VtPiBwYWlycy4KCQkgKiAKCQkgKiBAc2VlIGZsYXNoeC50ZXh0TGF5b3V0LmZvcm1hdHMuVGV4dExheW91dEZvcm1hdAoJCSAqIAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCgkJICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQoJCSAqIEBsYW5ndmVyc2lvbiAzLjAKCQkgKi8KCQlwdWJsaWMgZnVuY3Rpb24gZ2V0IHN0eWxlcygpOk9iamVjdAoJCXsKCQkJcmV0dXJuIF9zdHlsZXMgPT0gX2VtcHR5U3R5bGVzID8gbnVsbCA6IFByb3BlcnR5LnNoYWxsb3dDb3B5KF9zdHlsZXMpOwoJCX0KCgkJLyoqIEBwcml2YXRlICovCgkJdGxmX2ludGVybmFsIGZ1bmN0aW9uIHNldFN0eWxlQnlOYW1lKG5hbWU6U3RyaW5nLCBuZXdWYWx1ZToqKTp2b2lkCgkJewoJCQl3cml0YWJsZVN0eWxlcygpOwoJCQkJCgkJCWlmIChuZXdWYWx1ZSAhPT0gdW5kZWZpbmVkKQoJCQkJX3N0eWxlc1tuYW1lXSA9IG5ld1ZhbHVlOwoJCQllbHNlCgkJCXsKCQkJCWRlbGV0ZSBfc3R5bGVzW25hbWVdOwoJCQkJaWYgKF9zdHlsZXNbbmFtZV0gIT09IHVuZGVmaW5lZCkKCQkJCXsKCQkJCQlfc3R5bGVzID0gUHJvcGVydHkuc2hhbGxvd0NvcHkoX3N0eWxlcyk7CgkJCQkJZGVsZXRlIF9zdHlsZXNbbmFtZV07CgkJCQl9CgkJCX0KCQl9CgoJCS8qKiBJbnRlbnRpb25hbGx5IGhpZGRlbiBzbyB0aGF0IG92ZXJyaWRlcnMgY2FuIG92ZXJyaWRlIGluZGl2aWR1YWwgcHJvcGVydHkgc2V0dGVycyAqLwoJCXByaXZhdGUgZnVuY3Rpb24gc2V0U3R5bGVCeVByb3BlcnR5KHN0eWxlUHJvcDpQcm9wZXJ0eSxuZXdWYWx1ZToqKTp2b2lkCgkJewoJCQl2YXIgbmFtZTpTdHJpbmcgPSBzdHlsZVByb3AubmFtZTsKCQkJbmV3VmFsdWUgPSBzdHlsZVByb3Auc2V0SGVscGVyKF9zdHlsZXNbbmFtZV0sbmV3VmFsdWUpOwoJCQlzZXRTdHlsZUJ5TmFtZShuYW1lLCBuZXdWYWx1ZSk7CgkJfQoKCQkvKiogU2V0cyB0aGUgc3R5bGUgc3BlY2lmaWVkIGJ5IHRoZSA8Y29kZT5zdHlsZVByb3A8L2NvZGU+IHBhcmFtZXRlciB0byB0aGUgdmFsdWUgc3BlY2lmaWVkIGJ5IHRoZQoJCSAqIDxjb2RlPm5ld1ZhbHVlPC9jb2RlPiBwYXJhbWV0ZXIuIAoJCSAqCgkJICogQHBhcmFtIHN0eWxlUHJvcCBUaGUgbmFtZSBvZiB0aGUgc3R5bGUgdG8gc2V0LgoJCSAqIEBwYXJhbSBuZXdWYWx1ZSBUaGUgdmFsdWUgdG8gd2hpY2ggdG8gc2V0IHRoZSBzdHlsZS4KCQkgKi4KCQkgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKCQkgKiBAbGFuZ3ZlcnNpb24gMy4wCgoJCSAqLwoJCXB1YmxpYyBmdW5jdGlvbiBzZXRTdHlsZShzdHlsZVByb3A6U3RyaW5nLG5ld1ZhbHVlOiopOnZvaWQKCQl7CgkJCS8qKiByZWRpcmVjdCB0byBleGlzdGluZyBwcm9wZXJ0eSBzZXR0ZXJzIGZvciBvdmVycmlkZXJzKi8KCQkJaWYgKGRlc2NyaXB0aW9uLmhhc093blByb3BlcnR5KHN0eWxlUHJvcCkpCgkJCQl0aGlzW3N0eWxlUHJvcF0gPSBuZXdWYWx1ZTsKCQkJZWxzZQoJCQkJc2V0U3R5bGVCeU5hbWUoc3R5bGVQcm9wLG5ld1ZhbHVlKTsKCQl9CgoJCS8qKiBSZXR1cm5zIHRoZSB2YWx1ZSBvZiB0aGUgc3R5bGUgc3BlY2lmaWVkIGJ5IHRoZSA8Y29kZT5zdHlsZVByb3A8L2NvZGU+IHBhcmFtZXRlciwgd2hpY2ggc3BlY2lmaWVzCgkJICogdGhlIHN0eWxlIG5hbWUuCgkJICoKCQkgKiBAcGFyYW0gc3R5bGVQcm9wIFRoZSBuYW1lIG9mIHRoZSBzdHlsZSB3aG9zZSB2YWx1ZSBpcyB0byBiZSByZXRyaWV2ZWQuCgkJICoKCQkgKiBAcmV0dXJuIFRoZSB2YWx1ZSBvZiB0aGUgc3BlY2lmaWVkIHN0eWxlLiBUaGUgdHlwZSB2YXJpZXMgZGVwZW5kaW5nIG9uIHRoZSB0eXBlIG9mIHRoZSBzdHlsZSBiZWluZwoJCSAqIGFjY2Vzc2VkLiBSZXR1cm5zIDxjb2RlPnVuZGVmaW5lZDwvY29kZT4gaWYgdGhlIHN0eWxlIGlzIG5vdCBzZXQuCgkJICogCgkJICogQHBsYXllcnZlcnNpb24gRmxhc2ggMTAKCQkgKiBAcGxheWVydmVyc2lvbiBBSVIgMS41CgkJICogQGxhbmd2ZXJzaW9uIDMuMAoJCSAqLwoJCXB1YmxpYyBmdW5jdGlvbiBnZXRTdHlsZShzdHlsZVByb3A6U3RyaW5nKToqCgkJeyByZXR1cm4gX3N0eWxlc1tzdHlsZVByb3BdOyB9CgoJCS8qKgoJCSAqIENvcGllcyBUZXh0TGF5b3V0Rm9ybWF0IHNldHRpbmdzIGZyb20gdGhlIDxjb2RlPnZhbHVlczwvY29kZT4gSVRleHRMYXlvdXRGb3JtYXQgaW5zdGFuY2UgaW50byB0aGlzIFRleHRMYXlvdXRGb3JtYXQgb2JqZWN0LgoJCSAqIElmIDxjb2RlPnZhbHVlczwvY29kZT4gaXMgPGNvZGU+bnVsbDwvY29kZT4sIHRoaXMgVGV4dExheW91dEZvcm1hdCBvYmplY3QgaXMgaW5pdGlhbGl6ZWQgd2l0aCB1bmRlZmluZWQgdmFsdWVzIGZvciBhbGwgcHJvcGVydGllcy4KCQkgKiBAcGFyYW0gdmFsdWVzIG9wdGlvbmFsIGluc3RhbmNlIGZyb20gd2hpY2ggdG8gY29weSB2YWx1ZXMuCgkJICogCgkJICogQHBsYXllcnZlcnNpb24gRmxhc2ggMTAKCQkgKiBAcGxheWVydmVyc2lvbiBBSVIgMS41CgkJICogQGxhbmd2ZXJzaW9uIDMuMAoJCSAqLwoJCXB1YmxpYyBmdW5jdGlvbiBjb3B5KGluY29taW5nOklUZXh0TGF5b3V0Rm9ybWF0KTp2b2lkCgkJewoJCQlpZiAodGhpcyA9PSBpbmNvbWluZykKCQkJCXJldHVybjsKCQkJdmFyIGhvbGRlcjpUZXh0TGF5b3V0Rm9ybWF0ID0gaW5jb21pbmcgYXMgVGV4dExheW91dEZvcm1hdDsKCQkJaWYgKGhvbGRlcikKCQkJewoJCQkJX3N0eWxlcyA9IGhvbGRlci5fc3R5bGVzOwoJCQkJX3NoYXJlZFN0eWxlcyA9IHRydWU7CgkJCQlob2xkZXIuX3NoYXJlZFN0eWxlcyA9IHRydWU7CgkJCQlyZXR1cm47CgkJCX0KCgkJCV9zdHlsZXMgPSBfZW1wdHlTdHlsZXM7CgkJCV9zaGFyZWRTdHlsZXMgPSB0cnVlOwoKCQkJaWYgKGluY29taW5nKQoJCQl7CgkJCQlmb3IgZWFjaCAodmFyIHByb3A6UHJvcGVydHkgaW4gVGV4dExheW91dEZvcm1hdC5kZXNjcmlwdGlvbikKCQkJCXsKCQkJCQl2YXIgdmFsOiogPSBpbmNvbWluZ1twcm9wLm5hbWVdOwoJCQkJCWlmICh2YWwgIT09IHVuZGVmaW5lZCkKCQkJCQkJdGhpc1twcm9wLm5hbWVdID0gdmFsOwoJCQkJfQoJCQl9CgkJfQoKCQkvKioKCQkgKiBDb25jYXRlbmF0ZXMgdGhlIHZhbHVlcyBvZiBwcm9wZXJ0aWVzIGluIHRoZSA8Y29kZT5pbmNvbWluZzwvY29kZT4gSVRleHRMYXlvdXRGb3JtYXQgaW5zdGFuY2UKCQkgKiB3aXRoIHRoZSB2YWx1ZXMgb2YgdGhpcyBUZXh0TGF5b3V0Rm9ybWF0IG9iamVjdC4gSW4gdGhpcyAodGhlIHJlY2VpdmluZykgVGV4dExheW91dEZvcm1hdCBvYmplY3QsIHByb3BlcnRpZXMgd2hvc2UgdmFsdWVzIGFyZSA8Y29kZT5Gb3JtYXRWYWx1ZS5JTkhFUklUPC9jb2RlPiwKCQkgKiBhbmQgaW5oZXJpdGluZyBwcm9wZXJ0aWVzIHdob3NlIHZhbHVlcyBhcmUgPGNvZGU+dW5kZWZpbmVkPC9jb2RlPiB3aWxsIGdldCBuZXcgdmFsdWVzIGZyb20gdGhlIDxjb2RlPmluY29taW5nPC9jb2RlPiBvYmplY3QuCgkJICogTm9uLWluaGVyaXRpbmcgcHJvcGVydGllcyB3aG9zZSB2YWx1ZXMgYXJlIDxjb2RlPnVuZGVmaW5lZDwvY29kZT4gd2lsbCBnZXQgdGhlaXIgZGVmYXVsdCB2YWx1ZXMuCgkJICogQWxsIG90aGVyIHByb3BlcnR5IHZhbHVlcyB3aWxsIHJlbWFpbiB1bm1vZGlmaWVkLgoJCSAqIAoJCSAqIEBwYXJhbSBpbmNvbWluZyBpbnN0YW5jZSBmcm9tIHdoaWNoIHZhbHVlcyBhcmUgY29uY2F0ZW5hdGVkLgoJCSAqIEBzZWUgZmxhc2h4LnRleHRMYXlvdXQuZm9ybWF0cy5Gb3JtYXRWYWx1ZSNJTkhFUklUCgkJICogCgkJICogQHBsYXllcnZlcnNpb24gRmxhc2ggMTAKCQkgKiBAcGxheWVydmVyc2lvbiBBSVIgMS41CgkJICogQGxhbmd2ZXJzaW9uIDMuMAoJCSAqLwoJCXB1YmxpYyBmdW5jdGlvbiBjb25jYXQoaW5jb21pbmc6SVRleHRMYXlvdXRGb3JtYXQpOnZvaWQKCQl7CgkJCXZhciBob2xkZXI6VGV4dExheW91dEZvcm1hdCA9IGluY29taW5nIGFzIFRleHRMYXlvdXRGb3JtYXQ7CgkJCXZhciBwcm9wOlByb3BlcnR5OwoJCQlpZiAoaG9sZGVyKQoJCQl7CgkJCQl2YXIgaG9sZGVyU3R5bGVzOk9iamVjdCA9IGhvbGRlci5fc3R5bGVzOwoJCQkJZm9yICh2YXIga2V5OlN0cmluZyBpbiBob2xkZXJTdHlsZXMpCgkJCQl7CgkJCQkJcHJvcCA9IGRlc2NyaXB0aW9uW2tleV07CgkJCQkJaWYgKHByb3ApCgkJCQkJCXNldFN0eWxlQnlQcm9wZXJ0eShwcm9wLHByb3AuY29uY2F0SGVscGVyKF9zdHlsZXNba2V5XSxob2xkZXJTdHlsZXNba2V5XSkpOwoJCQkJCWVsc2UKCQkJCQkJc2V0U3R5bGVCeU5hbWUoa2V5LFByb3BlcnR5LmRlZmF1bHRDb25jYXRIZWxwZXIoX3N0eWxlc1trZXldLGhvbGRlclN0eWxlc1trZXldKSk7CgkJCQl9CgkJCQlyZXR1cm47CgkJCX0KCgkJCS8vIElnbm9yZXMgdXNlclN0eWxlcwoJCQlmb3IgZWFjaCAocHJvcCBpbiBUZXh0TGF5b3V0Rm9ybWF0LmRlc2NyaXB0aW9uKQoJCQl7CgkJCQlzZXRTdHlsZUJ5UHJvcGVydHkocHJvcCxwcm9wLmNvbmNhdEhlbHBlcihfc3R5bGVzW3Byb3AubmFtZV0saW5jb21pbmdbcHJvcC5uYW1lXSkpOwoJCQl9CgkJfQoKCQkvKioKCQkgKiBDb25jYXRlbmF0ZXMgdGhlIHZhbHVlcyBvZiBwcm9wZXJ0aWVzIGluIHRoZSA8Y29kZT5pbmNvbWluZzwvY29kZT4gSVRleHRMYXlvdXRGb3JtYXQgaW5zdGFuY2UKCQkgKiB3aXRoIHRoZSB2YWx1ZXMgb2YgdGhpcyBUZXh0TGF5b3V0Rm9ybWF0IG9iamVjdC4gSW4gdGhpcyAodGhlIHJlY2VpdmluZykgVGV4dExheW91dEZvcm1hdCBvYmplY3QsIHByb3BlcnRpZXMgd2hvc2UgdmFsdWVzIGFyZSA8Y29kZT5Gb3JtYXRWYWx1ZS5JTkhFUklUPC9jb2RlPiwKCQkgKiBhbmQgaW5oZXJpdGluZyBwcm9wZXJ0aWVzIHdob3NlIHZhbHVlcyBhcmUgPGNvZGU+dW5kZWZpbmVkPC9jb2RlPiB3aWxsIGdldCBuZXcgdmFsdWVzIGZyb20gdGhlIDxjb2RlPmluY29taW5nPC9jb2RlPiBvYmplY3QuCgkJICogQWxsIG90aGVyIHByb3BlcnR5IHZhbHVlcyB3aWxsIHJlbWFpbiB1bm1vZGlmaWVkLgoJCSAqIAoJCSAqIEBwYXJhbSBpbmNvbWluZyBpbnN0YW5jZSBmcm9tIHdoaWNoIHZhbHVlcyBhcmUgY29uY2F0ZW5hdGVkLgoJCSAqIEBzZWUgZmxhc2h4LnRleHRMYXlvdXQuZm9ybWF0cy5Gb3JtYXRWYWx1ZSNJTkhFUklUCgkJICogCgkJICogQHBsYXllcnZlcnNpb24gRmxhc2ggMTAKCQkgKiBAcGxheWVydmVyc2lvbiBBSVIgMS41CgkJICogQGxhbmd2ZXJzaW9uIDMuMAoJCSAqLwoJCXB1YmxpYyBmdW5jdGlvbiBjb25jYXRJbmhlcml0T25seShpbmNvbWluZzpJVGV4dExheW91dEZvcm1hdCk6dm9pZAoJCXsKCQkJdmFyIGhvbGRlcjpUZXh0TGF5b3V0Rm9ybWF0ID0gaW5jb21pbmcgYXMgVGV4dExheW91dEZvcm1hdDsKCQkJdmFyIHByb3A6UHJvcGVydHk7CgoJCQlpZiAoaG9sZGVyKQoJCQl7CgkJCQl2YXIgaG9sZGVyU3R5bGVzOk9iamVjdCA9IGhvbGRlci5fc3R5bGVzOwoJCQkJZm9yICh2YXIga2V5OlN0cmluZyBpbiBob2xkZXJTdHlsZXMpCgkJCQl7CgkJCQkJcHJvcCA9IGRlc2NyaXB0aW9uW2tleV07CgkJCQkJaWYgKHByb3ApCgkJCQkJCXNldFN0eWxlQnlQcm9wZXJ0eShwcm9wLHByb3AuY29uY2F0SW5oZXJpdE9ubHlIZWxwZXIoX3N0eWxlc1trZXldLGhvbGRlclN0eWxlc1trZXldKSk7CgkJCQkJZWxzZQoJCQkJCQlzZXRTdHlsZUJ5TmFtZShrZXksUHJvcGVydHkuZGVmYXVsdENvbmNhdEhlbHBlcihfc3R5bGVzW2tleV0saG9sZGVyU3R5bGVzW2tleV0pKTsKCQkJCX0KCQkJCXJldHVybjsKCQkJfQoKCQkJLy8gSWdub3JlcyB1c2VyU3R5bGVzCgkJCWZvciBlYWNoIChwcm9wIGluIFRleHRMYXlvdXRGb3JtYXQuZGVzY3JpcHRpb24pCgkJCXsKCQkJCXNldFN0eWxlQnlQcm9wZXJ0eShwcm9wLHByb3AuY29uY2F0SW5oZXJpdE9ubHlIZWxwZXIoX3N0eWxlc1twcm9wLm5hbWVdLGluY29taW5nW3Byb3AubmFtZV0pKTsKCQkJfQoJCX0KCgkJLyoqCgkJICogUmVwbGFjZXMgcHJvcGVydHkgdmFsdWVzIGluIHRoaXMgVGV4dExheW91dEZvcm1hdCBvYmplY3Qgd2l0aCB0aGUgdmFsdWVzIG9mIHByb3BlcnRpZXMgdGhhdCBhcmUgc2V0IGluCgkJICogdGhlIDxjb2RlPmluY29taW5nPC9jb2RlPiBJVGV4dExheW91dEZvcm1hdCBpbnN0YW5jZS4gUHJvcGVydGllcyB0aGF0IGFyZSA8Y29kZT51bmRlZmluZWQ8L2NvZGU+IGluIHRoZSA8Y29kZT5pbmNvbWluZzwvY29kZT4KCQkgKiBJVGV4dExheW91dEZvcm1hdCBpbnN0YW5jZSBhcmUgbm90IGNoYW5nZWQgaW4gdGhpcyBvYmplY3QuCgkJICogCgkJICogQHBhcmFtIGluY29taW5nIGluc3RhbmNlIHdob3NlIHByb3BlcnR5IHZhbHVlcyBhcmUgYXBwbGllZCB0byB0aGlzIFRleHRMYXlvdXRGb3JtYXQgb2JqZWN0LgoJCSAqIAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCgkJICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQoJCSAqIEBsYW5ndmVyc2lvbiAzLjAKCQkgKi8KCQlwdWJsaWMgZnVuY3Rpb24gYXBwbHkoaW5jb21pbmc6SVRleHRMYXlvdXRGb3JtYXQpOnZvaWQKCQl7CgkJCXZhciBob2xkZXI6VGV4dExheW91dEZvcm1hdCA9IGluY29taW5nIGFzIFRleHRMYXlvdXRGb3JtYXQ7CgkJCXZhciB2YWw6KjsKCgkJCWlmIChob2xkZXIpCgkJCXsKCQkJCXZhciBob2xkZXJTdHlsZXM6T2JqZWN0ID0gaG9sZGVyLl9zdHlsZXM7CgkJCQlmb3IgKHZhciBrZXk6U3RyaW5nIGluIGhvbGRlclN0eWxlcykKCQkJCXsKCQkJCQlDT05GSUc6OmRlYnVnIHsgYXNzZXJ0KGhvbGRlclN0eWxlc1trZXldICE9PSB1bmRlZmluZWQsImJhZCB2YWx1ZSBpbiBhcHBseSIpOyB9CgkJCQkJdmFsID0gaG9sZGVyU3R5bGVzW2tleV07CgkJCQkJaWYgKHZhbCAhPT0gdW5kZWZpbmVkKQoJCQkJCQlzZXRTdHlsZShrZXksdmFsKTsKCQkJCX0KCQkJCXJldHVybjsKCQkJfQoKCQkJZm9yIGVhY2ggKHZhciBwcm9wOlByb3BlcnR5IGluIFRleHRMYXlvdXRGb3JtYXQuZGVzY3JpcHRpb24pCgkJCXsKCQkJCXZhciBuYW1lOlN0cmluZyA9IHByb3AubmFtZTsKCQkJCXZhbCA9IGluY29taW5nW25hbWVdOwoJCQkJaWYgKHZhbCAhPT0gdW5kZWZpbmVkKQoJCQkJCXNldFN0eWxlKG5hbWUsdmFsKTsKCQkJfQoJCX0KCgkJLyoqCgkJICogQ29tcGFyZXMgcHJvcGVydGllcyBpbiBJVGV4dExheW91dEZvcm1hdCBpbnN0YW5jZSA8Y29kZT5wMTwvY29kZT4gd2l0aCBwcm9wZXJ0aWVzIGluIElUZXh0TGF5b3V0Rm9ybWF0IGluc3RhbmNlIDxjb2RlPnAyPC9jb2RlPgoJCSAqIGFuZCByZXR1cm5zIDxjb2RlPnRydWU8L2NvZGU+IGlmIGFsbCBwcm9wZXJ0aWVzIG1hdGNoLgoJCSAqIAoJCSAqIEBwYXJhbSBwMSBpbnN0YW5jZSB0byBjb21wYXJlIHRvIDxjb2RlPnAyPC9jb2RlPi4KCQkgKiBAcGFyYW0gcDIgaW5zdGFuY2UgdG8gY29tcGFyZSB0byA8Y29kZT5wMTwvY29kZT4uCgkJICogCgkJICogQHJldHVybiB0cnVlIGlmIGFsbCBwcm9wZXJ0aWVzIG1hdGNoLCBmYWxzZSBvdGhlcndpc2UuCgkJICogCgkJICogQHBsYXllcnZlcnNpb24gRmxhc2ggMTAKCQkgKiBAcGxheWVydmVyc2lvbiBBSVIgMS41CgkJICogQGxhbmd2ZXJzaW9uIDMuMAoJCSAqLwoJCXN0YXRpYyBwdWJsaWMgZnVuY3Rpb24gaXNFcXVhbChwMTpJVGV4dExheW91dEZvcm1hdCxwMjpJVGV4dExheW91dEZvcm1hdCk6Qm9vbGVhbgoJCXsKCQkJaWYgKHAxID09IG51bGwpCgkJCQlwMSA9IGVtcHR5VGV4dExheW91dEZvcm1hdDsKCQkJaWYgKHAyID09IG51bGwpCgkJCQlwMiA9IGVtcHR5VGV4dExheW91dEZvcm1hdDsKCQkJaWYgKHAxID09IHAyKQoJCQkJcmV0dXJuIHRydWU7CgkJCXZhciBwMUhvbGRlcjpUZXh0TGF5b3V0Rm9ybWF0ID0gcDEgYXMgVGV4dExheW91dEZvcm1hdDsKCQkJdmFyIHAySG9sZGVyOlRleHRMYXlvdXRGb3JtYXQgPSBwMiBhcyBUZXh0TGF5b3V0Rm9ybWF0OwoJCQlpZiAocDFIb2xkZXIgJiYgcDJIb2xkZXIpCgkJCQlyZXR1cm4gUHJvcGVydHkuZXF1YWxTdHlsZXMocDFIb2xkZXIuZ2V0U3R5bGVzKCkscDJIb2xkZXIuZ2V0U3R5bGVzKCksVGV4dExheW91dEZvcm1hdC5kZXNjcmlwdGlvbik7CgoJCQlmb3IgZWFjaCAodmFyIHByb3A6UHJvcGVydHkgaW4gVGV4dExheW91dEZvcm1hdC5kZXNjcmlwdGlvbikKCQkJewoJCQkJaWYgKCFwcm9wLmVxdWFsSGVscGVyKHAxW3Byb3AubmFtZV0scDJbcHJvcC5uYW1lXSkpCgkJCQkJcmV0dXJuIGZhbHNlOwoJCQl9CgoJCQlyZXR1cm4gdHJ1ZTsKCQl9CgoJCS8qKgoJCSAqIFNldHMgcHJvcGVydGllcyBpbiB0aGlzIFRleHRMYXlvdXRGb3JtYXQgb2JqZWN0IHRvIDxjb2RlPnVuZGVmaW5lZDwvY29kZT4gaWYgdGhleSBtYXRjaCB0aG9zZSBpbiB0aGUgPGNvZGU+aW5jb21pbmc8L2NvZGU+CgkJICogSVRleHRMYXlvdXRGb3JtYXQgaW5zdGFuY2UuCgkJICogCgkJICogQHBhcmFtIGluY29taW5nIGluc3RhbmNlIGFnYWluc3Qgd2hpY2ggdG8gY29tcGFyZSB0aGlzIFRleHRMYXlvdXRGb3JtYXQgb2JqZWN0J3MgcHJvcGVydHkgdmFsdWVzLgoJCSAqIAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCgkJICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQoJCSAqIEBsYW5ndmVyc2lvbiAzLjAKCQkgKi8KCQlwdWJsaWMgZnVuY3Rpb24gcmVtb3ZlTWF0Y2hpbmcoaW5jb21pbmc6SVRleHRMYXlvdXRGb3JtYXQpOnZvaWQKCQl7CgkJCWlmIChpbmNvbWluZyA9PSBudWxsKQoJCQkJcmV0dXJuOwoJCQkKCQkJdmFyIHByb3A6UHJvcGVydHk7CgkJCXZhciBob2xkZXI6VGV4dExheW91dEZvcm1hdCA9IGluY29taW5nIGFzIFRleHRMYXlvdXRGb3JtYXQ7CgkJCWlmIChob2xkZXIpCgkJCXsKCQkJCXZhciBob2xkZXJTdHlsZXM6T2JqZWN0ID0gaG9sZGVyLl9zdHlsZXM7CgkJCQlmb3IgKHZhciBrZXk6U3RyaW5nIGluIGhvbGRlclN0eWxlcykKCQkJCXsKCQkJCQlwcm9wID0gZGVzY3JpcHRpb25ba2V5XTsKCQkJCQlpZiAocHJvcCkKCQkJCQl7CgkJCQkJCWlmIChwcm9wLmVxdWFsSGVscGVyKF9zdHlsZXNba2V5XSxob2xkZXJTdHlsZXNba2V5XSkpCgkJCQkJCQl0aGlzW2tleV0gPSB1bmRlZmluZWQ7CgkJCQkJfQoJCQkJCWVsc2UgaWYgKF9zdHlsZXNba2V5XSA9PSBob2xkZXJTdHlsZXNba2V5XSkKCQkJCQkJc2V0U3R5bGUoa2V5LCB1bmRlZmluZWQpOwoJCQkJfQoJCQkJcmV0dXJuOwoJCQl9CgkJCQoJCQkvLyBpZ25vcmUgdXNlclN0eWxlcyAKCQkJZm9yIGVhY2ggKHByb3AgaW4gVGV4dExheW91dEZvcm1hdC5kZXNjcmlwdGlvbikKCQkJewoJCQkJaWYgKHByb3AuZXF1YWxIZWxwZXIoX3N0eWxlc1twcm9wLm5hbWVdLGluY29taW5nW3Byb3AubmFtZV0pKQoJCQkJCXRoaXNbcHJvcC5uYW1lXSA9IHVuZGVmaW5lZDsKCQkJfQoJCX0KCgkJLyoqCgkJICogU2V0cyBwcm9wZXJ0aWVzIGluIHRoaXMgVGV4dExheW91dEZvcm1hdCBvYmplY3QgdG8gPGNvZGU+dW5kZWZpbmVkPC9jb2RlPiBpZiB0aGV5IGRvIG5vdCBtYXRjaCB0aG9zZSBpbiB0aGUKCQkgKiA8Y29kZT5pbmNvbWluZzwvY29kZT4gSVRleHRMYXlvdXRGb3JtYXQgaW5zdGFuY2UuCgkJICogCgkJICogQHBhcmFtIGluY29taW5nIGluc3RhbmNlIGFnYWluc3Qgd2hpY2ggdG8gY29tcGFyZSB0aGlzIFRleHRMYXlvdXRGb3JtYXQgb2JqZWN0J3MgcHJvcGVydHkgdmFsdWVzLgoJCSAqIAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCgkJICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQoJCSAqIEBsYW5ndmVyc2lvbiAzLjAKCQkgKi8KCQlwdWJsaWMgZnVuY3Rpb24gcmVtb3ZlQ2xhc2hpbmcoaW5jb21pbmc6SVRleHRMYXlvdXRGb3JtYXQpOnZvaWQKCQl7CgkJCWlmIChpbmNvbWluZyA9PSBudWxsKQoJCQkJcmV0dXJuOwoJCQkKCQkJdmFyIHByb3A6UHJvcGVydHk7CgkJCXZhciBob2xkZXI6VGV4dExheW91dEZvcm1hdCA9IGluY29taW5nIGFzIFRleHRMYXlvdXRGb3JtYXQ7CgkJCWlmIChob2xkZXIpCgkJCXsKCQkJCXZhciBob2xkZXJTdHlsZXM6T2JqZWN0ID0gaG9sZGVyLl9zdHlsZXM7CgkJCQlmb3IgKHZhciBrZXk6U3RyaW5nIGluIGhvbGRlclN0eWxlcykKCQkJCXsKCQkJCQlDT05GSUc6OmRlYnVnIHsgYXNzZXJ0KGhvbGRlclN0eWxlc1trZXldICE9PSB1bmRlZmluZWQsImJhZCB2YWx1ZSBpbiByZW1vdmVDbGFzaGluZyIpOyB9CgkJCQkJcHJvcCA9IGRlc2NyaXB0aW9uW2tleV07CgkJCQkJaWYgKHByb3ApCgkJCQkJewoJCQkJCQlpZiAoIXByb3AuZXF1YWxIZWxwZXIoX3N0eWxlc1trZXldLGhvbGRlclN0eWxlc1trZXldKSkKCQkJCQkJCXRoaXNba2V5XSA9IHVuZGVmaW5lZDsKCQkJCQl9CgkJCQkJZWxzZSBpZiAoX3N0eWxlc1trZXldICE9IGhvbGRlclN0eWxlc1trZXldKQoJCQkJCQlzZXRTdHlsZShrZXksIHVuZGVmaW5lZCk7CgkJCQl9CgkJCQlyZXR1cm47CgkJCX0KCQkJZm9yIGVhY2ggKHByb3AgaW4gVGV4dExheW91dEZvcm1hdC5kZXNjcmlwdGlvbikKCQkJewoJCQkJaWYgKCFwcm9wLmVxdWFsSGVscGVyKF9zdHlsZXNbcHJvcC5uYW1lXSxpbmNvbWluZ1twcm9wLm5hbWVdKSkKCQkJCQl0aGlzW3Byb3AubmFtZV0gPSB1bmRlZmluZWQ7CgkJCX0JCQkKCQl9CgoJCVtJbnNwZWN0YWJsZShlbnVtZXJhdGlvbj0iYXV0byxhbHdheXMsaW5oZXJpdCIpXQoJCS8qKgoJCSAqIENvbnRyb2xzIGNvbHVtbiBicmVhayBiZWZvcmUgdGhlIGVsZW1lbnQuCgkJICogPHA+TGVnYWwgdmFsdWVzIGFyZSBCcmVha1N0eWxlLkFVVE8sIEJyZWFrU3R5bGUuQUxXQVlTLCBGb3JtYXRWYWx1ZS5JTkhFUklULjwvcD4KCQkgKiA8cD5EZWZhdWx0IHZhbHVlIGlzIHVuZGVmaW5lZCBpbmRpY2F0aW5nIG5vdCBzZXQuPC9wPgoJCSAqIDxwPklmIHVuZGVmaW5lZCBkdXJpbmcgdGhlIGNhc2NhZGUgdGhpcyBwcm9wZXJ0eSB3aWxsIGhhdmUgYSB2YWx1ZSBvZiBCcmVha1N0eWxlLkFVVE8uPC9wPgoJCSAqIAoJCSAqIEB0aHJvd3MgUmFuZ2VFcnJvciB3aGVuIHNldCB2YWx1ZSBpcyBub3Qgd2l0aGluIHJhbmdlIGZvciB0aGlzIHByb3BlcnR5CgkJICogCgkJICogQHBsYXllcnZlcnNpb24gRmxhc2ggMTAKCQkgKiBAcGxheWVydmVyc2lvbiBBSVIgMS41CgkJICogQGxhbmd2ZXJzaW9uIDMuMAoJCSAqIEBzZWUgZmxhc2h4LnRleHRMYXlvdXQuZm9ybWF0cy5CcmVha1N0eWxlCgkJICovCgkJcHVibGljIGZ1bmN0aW9uIGdldCBjb2x1bW5CcmVha0JlZm9yZSgpOioKCQl7IHJldHVybiBfc3R5bGVzLmNvbHVtbkJyZWFrQmVmb3JlOyB9CgkJcHVibGljIGZ1bmN0aW9uIHNldCBjb2x1bW5CcmVha0JlZm9yZSh2YWx1ZToqKTp2b2lkCgkJeyBzZXRTdHlsZUJ5UHJvcGVydHkoVGV4dExheW91dEZvcm1hdC5jb2x1bW5CcmVha0JlZm9yZVByb3BlcnR5LHZhbHVlKTsgfQoKCQlbSW5zcGVjdGFibGUoZW51bWVyYXRpb249ImF1dG8sYWx3YXlzLGluaGVyaXQiKV0KCQkvKioKCQkgKiBDb250cm9scyBjb2x1bW4gYWZ0ZXIgYmVmb3JlIHRoZSBlbGVtZW50LgoJCSAqIDxwPkxlZ2FsIHZhbHVlcyBhcmUgQnJlYWtTdHlsZS5BVVRPLCBCcmVha1N0eWxlLkFMV0FZUywgRm9ybWF0VmFsdWUuSU5IRVJJVC48L3A+CgkJICogPHA+RGVmYXVsdCB2YWx1ZSBpcyB1bmRlZmluZWQgaW5kaWNhdGluZyBub3Qgc2V0LjwvcD4KCQkgKiA8cD5JZiB1bmRlZmluZWQgZHVyaW5nIHRoZSBjYXNjYWRlIHRoaXMgcHJvcGVydHkgd2lsbCBoYXZlIGEgdmFsdWUgb2YgQnJlYWtTdHlsZS5BVVRPLjwvcD4KCQkgKiAKCQkgKiBAdGhyb3dzIFJhbmdlRXJyb3Igd2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eQoJCSAqIAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCgkJICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQoJCSAqIEBsYW5ndmVyc2lvbiAzLjAKCQkgKiBAc2VlIGZsYXNoeC50ZXh0TGF5b3V0LmZvcm1hdHMuQnJlYWtTdHlsZQoJCSAqLwoJCXB1YmxpYyBmdW5jdGlvbiBnZXQgY29sdW1uQnJlYWtBZnRlcigpOioKCQl7IHJldHVybiBfc3R5bGVzLmNvbHVtbkJyZWFrQWZ0ZXI7IH0KCQlwdWJsaWMgZnVuY3Rpb24gc2V0IGNvbHVtbkJyZWFrQWZ0ZXIodmFsdWU6Kik6dm9pZAoJCXsgc2V0U3R5bGVCeVByb3BlcnR5KFRleHRMYXlvdXRGb3JtYXQuY29sdW1uQnJlYWtBZnRlclByb3BlcnR5LHZhbHVlKTsgfQoKCQlbSW5zcGVjdGFibGUoZW51bWVyYXRpb249ImF1dG8sYWx3YXlzLGluaGVyaXQiKV0KCQkvKioKCQkgKiBDb250cm9scyBjb250YWluZXIgYnJlYWsgYmVmb3JlIHRoZSBlbGVtZW50LgoJCSAqIDxwPkxlZ2FsIHZhbHVlcyBhcmUgQnJlYWtTdHlsZS5BVVRPLCBCcmVha1N0eWxlLkFMV0FZUywgRm9ybWF0VmFsdWUuSU5IRVJJVC48L3A+CgkJICogPHA+RGVmYXVsdCB2YWx1ZSBpcyB1bmRlZmluZWQgaW5kaWNhdGluZyBub3Qgc2V0LjwvcD4KCQkgKiA8cD5JZiB1bmRlZmluZWQgZHVyaW5nIHRoZSBjYXNjYWRlIHRoaXMgcHJvcGVydHkgd2lsbCBoYXZlIGEgdmFsdWUgb2YgQnJlYWtTdHlsZS5BVVRPLjwvcD4KCQkgKiAKCQkgKiBAdGhyb3dzIFJhbmdlRXJyb3Igd2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eQoJCSAqIAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCgkJICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQoJCSAqIEBsYW5ndmVyc2lvbiAzLjAKCQkgKiBAc2VlIGZsYXNoeC50ZXh0TGF5b3V0LmZvcm1hdHMuQnJlYWtTdHlsZQoJCSAqLwoJCXB1YmxpYyBmdW5jdGlvbiBnZXQgY29udGFpbmVyQnJlYWtCZWZvcmUoKToqCgkJeyByZXR1cm4gX3N0eWxlcy5jb250YWluZXJCcmVha0JlZm9yZTsgfQoJCXB1YmxpYyBmdW5jdGlvbiBzZXQgY29udGFpbmVyQnJlYWtCZWZvcmUodmFsdWU6Kik6dm9pZAoJCXsgc2V0U3R5bGVCeVByb3BlcnR5KFRleHRMYXlvdXRGb3JtYXQuY29udGFpbmVyQnJlYWtCZWZvcmVQcm9wZXJ0eSx2YWx1ZSk7IH0KCgkJW0luc3BlY3RhYmxlKGVudW1lcmF0aW9uPSJhdXRvLGFsd2F5cyxpbmhlcml0IildCgkJLyoqCgkJICogQ29udHJvbHMgY29udGFpbmVyIGFmdGVyIGJlZm9yZSB0aGUgZWxlbWVudC4KCQkgKiA8cD5MZWdhbCB2YWx1ZXMgYXJlIEJyZWFrU3R5bGUuQVVUTywgQnJlYWtTdHlsZS5BTFdBWVMsIEZvcm1hdFZhbHVlLklOSEVSSVQuPC9wPgoJCSAqIDxwPkRlZmF1bHQgdmFsdWUgaXMgdW5kZWZpbmVkIGluZGljYXRpbmcgbm90IHNldC48L3A+CgkJICogPHA+SWYgdW5kZWZpbmVkIGR1cmluZyB0aGUgY2FzY2FkZSB0aGlzIHByb3BlcnR5IHdpbGwgaGF2ZSBhIHZhbHVlIG9mIEJyZWFrU3R5bGUuQVVUTy48L3A+CgkJICogCgkJICogQHRocm93cyBSYW5nZUVycm9yIHdoZW4gc2V0IHZhbHVlIGlzIG5vdCB3aXRoaW4gcmFuZ2UgZm9yIHRoaXMgcHJvcGVydHkKCQkgKiAKCQkgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKCQkgKiBAbGFuZ3ZlcnNpb24gMy4wCgkJICogQHNlZSBmbGFzaHgudGV4dExheW91dC5mb3JtYXRzLkJyZWFrU3R5bGUKCQkgKi8KCQlwdWJsaWMgZnVuY3Rpb24gZ2V0IGNvbnRhaW5lckJyZWFrQWZ0ZXIoKToqCgkJeyByZXR1cm4gX3N0eWxlcy5jb250YWluZXJCcmVha0FmdGVyOyB9CgkJcHVibGljIGZ1bmN0aW9uIHNldCBjb250YWluZXJCcmVha0FmdGVyKHZhbHVlOiopOnZvaWQKCQl7IHNldFN0eWxlQnlQcm9wZXJ0eShUZXh0TGF5b3V0Rm9ybWF0LmNvbnRhaW5lckJyZWFrQWZ0ZXJQcm9wZXJ0eSx2YWx1ZSk7IH0KCgkJLyoqCgkJICogQ29sb3Igb2YgdGhlIHRleHQuIEEgaGV4YWRlY2ltYWwgbnVtYmVyIHRoYXQgc3BlY2lmaWVzIHRocmVlIDgtYml0IFJHQiAocmVkLCBncmVlbiwgYmx1ZSkgdmFsdWVzOyBmb3IgZXhhbXBsZSwgMHhGRjAwMDAgaXMgcmVkIGFuZCAweDAwRkYwMCBpcyBncmVlbi4gSXQgY2FuIGFsc28gYmUgZW51bSB2YWx1ZSB7QkxBQ0ssIEdSRUVOLCBHUkFZLCBCTFVFLCBTSUxWRVIsIExJTUUsIE9MSVZFLCBXSElURSwgWUVMTE9XLCBNQVJPT04sIE5BVlksIFJFRCwgUFVSUExFLCBURUFMLCBGVUNIU0lBLCBBUVVBLCBNQUdFTlRBLCBDWUFOfQoJCSAqIDxwPkxlZ2FsIHZhbHVlcyBhcyBhIHN0cmluZyBhcmUgQ29sb3JOYW1lLkJMQUNLLCBDb2xvck5hbWUuR1JFRU4sIENvbG9yTmFtZS5HUkFZLCBDb2xvck5hbWUuQkxVRSwgQ29sb3JOYW1lLlNJTFZFUiwgQ29sb3JOYW1lLkxJTUUsIENvbG9yTmFtZS5PTElWRSwgQ29sb3JOYW1lLldISVRFLCBDb2xvck5hbWUuWUVMTE9XLCBDb2xvck5hbWUuTUFST09OLCBDb2xvck5hbWUuTkFWWSwgQ29sb3JOYW1lLlJFRCwgQ29sb3JOYW1lLlBVUlBMRSwgQ29sb3JOYW1lLlRFQUwsIENvbG9yTmFtZS5GVUNIU0lBLCBDb2xvck5hbWUuQVFVQSwgQ29sb3JOYW1lLk1BR0VOVEEsIENvbG9yTmFtZS5DWUFOLCBGb3JtYXRWYWx1ZS5JTkhFUklUIGFuZCB1aW50cyBmcm9tIDB4MCB0byAweGZmZmZmZmZmLjwvcD4KCQkgKiA8cD5EZWZhdWx0IHZhbHVlIGlzIHVuZGVmaW5lZCBpbmRpY2F0aW5nIG5vdCBzZXQuPC9wPgoJCSAqIDxwPklmIHVuZGVmaW5lZCBkdXJpbmcgdGhlIGNhc2NhZGUgdGhpcyBwcm9wZXJ0eSB3aWxsIGluaGVyaXQgaXRzIHZhbHVlIGZyb20gYW4gYW5jZXN0b3IuIElmIG5vIGFuY2VzdG9yIGhhcyBzZXQgdGhpcyBwcm9wZXJ0eSwgaXQgd2lsbCBoYXZlIGEgdmFsdWUgb2YgMC48L3A+CgkJICogCgkJICogQHRocm93cyBSYW5nZUVycm9yIHdoZW4gc2V0IHZhbHVlIGlzIG5vdCB3aXRoaW4gcmFuZ2UgZm9yIHRoaXMgcHJvcGVydHkKCQkgKiAKCQkgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKCQkgKiBAbGFuZ3ZlcnNpb24gMy4wCgkJICogQHNlZSBmbGFzaHgudGV4dExheW91dC5mb3JtYXRzLkNvbG9yTmFtZQoJCSAqLwoJCXB1YmxpYyBmdW5jdGlvbiBnZXQgY29sb3IoKToqCgkJeyByZXR1cm4gX3N0eWxlcy5jb2xvcjsgfQoJCXB1YmxpYyBmdW5jdGlvbiBzZXQgY29sb3IodmFsdWU6Kik6dm9pZAoJCXsgc2V0U3R5bGVCeVByb3BlcnR5KFRleHRMYXlvdXRGb3JtYXQuY29sb3JQcm9wZXJ0eSx2YWx1ZSk7IH0KCgkJLyoqCgkJICogQmFja2dyb3VuZCBjb2xvciBvZiB0aGUgdGV4dCAoYWRvcHRzIGRlZmF1bHQgdmFsdWUgaWYgdW5kZWZpbmVkIGR1cmluZyBjYXNjYWRlKS4gQ2FuIGJlIGVpdGhlciB0aGUgY29uc3RhbnQgdmFsdWUgIDxjb2RlPkJhY2tncm91bmRDb2xvci5UUkFOU1BBUkVOVDwvY29kZT4sIG9yIGEgaGV4YWRlY2ltYWwgdmFsdWUgdGhhdCBzcGVjaWZpZXMgdGhlIHRocmVlIDgtYml0IFJHQiAocmVkLCBncmVlbiwgYmx1ZSkgdmFsdWVzOyBmb3IgZXhhbXBsZSwgMHhGRjAwMDAgaXMgcmVkIGFuZCAweDAwRkYwMCBpcyBncmVlbi4KCQkgKiA8cD5MZWdhbCB2YWx1ZXMgYXMgYSBzdHJpbmcgYXJlIEJhY2tncm91bmRDb2xvci5UUkFOU1BBUkVOVCwgRm9ybWF0VmFsdWUuSU5IRVJJVCBhbmQgdWludHMgZnJvbSAweDAgdG8gMHhmZmZmZmZmZi48L3A+CgkJICogPHA+RGVmYXVsdCB2YWx1ZSBpcyB1bmRlZmluZWQgaW5kaWNhdGluZyBub3Qgc2V0LjwvcD4KCQkgKiA8cD5JZiB1bmRlZmluZWQgZHVyaW5nIHRoZSBjYXNjYWRlIHRoaXMgcHJvcGVydHkgd2lsbCBoYXZlIGEgdmFsdWUgb2YgQmFja2dyb3VuZENvbG9yLlRSQU5TUEFSRU5ULjwvcD4KCQkgKiAKCQkgKiBAdGhyb3dzIFJhbmdlRXJyb3Igd2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eQoJCSAqIAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCgkJICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQoJCSAqIEBsYW5ndmVyc2lvbiAzLjAKCQkgKiBAc2VlIGZsYXNoeC50ZXh0TGF5b3V0LmZvcm1hdHMuQmFja2dyb3VuZENvbG9yCgkJICovCgkJcHVibGljIGZ1bmN0aW9uIGdldCBiYWNrZ3JvdW5kQ29sb3IoKToqCgkJeyByZXR1cm4gX3N0eWxlcy5iYWNrZ3JvdW5kQ29sb3I7IH0KCQlwdWJsaWMgZnVuY3Rpb24gc2V0IGJhY2tncm91bmRDb2xvcih2YWx1ZToqKTp2b2lkCgkJeyBzZXRTdHlsZUJ5UHJvcGVydHkoVGV4dExheW91dEZvcm1hdC5iYWNrZ3JvdW5kQ29sb3JQcm9wZXJ0eSx2YWx1ZSk7IH0KCgkJW0luc3BlY3RhYmxlKGVudW1lcmF0aW9uPSJ0cnVlLGZhbHNlLGluaGVyaXQiKV0KCQkvKioKCQkgKiBJZiA8Y29kZT50cnVlPC9jb2RlPiwgYXBwbGllcyBzdHJpa2V0aHJvdWdoLCBhIGxpbmUgZHJhd24gdGhyb3VnaCB0aGUgbWlkZGxlIG9mIHRoZSB0ZXh0LgoJCSAqIDxwPkxlZ2FsIHZhbHVlcyBhcmUgdHJ1ZSwgZmFsc2UgYW5kIEZvcm1hdFZhbHVlLklOSEVSSVQuPC9wPgoJCSAqIDxwPkRlZmF1bHQgdmFsdWUgaXMgdW5kZWZpbmVkIGluZGljYXRpbmcgbm90IHNldC48L3A+CgkJICogPHA+SWYgdW5kZWZpbmVkIGR1cmluZyB0aGUgY2FzY2FkZSB0aGlzIHByb3BlcnR5IHdpbGwgaW5oZXJpdCBpdHMgdmFsdWUgZnJvbSBhbiBhbmNlc3Rvci4gSWYgbm8gYW5jZXN0b3IgaGFzIHNldCB0aGlzIHByb3BlcnR5LCBpdCB3aWxsIGhhdmUgYSB2YWx1ZSBvZiBmYWxzZS48L3A+CgkJICogCgkJICogQHRocm93cyBSYW5nZUVycm9yIHdoZW4gc2V0IHZhbHVlIGlzIG5vdCB3aXRoaW4gcmFuZ2UgZm9yIHRoaXMgcHJvcGVydHkKCQkgKiAKCQkgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKCQkgKiBAbGFuZ3ZlcnNpb24gMy4wCgkJICovCgkJcHVibGljIGZ1bmN0aW9uIGdldCBsaW5lVGhyb3VnaCgpOioKCQl7IHJldHVybiBfc3R5bGVzLmxpbmVUaHJvdWdoOyB9CgkJcHVibGljIGZ1bmN0aW9uIHNldCBsaW5lVGhyb3VnaCh2YWx1ZToqKTp2b2lkCgkJeyBzZXRTdHlsZUJ5UHJvcGVydHkoVGV4dExheW91dEZvcm1hdC5saW5lVGhyb3VnaFByb3BlcnR5LHZhbHVlKTsgfQoKCQkvKioKCQkgKiBBbHBoYSAodHJhbnNwYXJlbmN5KSB2YWx1ZSBmb3IgdGhlIHRleHQuIEEgdmFsdWUgb2YgMCBpcyBmdWxseSB0cmFuc3BhcmVudCwgYW5kIGEgdmFsdWUgb2YgMSBpcyBmdWxseSBvcGFxdWUuIERpc3BsYXkgb2JqZWN0cyB3aXRoIDxjb2RlPnRleHRBbHBoYTwvY29kZT4gc2V0IHRvIDAgYXJlIGFjdGl2ZSwgZXZlbiB0aG91Z2ggdGhleSBhcmUgaW52aXNpYmxlLgoJCSAqIDxwPkxlZ2FsIHZhbHVlcyBhcmUgbnVtYmVycyBmcm9tIDAgdG8gMSBhbmQgRm9ybWF0VmFsdWUuSU5IRVJJVC48L3A+CgkJICogPHA+RGVmYXVsdCB2YWx1ZSBpcyB1bmRlZmluZWQgaW5kaWNhdGluZyBub3Qgc2V0LjwvcD4KCQkgKiA8cD5JZiB1bmRlZmluZWQgZHVyaW5nIHRoZSBjYXNjYWRlIHRoaXMgcHJvcGVydHkgd2lsbCBpbmhlcml0IGl0cyB2YWx1ZSBmcm9tIGFuIGFuY2VzdG9yLiBJZiBubyBhbmNlc3RvciBoYXMgc2V0IHRoaXMgcHJvcGVydHksIGl0IHdpbGwgaGF2ZSBhIHZhbHVlIG9mIDEuPC9wPgoJCSAqIAoJCSAqIEB0aHJvd3MgUmFuZ2VFcnJvciB3aGVuIHNldCB2YWx1ZSBpcyBub3Qgd2l0aGluIHJhbmdlIGZvciB0aGlzIHByb3BlcnR5CgkJICogCgkJICogQHBsYXllcnZlcnNpb24gRmxhc2ggMTAKCQkgKiBAcGxheWVydmVyc2lvbiBBSVIgMS41CgkJICogQGxhbmd2ZXJzaW9uIDMuMAoJCSAqLwoJCXB1YmxpYyBmdW5jdGlvbiBnZXQgdGV4dEFscGhhKCk6KgoJCXsgcmV0dXJuIF9zdHlsZXMudGV4dEFscGhhOyB9CgkJcHVibGljIGZ1bmN0aW9uIHNldCB0ZXh0QWxwaGEodmFsdWU6Kik6dm9pZAoJCXsgc2V0U3R5bGVCeVByb3BlcnR5KFRleHRMYXlvdXRGb3JtYXQudGV4dEFscGhhUHJvcGVydHksdmFsdWUpOyB9CgoJCS8qKgoJCSAqIEFscGhhICh0cmFuc3BhcmVuY3kpIHZhbHVlIGZvciB0aGUgYmFja2dyb3VuZCAoYWRvcHRzIGRlZmF1bHQgdmFsdWUgaWYgdW5kZWZpbmVkIGR1cmluZyBjYXNjYWRlKS4gQSB2YWx1ZSBvZiAwIGlzIGZ1bGx5IHRyYW5zcGFyZW50LCBhbmQgYSB2YWx1ZSBvZiAxIGlzIGZ1bGx5IG9wYXF1ZS4gRGlzcGxheSBvYmplY3RzIHdpdGggYWxwaGEgc2V0IHRvIDAgYXJlIGFjdGl2ZSwgZXZlbiB0aG91Z2ggdGhleSBhcmUgaW52aXNpYmxlLgoJCSAqIDxwPkxlZ2FsIHZhbHVlcyBhcmUgbnVtYmVycyBmcm9tIDAgdG8gMSBhbmQgRm9ybWF0VmFsdWUuSU5IRVJJVC48L3A+CgkJICogPHA+RGVmYXVsdCB2YWx1ZSBpcyB1bmRlZmluZWQgaW5kaWNhdGluZyBub3Qgc2V0LjwvcD4KCQkgKiA8cD5JZiB1bmRlZmluZWQgZHVyaW5nIHRoZSBjYXNjYWRlIHRoaXMgcHJvcGVydHkgd2lsbCBoYXZlIGEgdmFsdWUgb2YgMS48L3A+CgkJICogCgkJICogQHRocm93cyBSYW5nZUVycm9yIHdoZW4gc2V0IHZhbHVlIGlzIG5vdCB3aXRoaW4gcmFuZ2UgZm9yIHRoaXMgcHJvcGVydHkKCQkgKiAKCQkgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKCQkgKiBAbGFuZ3ZlcnNpb24gMy4wCgkJICovCgkJcHVibGljIGZ1bmN0aW9uIGdldCBiYWNrZ3JvdW5kQWxwaGEoKToqCgkJeyByZXR1cm4gX3N0eWxlcy5iYWNrZ3JvdW5kQWxwaGE7IH0KCQlwdWJsaWMgZnVuY3Rpb24gc2V0IGJhY2tncm91bmRBbHBoYSh2YWx1ZToqKTp2b2lkCgkJeyBzZXRTdHlsZUJ5UHJvcGVydHkoVGV4dExheW91dEZvcm1hdC5iYWNrZ3JvdW5kQWxwaGFQcm9wZXJ0eSx2YWx1ZSk7IH0KCgkJLyoqCgkJICogVGhlIHNpemUgb2YgdGhlIHRleHQgaW4gcGl4ZWxzLgoJCSAqIDxwPkxlZ2FsIHZhbHVlcyBhcmUgbnVtYmVycyBmcm9tIDEgdG8gNzIwIGFuZCBGb3JtYXRWYWx1ZS5JTkhFUklULjwvcD4KCQkgKiA8cD5EZWZhdWx0IHZhbHVlIGlzIHVuZGVmaW5lZCBpbmRpY2F0aW5nIG5vdCBzZXQuPC9wPgoJCSAqIDxwPklmIHVuZGVmaW5lZCBkdXJpbmcgdGhlIGNhc2NhZGUgdGhpcyBwcm9wZXJ0eSB3aWxsIGluaGVyaXQgaXRzIHZhbHVlIGZyb20gYW4gYW5jZXN0b3IuIElmIG5vIGFuY2VzdG9yIGhhcyBzZXQgdGhpcyBwcm9wZXJ0eSwgaXQgd2lsbCBoYXZlIGEgdmFsdWUgb2YgMTIuPC9wPgoJCSAqIAoJCSAqIEB0aHJvd3MgUmFuZ2VFcnJvciB3aGVuIHNldCB2YWx1ZSBpcyBub3Qgd2l0aGluIHJhbmdlIGZvciB0aGlzIHByb3BlcnR5CgkJICogCgkJICogQHBsYXllcnZlcnNpb24gRmxhc2ggMTAKCQkgKiBAcGxheWVydmVyc2lvbiBBSVIgMS41CgkJICogQGxhbmd2ZXJzaW9uIDMuMAoJCSAqLwoJCXB1YmxpYyBmdW5jdGlvbiBnZXQgZm9udFNpemUoKToqCgkJeyByZXR1cm4gX3N0eWxlcy5mb250U2l6ZTsgfQoJCXB1YmxpYyBmdW5jdGlvbiBzZXQgZm9udFNpemUodmFsdWU6Kik6dm9pZAoJCXsgc2V0U3R5bGVCeVByb3BlcnR5KFRleHRMYXlvdXRGb3JtYXQuZm9udFNpemVQcm9wZXJ0eSx2YWx1ZSk7IH0KCgkJLyoqCgkJICogQW1vdW50IHRvIHNoaWZ0IHRoZSBiYXNlbGluZSBmcm9tIHRoZSA8Y29kZT5kb21pbmFudEJhc2VsaW5lPC9jb2RlPiB2YWx1ZS4gVW5pdHMgYXJlIGluIHBpeGVscywgb3IgYSBwZXJjZW50YWdlIG9mIDxjb2RlPmZvbnRTaXplPC9jb2RlPiAoaW4gd2hpY2ggY2FzZSwgZW50ZXIgYSBzdHJpbmcgdmFsdWUsIGxpa2UgMTQwJSkuICBQb3NpdGl2ZSB2YWx1ZXMgc2hpZnQgdGhlIGxpbmUgdXAgZm9yIGhvcml6b250YWwgdGV4dCAocmlnaHQgZm9yIHZlcnRpY2FsKSBhbmQgbmVnYXRpdmUgdmFsdWVzIHNoaWZ0IGl0IGRvd24gZm9yIGhvcml6b250YWwgKGxlZnQgZm9yIHZlcnRpY2FsKS4gCgkJICogPHA+TGVnYWwgdmFsdWVzIGFyZSBCYXNlbGluZVNoaWZ0LlNVUEVSU0NSSVBULCBCYXNlbGluZVNoaWZ0LlNVQlNDUklQVCwgRm9ybWF0VmFsdWUuSU5IRVJJVC48L3A+CgkJICogPHA+TGVnYWwgdmFsdWVzIGFzIGEgbnVtYmVyIGFyZSBmcm9tIC0xMDAwIHRvIDEwMDAuPC9wPgoJCSAqIDxwPkxlZ2FsIHZhbHVlcyBhcyBhIHBlcmNlbnQgYXJlIG51bWJlcnMgZnJvbSAtMTAwMCB0byAxMDAwLjwvcD4KCQkgKiA8cD5EZWZhdWx0IHZhbHVlIGlzIHVuZGVmaW5lZCBpbmRpY2F0aW5nIG5vdCBzZXQuPC9wPgoJCSAqIDxwPklmIHVuZGVmaW5lZCBkdXJpbmcgdGhlIGNhc2NhZGUgdGhpcyBwcm9wZXJ0eSB3aWxsIGluaGVyaXQgaXRzIHZhbHVlIGZyb20gYW4gYW5jZXN0b3IuIElmIG5vIGFuY2VzdG9yIGhhcyBzZXQgdGhpcyBwcm9wZXJ0eSwgaXQgd2lsbCBoYXZlIGEgdmFsdWUgb2YgMC4wLjwvcD4KCQkgKiAKCQkgKiBAdGhyb3dzIFJhbmdlRXJyb3Igd2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eQoJCSAqIAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCgkJICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQoJCSAqIEBsYW5ndmVyc2lvbiAzLjAKCQkgKiBAc2VlIGZsYXNoeC50ZXh0TGF5b3V0LmZvcm1hdHMuQmFzZWxpbmVTaGlmdAoJCSAqLwoJCXB1YmxpYyBmdW5jdGlvbiBnZXQgYmFzZWxpbmVTaGlmdCgpOioKCQl7IHJldHVybiBfc3R5bGVzLmJhc2VsaW5lU2hpZnQ7IH0KCQlwdWJsaWMgZnVuY3Rpb24gc2V0IGJhc2VsaW5lU2hpZnQodmFsdWU6Kik6dm9pZAoJCXsgc2V0U3R5bGVCeVByb3BlcnR5KFRleHRMYXlvdXRGb3JtYXQuYmFzZWxpbmVTaGlmdFByb3BlcnR5LHZhbHVlKTsgfQoKCQkvKioKCQkgKiBOdW1iZXIgaW4gcGl4ZWxzIChvciBwZXJjZW50IG9mIDxjb2RlPmZvbnRTaXplPC9jb2RlPiwgbGlrZSAxMjAlKSBpbmRpY2F0aW5nIHRoZSBhbW91bnQgb2YgdHJhY2tpbmcgKG1hbnVhbCBrZXJuaW5nKSB0byBiZSBhcHBsaWVkIHRvIHRoZSBsZWZ0IG9mIGVhY2ggY2hhcmFjdGVyLiBJZiBrZXJuaW5nIGlzIGVuYWJsZWQsIHRoZSA8Y29kZT50cmFja2luZ0xlZnQ8L2NvZGU+IHZhbHVlIGlzIGFkZGVkIHRvIHRoZSB2YWx1ZXMgaW4gdGhlIGtlcm5pbmcgdGFibGUgZm9yIHRoZSBmb250LiBJZiBrZXJuaW5nIGlzIGRpc2FibGVkLCB0aGUgPGNvZGU+dHJhY2tpbmdMZWZ0PC9jb2RlPiB2YWx1ZSBpcyB1c2VkIGFzIGEgbWFudWFsIGtlcm5pbmcgdmFsdWUuIFN1cHBvcnRzIGJvdGggcG9zaXRpdmUgYW5kIG5lZ2F0aXZlIHZhbHVlcy4gCgkJICogPHA+TGVnYWwgdmFsdWVzIGFzIGEgbnVtYmVyIGFyZSBmcm9tIC0xMDAwIHRvIDEwMDAuPC9wPgoJCSAqIDxwPkxlZ2FsIHZhbHVlcyBhcyBhIHBlcmNlbnQgYXJlIG51bWJlcnMgZnJvbSAtMTAwMCUgdG8gMTAwMCUuPC9wPgoJCSAqIDxwPkxlZ2FsIHZhbHVlcyBpbmNsdWRlIEZvcm1hdFZhbHVlLklOSEVSSVQuPC9wPgoJCSAqIDxwPkRlZmF1bHQgdmFsdWUgaXMgdW5kZWZpbmVkIGluZGljYXRpbmcgbm90IHNldC48L3A+CgkJICogPHA+SWYgdW5kZWZpbmVkIGR1cmluZyB0aGUgY2FzY2FkZSB0aGlzIHByb3BlcnR5IHdpbGwgaW5oZXJpdCBpdHMgdmFsdWUgZnJvbSBhbiBhbmNlc3Rvci4gSWYgbm8gYW5jZXN0b3IgaGFzIHNldCB0aGlzIHByb3BlcnR5LCBpdCB3aWxsIGhhdmUgYSB2YWx1ZSBvZiAwLjwvcD4KCQkgKiAKCQkgKiBAdGhyb3dzIFJhbmdlRXJyb3Igd2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eQoJCSAqIAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCgkJICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQoJCSAqIEBsYW5ndmVyc2lvbiAzLjAKCQkgKi8KCQlwdWJsaWMgZnVuY3Rpb24gZ2V0IHRyYWNraW5nTGVmdCgpOioKCQl7IHJldHVybiBfc3R5bGVzLnRyYWNraW5nTGVmdDsgfQoJCXB1YmxpYyBmdW5jdGlvbiBzZXQgdHJhY2tpbmdMZWZ0KHZhbHVlOiopOnZvaWQKCQl7IHNldFN0eWxlQnlQcm9wZXJ0eShUZXh0TGF5b3V0Rm9ybWF0LnRyYWNraW5nTGVmdFByb3BlcnR5LHZhbHVlKTsgfQoKCQkvKioKCQkgKiBOdW1iZXIgaW4gcGl4ZWxzIChvciBwZXJjZW50IG9mIDxjb2RlPmZvbnRTaXplPC9jb2RlPiwgbGlrZSAxMjAlKSBpbmRpY2F0aW5nIHRoZSBhbW91bnQgb2YgdHJhY2tpbmcgKG1hbnVhbCBrZXJuaW5nKSB0byBiZSBhcHBsaWVkIHRvIHRoZSByaWdodCBvZiBlYWNoIGNoYXJhY3Rlci4gIElmIGtlcm5pbmcgaXMgZW5hYmxlZCwgdGhlIDxjb2RlPnRyYWNraW5nUmlnaHQ8L2NvZGU+IHZhbHVlIGlzIGFkZGVkIHRvIHRoZSB2YWx1ZXMgaW4gdGhlIGtlcm5pbmcgdGFibGUgZm9yIHRoZSBmb250LiBJZiBrZXJuaW5nIGlzIGRpc2FibGVkLCB0aGUgPGNvZGU+dHJhY2tpbmdSaWdodDwvY29kZT4gdmFsdWUgaXMgdXNlZCBhcyBhIG1hbnVhbCBrZXJuaW5nIHZhbHVlLiBTdXBwb3J0cyBib3RoIHBvc2l0aXZlIGFuZCBuZWdhdGl2ZSB2YWx1ZXMuIAoJCSAqIDxwPkxlZ2FsIHZhbHVlcyBhcyBhIG51bWJlciBhcmUgZnJvbSAtMTAwMCB0byAxMDAwLjwvcD4KCQkgKiA8cD5MZWdhbCB2YWx1ZXMgYXMgYSBwZXJjZW50IGFyZSBudW1iZXJzIGZyb20gLTEwMDAlIHRvIDEwMDAlLjwvcD4KCQkgKiA8cD5MZWdhbCB2YWx1ZXMgaW5jbHVkZSBGb3JtYXRWYWx1ZS5JTkhFUklULjwvcD4KCQkgKiA8cD5EZWZhdWx0IHZhbHVlIGlzIHVuZGVmaW5lZCBpbmRpY2F0aW5nIG5vdCBzZXQuPC9wPgoJCSAqIDxwPklmIHVuZGVmaW5lZCBkdXJpbmcgdGhlIGNhc2NhZGUgdGhpcyBwcm9wZXJ0eSB3aWxsIGluaGVyaXQgaXRzIHZhbHVlIGZyb20gYW4gYW5jZXN0b3IuIElmIG5vIGFuY2VzdG9yIGhhcyBzZXQgdGhpcyBwcm9wZXJ0eSwgaXQgd2lsbCBoYXZlIGEgdmFsdWUgb2YgMC48L3A+CgkJICogCgkJICogQHRocm93cyBSYW5nZUVycm9yIHdoZW4gc2V0IHZhbHVlIGlzIG5vdCB3aXRoaW4gcmFuZ2UgZm9yIHRoaXMgcHJvcGVydHkKCQkgKiAKCQkgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKCQkgKiBAbGFuZ3ZlcnNpb24gMy4wCgkJICovCgkJcHVibGljIGZ1bmN0aW9uIGdldCB0cmFja2luZ1JpZ2h0KCk6KgoJCXsgcmV0dXJuIF9zdHlsZXMudHJhY2tpbmdSaWdodDsgfQoJCXB1YmxpYyBmdW5jdGlvbiBzZXQgdHJhY2tpbmdSaWdodCh2YWx1ZToqKTp2b2lkCgkJeyBzZXRTdHlsZUJ5UHJvcGVydHkoVGV4dExheW91dEZvcm1hdC50cmFja2luZ1JpZ2h0UHJvcGVydHksdmFsdWUpOyB9CgoJCS8qKgoJCSAqIExlYWRpbmcgY29udHJvbHMgZm9yIHRoZSB0ZXh0LiBUaGUgZGlzdGFuY2UgZnJvbSB0aGUgYmFzZWxpbmUgb2YgdGhlIHByZXZpb3VzIG9yIHRoZSBuZXh0IGxpbmUgKGJhc2VkIG9uIDxjb2RlPkxlYWRpbmdNb2RlbDwvY29kZT4pIHRvIHRoZSBiYXNlbGluZSBvZiB0aGUgY3VycmVudCBsaW5lIGlzIGVxdWFsIHRvIHRoZSBtYXhpbXVtIGFtb3VudCBvZiB0aGUgbGVhZGluZyBhcHBsaWVkIHRvIGFueSBjaGFyYWN0ZXIgaW4gdGhlIGxpbmUuIFRoaXMgaXMgZWl0aGVyIGEgbnVtYmVyIG9yIGEgcGVyY2VudC4gIElmIHNwZWNpZnlpbmcgYSBwZXJjZW50LCBlbnRlciBhIHN0cmluZyB2YWx1ZSwgbGlrZSAxNDAlLjxwPjxpbWcgc3JjPScuLi8uLi8uLi9pbWFnZXMvdGV4dExheW91dF9saW5lSGVpZ2h0MS5qcGcnIGFsdD0nbGluZUhlaWdodDEnIC8+PGltZyBzcmM9Jy4uLy4uLy4uL2ltYWdlcy90ZXh0TGF5b3V0X2xpbmVIZWlnaHQyLmpwZycgYWx0PSdsaW5lSGVpZ2h0MicgLz48L3A+CgkJICogPHA+TGVnYWwgdmFsdWVzIGFzIGEgbnVtYmVyIGFyZSBmcm9tIC03MjAgdG8gNzIwLjwvcD4KCQkgKiA8cD5MZWdhbCB2YWx1ZXMgYXMgYSBwZXJjZW50IGFyZSBudW1iZXJzIGZyb20gLTEwMDAlIHRvIDEwMDAlLjwvcD4KCQkgKiA8cD5MZWdhbCB2YWx1ZXMgaW5jbHVkZSBGb3JtYXRWYWx1ZS5JTkhFUklULjwvcD4KCQkgKiA8cD5EZWZhdWx0IHZhbHVlIGlzIHVuZGVmaW5lZCBpbmRpY2F0aW5nIG5vdCBzZXQuPC9wPgoJCSAqIDxwPklmIHVuZGVmaW5lZCBkdXJpbmcgdGhlIGNhc2NhZGUgdGhpcyBwcm9wZXJ0eSB3aWxsIGluaGVyaXQgaXRzIHZhbHVlIGZyb20gYW4gYW5jZXN0b3IuIElmIG5vIGFuY2VzdG9yIGhhcyBzZXQgdGhpcyBwcm9wZXJ0eSwgaXQgd2lsbCBoYXZlIGEgdmFsdWUgb2YgMTIwJS48L3A+CgkJICogCgkJICogQHRocm93cyBSYW5nZUVycm9yIHdoZW4gc2V0IHZhbHVlIGlzIG5vdCB3aXRoaW4gcmFuZ2UgZm9yIHRoaXMgcHJvcGVydHkKCQkgKiAKCQkgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKCQkgKiBAbGFuZ3ZlcnNpb24gMy4wCgkJICovCgkJcHVibGljIGZ1bmN0aW9uIGdldCBsaW5lSGVpZ2h0KCk6KgoJCXsgcmV0dXJuIF9zdHlsZXMubGluZUhlaWdodDsgfQoJCXB1YmxpYyBmdW5jdGlvbiBzZXQgbGluZUhlaWdodCh2YWx1ZToqKTp2b2lkCgkJeyBzZXRTdHlsZUJ5UHJvcGVydHkoVGV4dExheW91dEZvcm1hdC5saW5lSGVpZ2h0UHJvcGVydHksdmFsdWUpOyB9CgoJCVtJbnNwZWN0YWJsZShlbnVtZXJhdGlvbj0iYWxsLGFueSxhdXRvLG5vbmUsaW5oZXJpdCIpXQoJCS8qKgoJCSAqIENvbnRyb2xzIHdoZXJlIGxpbmVzIGFyZSBhbGxvd2VkIHRvIGJyZWFrIHdoZW4gYnJlYWtpbmcgd3JhcHBpbmcgdGV4dCBpbnRvIG11bHRpcGxlIGxpbmVzLiBTZXQgdG8gPGNvZGU+QnJlYWtPcHBvcnR1bml0eS5BVVRPPC9jb2RlPiB0byBicmVhayB0ZXh0IG5vcm1hbGx5LiBTZXQgdG8gPGNvZGU+QnJlYWtPcHBvcnR1bml0eS5OT05FPC9jb2RlPiB0byA8ZW0+bm90PC9lbT4gYnJlYWsgdGhlIHRleHQgdW5sZXNzIHRoZSB0ZXh0IHdvdWxkIG92ZXJydW4gdGhlIG1lYXN1cmUgYW5kIHRoZXJlIGFyZSBubyBvdGhlciBwbGFjZXMgdG8gYnJlYWsgdGhlIGxpbmUuIFNldCB0byA8Y29kZT5CcmVha09wcG9ydHVuaXR5LkFOWTwvY29kZT4gdG8gYWxsb3cgdGhlIGxpbmUgdG8gYnJlYWsgYW55d2hlcmUsIHJhdGhlciB0aGFuIGp1c3QgYmV0d2VlbiB3b3Jkcy4gU2V0IHRvIDxjb2RlPkJyZWFrT3Bwb3J0dW5pdHkuQUxMPC9jb2RlPiB0byBoYXZlIGVhY2ggdHlwb2dyYXBoaWMgY2x1c3RlciBwdXQgb24gYSBzZXBhcmF0ZSBsaW5lICh1c2VmdWwgZm9yIHRleHQgb24gYSBwYXRoKS4KCQkgKiA8cD5MZWdhbCB2YWx1ZXMgYXJlIEJyZWFrT3Bwb3J0dW5pdHkuQUxMLCBCcmVha09wcG9ydHVuaXR5LkFOWSwgQnJlYWtPcHBvcnR1bml0eS5BVVRPLCBCcmVha09wcG9ydHVuaXR5Lk5PTkUsIEZvcm1hdFZhbHVlLklOSEVSSVQuPC9wPgoJCSAqIDxwPkRlZmF1bHQgdmFsdWUgaXMgdW5kZWZpbmVkIGluZGljYXRpbmcgbm90IHNldC48L3A+CgkJICogPHA+SWYgdW5kZWZpbmVkIGR1cmluZyB0aGUgY2FzY2FkZSB0aGlzIHByb3BlcnR5IHdpbGwgaW5oZXJpdCBpdHMgdmFsdWUgZnJvbSBhbiBhbmNlc3Rvci4gSWYgbm8gYW5jZXN0b3IgaGFzIHNldCB0aGlzIHByb3BlcnR5LCBpdCB3aWxsIGhhdmUgYSB2YWx1ZSBvZiBCcmVha09wcG9ydHVuaXR5LkFVVE8uPC9wPgoJCSAqIAoJCSAqIEB0aHJvd3MgUmFuZ2VFcnJvciB3aGVuIHNldCB2YWx1ZSBpcyBub3Qgd2l0aGluIHJhbmdlIGZvciB0aGlzIHByb3BlcnR5CgkJICogCgkJICogQHBsYXllcnZlcnNpb24gRmxhc2ggMTAKCQkgKiBAcGxheWVydmVyc2lvbiBBSVIgMS41CgkJICogQGxhbmd2ZXJzaW9uIDMuMAoJCSAqIEBzZWUgZmxhc2gudGV4dC5lbmdpbmUuQnJlYWtPcHBvcnR1bml0eQoJCSAqLwoJCXB1YmxpYyBmdW5jdGlvbiBnZXQgYnJlYWtPcHBvcnR1bml0eSgpOioKCQl7IHJldHVybiBfc3R5bGVzLmJyZWFrT3Bwb3J0dW5pdHk7IH0KCQlwdWJsaWMgZnVuY3Rpb24gc2V0IGJyZWFrT3Bwb3J0dW5pdHkodmFsdWU6Kik6dm9pZAoJCXsgc2V0U3R5bGVCeVByb3BlcnR5KFRleHRMYXlvdXRGb3JtYXQuYnJlYWtPcHBvcnR1bml0eVByb3BlcnR5LHZhbHVlKTsgfQoKCQlbSW5zcGVjdGFibGUoZW51bWVyYXRpb249ImRlZmF1bHQsbGluaW5nLG9sZFN0eWxlLGluaGVyaXQiKV0KCQkvKioKCQkgKiBUaGUgdHlwZSBvZiBkaWdpdCBjYXNlIHVzZWQgZm9yIHRoaXMgdGV4dC4gU2V0dGluZyB0aGUgdmFsdWUgdG8gPGNvZGU+RGlnaXRDYXNlLk9MRF9TVFlMRTwvY29kZT4gYXBwcm94aW1hdGVzIGxvd2VyY2FzZSBsZXR0ZXJmb3JtcyB3aXRoIHZhcnlpbmcgYXNjZW5kZXJzIGFuZCBkZXNjZW5kZXJzLiBUaGUgZmlndXJlcyBhcmUgcHJvcG9ydGlvbmFsbHkgc3BhY2VkLiBUaGlzIHN0eWxlIGlzIG9ubHkgYXZhaWxhYmxlIGluIHNlbGVjdGVkIHR5cGVmYWNlcywgbW9zdCBjb21tb25seSBpbiBhIHN1cHBsZW1lbnRhbCBvciBleHBlcnQgZm9udC4gVGhlIDxjb2RlPkRpZ2l0Q2FzZS5MSU5JTkc8L2NvZGU+IHNldHRpbmcgaGFzIGFsbC1jYXAgaGVpZ2h0IGFuZCBpcyB0eXBpY2FsbHkgbW9ub3NwYWNlZCB0byBsaW5lIHVwIGluIGNoYXJ0cy48cD48aW1nIHNyYz0nLi4vLi4vLi4vaW1hZ2VzL3RleHRMYXlvdXRfZGlnaXRjYXNlLmdpZicgYWx0PSdkaWdpdENhc2UnIC8+PC9wPgoJCSAqIDxwPkxlZ2FsIHZhbHVlcyBhcmUgRGlnaXRDYXNlLkRFRkFVTFQsIERpZ2l0Q2FzZS5MSU5JTkcsIERpZ2l0Q2FzZS5PTERfU1RZTEUsIEZvcm1hdFZhbHVlLklOSEVSSVQuPC9wPgoJCSAqIDxwPkRlZmF1bHQgdmFsdWUgaXMgdW5kZWZpbmVkIGluZGljYXRpbmcgbm90IHNldC48L3A+CgkJICogPHA+SWYgdW5kZWZpbmVkIGR1cmluZyB0aGUgY2FzY2FkZSB0aGlzIHByb3BlcnR5IHdpbGwgaW5oZXJpdCBpdHMgdmFsdWUgZnJvbSBhbiBhbmNlc3Rvci4gSWYgbm8gYW5jZXN0b3IgaGFzIHNldCB0aGlzIHByb3BlcnR5LCBpdCB3aWxsIGhhdmUgYSB2YWx1ZSBvZiBEaWdpdENhc2UuREVGQVVMVC48L3A+CgkJICogCgkJICogQHRocm93cyBSYW5nZUVycm9yIHdoZW4gc2V0IHZhbHVlIGlzIG5vdCB3aXRoaW4gcmFuZ2UgZm9yIHRoaXMgcHJvcGVydHkKCQkgKiAKCQkgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKCQkgKiBAbGFuZ3ZlcnNpb24gMy4wCgkJICogQHNlZSBmbGFzaC50ZXh0LmVuZ2luZS5EaWdpdENhc2UKCQkgKi8KCQlwdWJsaWMgZnVuY3Rpb24gZ2V0IGRpZ2l0Q2FzZSgpOioKCQl7IHJldHVybiBfc3R5bGVzLmRpZ2l0Q2FzZTsgfQoJCXB1YmxpYyBmdW5jdGlvbiBzZXQgZGlnaXRDYXNlKHZhbHVlOiopOnZvaWQKCQl7IHNldFN0eWxlQnlQcm9wZXJ0eShUZXh0TGF5b3V0Rm9ybWF0LmRpZ2l0Q2FzZVByb3BlcnR5LHZhbHVlKTsgfQoKCQlbSW5zcGVjdGFibGUoZW51bWVyYXRpb249ImRlZmF1bHQscHJvcG9ydGlvbmFsLHRhYnVsYXIsaW5oZXJpdCIpXQoJCS8qKgoJCSAqIFR5cGUgb2YgZGlnaXQgd2lkdGggdXNlZCBmb3IgdGhpcyB0ZXh0LiBUaGlzIGNhbiBiZSA8Y29kZT5EaWdpdFdpZHRoLlBST1BPUlRJT05BTDwvY29kZT4sIHdoaWNoIGxvb2tzIGJlc3QgZm9yIGluZGl2aWR1YWwgbnVtYmVycywgb3IgPGNvZGU+RGlnaXRXaWR0aC5UQUJVTEFSPC9jb2RlPiwgd2hpY2ggd29ya3MgYmVzdCBmb3IgbnVtYmVycyBpbiB0YWJsZXMsIGNoYXJ0cywgYW5kIHZlcnRpY2FsIHJvd3MuPHA+PGltZyBzcmM9Jy4uLy4uLy4uL2ltYWdlcy90ZXh0TGF5b3V0X2RpZ2l0d2lkdGguZ2lmJyBhbHQ9J2RpZ2l0V2lkdGgnIC8+PC9wPgoJCSAqIDxwPkxlZ2FsIHZhbHVlcyBhcmUgRGlnaXRXaWR0aC5ERUZBVUxULCBEaWdpdFdpZHRoLlBST1BPUlRJT05BTCwgRGlnaXRXaWR0aC5UQUJVTEFSLCBGb3JtYXRWYWx1ZS5JTkhFUklULjwvcD4KCQkgKiA8cD5EZWZhdWx0IHZhbHVlIGlzIHVuZGVmaW5lZCBpbmRpY2F0aW5nIG5vdCBzZXQuPC9wPgoJCSAqIDxwPklmIHVuZGVmaW5lZCBkdXJpbmcgdGhlIGNhc2NhZGUgdGhpcyBwcm9wZXJ0eSB3aWxsIGluaGVyaXQgaXRzIHZhbHVlIGZyb20gYW4gYW5jZXN0b3IuIElmIG5vIGFuY2VzdG9yIGhhcyBzZXQgdGhpcyBwcm9wZXJ0eSwgaXQgd2lsbCBoYXZlIGEgdmFsdWUgb2YgRGlnaXRXaWR0aC5ERUZBVUxULjwvcD4KCQkgKiAKCQkgKiBAdGhyb3dzIFJhbmdlRXJyb3Igd2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eQoJCSAqIAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCgkJICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQoJCSAqIEBsYW5ndmVyc2lvbiAzLjAKCQkgKiBAc2VlIGZsYXNoLnRleHQuZW5naW5lLkRpZ2l0V2lkdGgKCQkgKi8KCQlwdWJsaWMgZnVuY3Rpb24gZ2V0IGRpZ2l0V2lkdGgoKToqCgkJeyByZXR1cm4gX3N0eWxlcy5kaWdpdFdpZHRoOyB9CgkJcHVibGljIGZ1bmN0aW9uIHNldCBkaWdpdFdpZHRoKHZhbHVlOiopOnZvaWQKCQl7IHNldFN0eWxlQnlQcm9wZXJ0eShUZXh0TGF5b3V0Rm9ybWF0LmRpZ2l0V2lkdGhQcm9wZXJ0eSx2YWx1ZSk7IH0KCgkJW0luc3BlY3RhYmxlKGVudW1lcmF0aW9uPSJhdXRvLHJvbWFuLGFzY2VudCxkZXNjZW50LGlkZW9ncmFwaGljVG9wLGlkZW9ncmFwaGljQ2VudGVyLGlkZW9ncmFwaGljQm90dG9tLGluaGVyaXQiKV0KCQkvKioKCQkgKiBTcGVjaWZpZXMgd2hpY2ggZWxlbWVudCBiYXNlbGluZSBzbmFwcyB0byB0aGUgPGNvZGU+YWxpZ25tZW50QmFzZWxpbmU8L2NvZGU+IHRvIGRldGVybWluZSB0aGUgdmVydGljYWwgcG9zaXRpb24gb2YgdGhlIGVsZW1lbnQgb24gdGhlIGxpbmUuIEEgdmFsdWUgb2YgPGNvZGU+VGV4dEJhc2VsaW5lLkFVVE88L2NvZGU+IHNlbGVjdHMgdGhlIGRvbWluYW50IGJhc2VsaW5lIGJhc2VkIG9uIHRoZSA8Y29kZT5sb2NhbGU8L2NvZGU+IHByb3BlcnR5IG9mIHRoZSBwYXJlbnQgcGFyYWdyYXBoLiAgRm9yIEphcGFuZXNlIGFuZCBDaGluZXNlLCB0aGUgc2VsZWN0ZWQgYmFzZWxpbmUgdmFsdWUgaXMgPGNvZGU+VGV4dEJhc2VsaW5lLklERU9HUkFQSElDX0NFTlRFUjwvY29kZT47IGZvciBhbGwgb3RoZXJzIGl0IGlzIDxjb2RlPlRleHRCYXNlbGluZS5ST01BTjwvY29kZT4uIFRoZXNlIGJhc2VsaW5lIGNob2ljZXMgYXJlIGRldGVybWluZWQgYnkgdGhlIGNob2ljZSBvZiBmb250IGFuZCB0aGUgZm9udCBzaXplLjxwPjxpbWcgc3JjPScuLi8uLi8uLi9pbWFnZXMvdGV4dExheW91dF9iYXNlbGluZXMuanBnJyBhbHQ9J2Jhc2VsaW5lcycgLz48L3A+CgkJICogPHA+TGVnYWwgdmFsdWVzIGFyZSBGb3JtYXRWYWx1ZS5BVVRPLCBUZXh0QmFzZWxpbmUuUk9NQU4sIFRleHRCYXNlbGluZS5BU0NFTlQsIFRleHRCYXNlbGluZS5ERVNDRU5ULCBUZXh0QmFzZWxpbmUuSURFT0dSQVBISUNfVE9QLCBUZXh0QmFzZWxpbmUuSURFT0dSQVBISUNfQ0VOVEVSLCBUZXh0QmFzZWxpbmUuSURFT0dSQVBISUNfQk9UVE9NLCBGb3JtYXRWYWx1ZS5JTkhFUklULjwvcD4KCQkgKiA8cD5EZWZhdWx0IHZhbHVlIGlzIHVuZGVmaW5lZCBpbmRpY2F0aW5nIG5vdCBzZXQuPC9wPgoJCSAqIDxwPklmIHVuZGVmaW5lZCBkdXJpbmcgdGhlIGNhc2NhZGUgdGhpcyBwcm9wZXJ0eSB3aWxsIGluaGVyaXQgaXRzIHZhbHVlIGZyb20gYW4gYW5jZXN0b3IuIElmIG5vIGFuY2VzdG9yIGhhcyBzZXQgdGhpcyBwcm9wZXJ0eSwgaXQgd2lsbCBoYXZlIGEgdmFsdWUgb2YgRm9ybWF0VmFsdWUuQVVUTy48L3A+CgkJICogCgkJICogQHRocm93cyBSYW5nZUVycm9yIHdoZW4gc2V0IHZhbHVlIGlzIG5vdCB3aXRoaW4gcmFuZ2UgZm9yIHRoaXMgcHJvcGVydHkKCQkgKiAKCQkgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKCQkgKiBAbGFuZ3ZlcnNpb24gMy4wCgkJICogQHNlZSBmbGFzaC50ZXh0LmVuZ2luZS5UZXh0QmFzZWxpbmUKCQkgKi8KCQlwdWJsaWMgZnVuY3Rpb24gZ2V0IGRvbWluYW50QmFzZWxpbmUoKToqCgkJeyByZXR1cm4gX3N0eWxlcy5kb21pbmFudEJhc2VsaW5lOyB9CgkJcHVibGljIGZ1bmN0aW9uIHNldCBkb21pbmFudEJhc2VsaW5lKHZhbHVlOiopOnZvaWQKCQl7IHNldFN0eWxlQnlQcm9wZXJ0eShUZXh0TGF5b3V0Rm9ybWF0LmRvbWluYW50QmFzZWxpbmVQcm9wZXJ0eSx2YWx1ZSk7IH0KCgkJW0luc3BlY3RhYmxlKGVudW1lcmF0aW9uPSJvbixvZmYsYXV0byxpbmhlcml0IildCgkJLyoqCgkJICogS2VybmluZyBhZGp1c3RzIHRoZSBwaXhlbHMgYmV0d2VlbiBjZXJ0YWluIGNoYXJhY3RlciBwYWlycyB0byBpbXByb3ZlIHJlYWRhYmlsaXR5LiBLZXJuaW5nIGlzIHN1cHBvcnRlZCBmb3IgYWxsIGZvbnRzIHdpdGgga2VybmluZyB0YWJsZXMuCgkJICogPHA+TGVnYWwgdmFsdWVzIGFyZSBLZXJuaW5nLk9OLCBLZXJuaW5nLk9GRiwgS2VybmluZy5BVVRPLCBGb3JtYXRWYWx1ZS5JTkhFUklULjwvcD4KCQkgKiA8cD5EZWZhdWx0IHZhbHVlIGlzIHVuZGVmaW5lZCBpbmRpY2F0aW5nIG5vdCBzZXQuPC9wPgoJCSAqIDxwPklmIHVuZGVmaW5lZCBkdXJpbmcgdGhlIGNhc2NhZGUgdGhpcyBwcm9wZXJ0eSB3aWxsIGluaGVyaXQgaXRzIHZhbHVlIGZyb20gYW4gYW5jZXN0b3IuIElmIG5vIGFuY2VzdG9yIGhhcyBzZXQgdGhpcyBwcm9wZXJ0eSwgaXQgd2lsbCBoYXZlIGEgdmFsdWUgb2YgS2VybmluZy5BVVRPLjwvcD4KCQkgKiAKCQkgKiBAdGhyb3dzIFJhbmdlRXJyb3Igd2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eQoJCSAqIAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCgkJICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQoJCSAqIEBsYW5ndmVyc2lvbiAzLjAKCQkgKiBAc2VlIGZsYXNoLnRleHQuZW5naW5lLktlcm5pbmcKCQkgKi8KCQlwdWJsaWMgZnVuY3Rpb24gZ2V0IGtlcm5pbmcoKToqCgkJeyByZXR1cm4gX3N0eWxlcy5rZXJuaW5nOyB9CgkJcHVibGljIGZ1bmN0aW9uIHNldCBrZXJuaW5nKHZhbHVlOiopOnZvaWQKCQl7IHNldFN0eWxlQnlQcm9wZXJ0eShUZXh0TGF5b3V0Rm9ybWF0Lmtlcm5pbmdQcm9wZXJ0eSx2YWx1ZSk7IH0KCgkJW0luc3BlY3RhYmxlKGVudW1lcmF0aW9uPSJtaW5pbXVtLGNvbW1vbix1bmNvbW1vbixleG90aWMsaW5oZXJpdCIpXQoJCS8qKgoJCSAqIENvbnRyb2xzIHdoaWNoIG9mIHRoZSBsaWdhdHVyZXMgdGhhdCBhcmUgZGVmaW5lZCBpbiB0aGUgZm9udCBtYXkgYmUgdXNlZCBpbiB0aGUgdGV4dC4gVGhlIGxpZ2F0dXJlcyB0aGF0IGFwcGVhciBmb3IgZWFjaCBvZiB0aGVzZSBzZXR0aW5ncyBpcyBkZXBlbmRlbnQgb24gdGhlIGZvbnQuIEEgbGlnYXR1cmUgb2NjdXJzIHdoZXJlIHR3byBvciBtb3JlIGxldHRlci1mb3JtcyBhcmUgam9pbmVkIGFzIGEgc2luZ2xlIGdseXBoLiBMaWdhdHVyZXMgdXN1YWxseSByZXBsYWNlIGNvbnNlY3V0aXZlIGNoYXJhY3RlcnMgc2hhcmluZyBjb21tb24gY29tcG9uZW50cywgc3VjaCBhcyB0aGUgbGV0dGVyIHBhaXJzICdmaScsICdmbCcsIG9yICdhZScuIFRoZXkgYXJlIHVzZWQgd2l0aCBib3RoIExhdGluIGFuZCBOb24tTGF0aW4gY2hhcmFjdGVyIHNldHMuIFRoZSBsaWdhdHVyZXMgZW5hYmxlZCBieSB0aGUgdmFsdWVzIG9mIHRoZSBMaWdhdHVyZUxldmVsIGNsYXNzIC0gPGNvZGU+TUlOSU1VTTwvY29kZT4sIDxjb2RlPkNPTU1PTjwvY29kZT4sIDxjb2RlPlVOQ09NTU9OPC9jb2RlPiwgYW5kIDxjb2RlPkVYT1RJQzwvY29kZT4gLSBhcmUgYWRkaXRpdmUuIEVhY2ggdmFsdWUgZW5hYmxlcyBhIG5ldyBzZXQgb2YgbGlnYXR1cmVzLCBidXQgYWxzbyBpbmNsdWRlcyB0aG9zZSBvZiB0aGUgcHJldmlvdXMgdHlwZXMuPHA+PGI+Tm90ZTogPC9iPldoZW4gd29ya2luZyB3aXRoIEFyYWJpYyBvciBTeXJpYWMgZm9udHMsIDxjb2RlPmxpZ2F0dXJlTGV2ZWw8L2NvZGU+IG11c3QgYmUgc2V0IHRvIE1JTklNVU0gb3IgYWJvdmUuPC9wPjxwPjxpbWcgc3JjPScuLi8uLi8uLi9pbWFnZXMvdGV4dExheW91dF9saWdhdHVyZXMucG5nJyBhbHQ9J2xpZ2F0dXJlTGV2ZWwnIC8+PC9wPgoJCSAqIDxwPkxlZ2FsIHZhbHVlcyBhcmUgTGlnYXR1cmVMZXZlbC5NSU5JTVVNLCBMaWdhdHVyZUxldmVsLkNPTU1PTiwgTGlnYXR1cmVMZXZlbC5VTkNPTU1PTiwgTGlnYXR1cmVMZXZlbC5FWE9USUMsIEZvcm1hdFZhbHVlLklOSEVSSVQuPC9wPgoJCSAqIDxwPkRlZmF1bHQgdmFsdWUgaXMgdW5kZWZpbmVkIGluZGljYXRpbmcgbm90IHNldC48L3A+CgkJICogPHA+SWYgdW5kZWZpbmVkIGR1cmluZyB0aGUgY2FzY2FkZSB0aGlzIHByb3BlcnR5IHdpbGwgaW5oZXJpdCBpdHMgdmFsdWUgZnJvbSBhbiBhbmNlc3Rvci4gSWYgbm8gYW5jZXN0b3IgaGFzIHNldCB0aGlzIHByb3BlcnR5LCBpdCB3aWxsIGhhdmUgYSB2YWx1ZSBvZiBMaWdhdHVyZUxldmVsLkNPTU1PTi48L3A+CgkJICogCgkJICogQHRocm93cyBSYW5nZUVycm9yIHdoZW4gc2V0IHZhbHVlIGlzIG5vdCB3aXRoaW4gcmFuZ2UgZm9yIHRoaXMgcHJvcGVydHkKCQkgKiAKCQkgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKCQkgKiBAbGFuZ3ZlcnNpb24gMy4wCgkJICogQHNlZSBmbGFzaC50ZXh0LmVuZ2luZS5MaWdhdHVyZUxldmVsCgkJICovCgkJcHVibGljIGZ1bmN0aW9uIGdldCBsaWdhdHVyZUxldmVsKCk6KgoJCXsgcmV0dXJuIF9zdHlsZXMubGlnYXR1cmVMZXZlbDsgfQoJCXB1YmxpYyBmdW5jdGlvbiBzZXQgbGlnYXR1cmVMZXZlbCh2YWx1ZToqKTp2b2lkCgkJeyBzZXRTdHlsZUJ5UHJvcGVydHkoVGV4dExheW91dEZvcm1hdC5saWdhdHVyZUxldmVsUHJvcGVydHksdmFsdWUpOyB9CgoJCVtJbnNwZWN0YWJsZShlbnVtZXJhdGlvbj0icm9tYW4sYXNjZW50LGRlc2NlbnQsaWRlb2dyYXBoaWNUb3AsaWRlb2dyYXBoaWNDZW50ZXIsaWRlb2dyYXBoaWNCb3R0b20sdXNlRG9taW5hbnRCYXNlbGluZSxpbmhlcml0IildCgkJLyoqCgkJICogU3BlY2lmaWVzIHRoZSBiYXNlbGluZSB0byB3aGljaCB0aGUgZG9taW5hbnQgYmFzZWxpbmUgYWxpZ25zLiBGb3IgZXhhbXBsZSwgaWYgeW91IHNldCA8Y29kZT5kb21pbmFudEJhc2VsaW5lPC9jb2RlPiB0byBBU0NFTlQsIHNldHRpbmcgPGNvZGU+YWxpZ25tZW50QmFzZWxpbmU8L2NvZGU+IHRvIERFU0NFTlQgYWxpZ25zIHRoZSB0b3Agb2YgdGhlIHRleHQgd2l0aCB0aGUgREVTQ0VOVCBiYXNlbGluZSwgb3IgYmVsb3cgdGhlIGxpbmUuICBUaGUgbGFyZ2VzdCBlbGVtZW50IGluIHRoZSBsaW5lIGdlbmVyYWxseSBkZXRlcm1pbmVzIHRoZSBiYXNlbGluZXMuPHA+PGltZyBzcmM9Jy4uLy4uLy4uL2ltYWdlcy90ZXh0TGF5b3V0X2Jhc2VsaW5lcy5qcGcnIGFsdD0nYmFzZWxpbmVzJyAvPjwvcD4KCQkgKiA8cD5MZWdhbCB2YWx1ZXMgYXJlIFRleHRCYXNlbGluZS5ST01BTiwgVGV4dEJhc2VsaW5lLkFTQ0VOVCwgVGV4dEJhc2VsaW5lLkRFU0NFTlQsIFRleHRCYXNlbGluZS5JREVPR1JBUEhJQ19UT1AsIFRleHRCYXNlbGluZS5JREVPR1JBUEhJQ19DRU5URVIsIFRleHRCYXNlbGluZS5JREVPR1JBUEhJQ19CT1RUT00sIFRleHRCYXNlbGluZS5VU0VfRE9NSU5BTlRfQkFTRUxJTkUsIEZvcm1hdFZhbHVlLklOSEVSSVQuPC9wPgoJCSAqIDxwPkRlZmF1bHQgdmFsdWUgaXMgdW5kZWZpbmVkIGluZGljYXRpbmcgbm90IHNldC48L3A+CgkJICogPHA+SWYgdW5kZWZpbmVkIGR1cmluZyB0aGUgY2FzY2FkZSB0aGlzIHByb3BlcnR5IHdpbGwgaW5oZXJpdCBpdHMgdmFsdWUgZnJvbSBhbiBhbmNlc3Rvci4gSWYgbm8gYW5jZXN0b3IgaGFzIHNldCB0aGlzIHByb3BlcnR5LCBpdCB3aWxsIGhhdmUgYSB2YWx1ZSBvZiBUZXh0QmFzZWxpbmUuVVNFX0RPTUlOQU5UX0JBU0VMSU5FLjwvcD4KCQkgKiBAaW5jbHVkZUV4YW1wbGUgZXhhbXBsZXNcVGV4dExheW91dEZvcm1hdF9hbGlnbm1lbnRCYXNlbGluZUV4YW1wbGUuYXMgLW5vc3dmCgkJICogCgkJICogQHRocm93cyBSYW5nZUVycm9yIHdoZW4gc2V0IHZhbHVlIGlzIG5vdCB3aXRoaW4gcmFuZ2UgZm9yIHRoaXMgcHJvcGVydHkKCQkgKiAKCQkgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKCQkgKiBAbGFuZ3ZlcnNpb24gMy4wCgkJICogQHNlZSBmbGFzaC50ZXh0LmVuZ2luZS5UZXh0QmFzZWxpbmUKCQkgKi8KCQlwdWJsaWMgZnVuY3Rpb24gZ2V0IGFsaWdubWVudEJhc2VsaW5lKCk6KgoJCXsgcmV0dXJuIF9zdHlsZXMuYWxpZ25tZW50QmFzZWxpbmU7IH0KCQlwdWJsaWMgZnVuY3Rpb24gc2V0IGFsaWdubWVudEJhc2VsaW5lKHZhbHVlOiopOnZvaWQKCQl7IHNldFN0eWxlQnlQcm9wZXJ0eShUZXh0TGF5b3V0Rm9ybWF0LmFsaWdubWVudEJhc2VsaW5lUHJvcGVydHksdmFsdWUpOyB9CgoJCS8qKgoJCSAqIFRoZSBsb2NhbGUgb2YgdGhlIHRleHQuIENvbnRyb2xzIGNhc2UgdHJhbnNmb3JtYXRpb25zIGFuZCBzaGFwaW5nLiBTdGFuZGFyZCBsb2NhbGUgaWRlbnRpZmllcnMgYXMgZGVzY3JpYmVkIGluIFVuaWNvZGUgVGVjaG5pY2FsIFN0YW5kYXJkICMzNSBhcmUgdXNlZC4gRm9yIGV4YW1wbGUgZW4sIGVuX1VTIGFuZCBlbi1VUyBhcmUgYWxsIEVuZ2xpc2gsIGphIGlzIEphcGFuZXNlLiAKCQkgKiA8cD5EZWZhdWx0IHZhbHVlIGlzIHVuZGVmaW5lZCBpbmRpY2F0aW5nIG5vdCBzZXQuPC9wPgoJCSAqIDxwPklmIHVuZGVmaW5lZCBkdXJpbmcgdGhlIGNhc2NhZGUgdGhpcyBwcm9wZXJ0eSB3aWxsIGluaGVyaXQgaXRzIHZhbHVlIGZyb20gYW4gYW5jZXN0b3IuIElmIG5vIGFuY2VzdG9yIGhhcyBzZXQgdGhpcyBwcm9wZXJ0eSwgaXQgd2lsbCBoYXZlIGEgdmFsdWUgb2YgZW4uPC9wPgoJCSAqIAoJCSAqIEB0aHJvd3MgUmFuZ2VFcnJvciB3aGVuIHNldCB2YWx1ZSBpcyBub3Qgd2l0aGluIHJhbmdlIGZvciB0aGlzIHByb3BlcnR5CgkJICogCgkJICogQHBsYXllcnZlcnNpb24gRmxhc2ggMTAKCQkgKiBAcGxheWVydmVyc2lvbiBBSVIgMS41CgkJICogQGxhbmd2ZXJzaW9uIDMuMAoJCSAqLwoJCXB1YmxpYyBmdW5jdGlvbiBnZXQgbG9jYWxlKCk6KgoJCXsgcmV0dXJuIF9zdHlsZXMubG9jYWxlOyB9CgkJcHVibGljIGZ1bmN0aW9uIHNldCBsb2NhbGUodmFsdWU6Kik6dm9pZAoJCXsgc2V0U3R5bGVCeVByb3BlcnR5KFRleHRMYXlvdXRGb3JtYXQubG9jYWxlUHJvcGVydHksdmFsdWUpOyB9CgoJCVtJbnNwZWN0YWJsZShlbnVtZXJhdGlvbj0iZGVmYXVsdCxjYXBzVG9TbWFsbENhcHMsdXBwZXJjYXNlLGxvd2VyY2FzZSxsb3dlcmNhc2VUb1NtYWxsQ2Fwcyxpbmhlcml0IildCgkJLyoqCgkJICogVGhlIHR5cGUgb2YgdHlwb2dyYXBoaWMgY2FzZSB1c2VkIGZvciB0aGlzIHRleHQuIEhlcmUgYXJlIHNvbWUgZXhhbXBsZXM6PHA+PGltZyBzcmM9Jy4uLy4uLy4uL2ltYWdlcy90ZXh0TGF5b3V0X3R5cG9ncmFwaGljY2FzZS5wbmcnIGFsdD0ndHlwb2dyYXBoaWNDYXNlJyAvPjwvcD4KCQkgKiA8cD5MZWdhbCB2YWx1ZXMgYXJlIFRMRlR5cG9ncmFwaGljQ2FzZS5ERUZBVUxULCBUTEZUeXBvZ3JhcGhpY0Nhc2UuQ0FQU19UT19TTUFMTF9DQVBTLCBUTEZUeXBvZ3JhcGhpY0Nhc2UuVVBQRVJDQVNFLCBUTEZUeXBvZ3JhcGhpY0Nhc2UuTE9XRVJDQVNFLCBUTEZUeXBvZ3JhcGhpY0Nhc2UuTE9XRVJDQVNFX1RPX1NNQUxMX0NBUFMsIEZvcm1hdFZhbHVlLklOSEVSSVQuPC9wPgoJCSAqIDxwPkRlZmF1bHQgdmFsdWUgaXMgdW5kZWZpbmVkIGluZGljYXRpbmcgbm90IHNldC48L3A+CgkJICogPHA+SWYgdW5kZWZpbmVkIGR1cmluZyB0aGUgY2FzY2FkZSB0aGlzIHByb3BlcnR5IHdpbGwgaW5oZXJpdCBpdHMgdmFsdWUgZnJvbSBhbiBhbmNlc3Rvci4gSWYgbm8gYW5jZXN0b3IgaGFzIHNldCB0aGlzIHByb3BlcnR5LCBpdCB3aWxsIGhhdmUgYSB2YWx1ZSBvZiBUTEZUeXBvZ3JhcGhpY0Nhc2UuREVGQVVMVC48L3A+CgkJICogCgkJICogQHRocm93cyBSYW5nZUVycm9yIHdoZW4gc2V0IHZhbHVlIGlzIG5vdCB3aXRoaW4gcmFuZ2UgZm9yIHRoaXMgcHJvcGVydHkKCQkgKiAKCQkgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKCQkgKiBAbGFuZ3ZlcnNpb24gMy4wCgkJICogQHNlZSBmbGFzaHgudGV4dExheW91dC5mb3JtYXRzLlRMRlR5cG9ncmFwaGljQ2FzZQoJCSAqLwoJCXB1YmxpYyBmdW5jdGlvbiBnZXQgdHlwb2dyYXBoaWNDYXNlKCk6KgoJCXsgcmV0dXJuIF9zdHlsZXMudHlwb2dyYXBoaWNDYXNlOyB9CgkJcHVibGljIGZ1bmN0aW9uIHNldCB0eXBvZ3JhcGhpY0Nhc2UodmFsdWU6Kik6dm9pZAoJCXsgc2V0U3R5bGVCeVByb3BlcnR5KFRleHRMYXlvdXRGb3JtYXQudHlwb2dyYXBoaWNDYXNlUHJvcGVydHksdmFsdWUpOyB9CgoJCS8qKgoJCSAqICBUaGUgbmFtZSBvZiB0aGUgZm9udCB0byB1c2UsIG9yIGEgY29tbWEtc2VwYXJhdGVkIGxpc3Qgb2YgZm9udCBuYW1lcy4gVGhlIEZsYXNoIHJ1bnRpbWUgcmVuZGVycyB0aGUgZWxlbWVudCB3aXRoIHRoZSBmaXJzdCBhdmFpbGFibGUgZm9udCBpbiB0aGUgbGlzdC4gRm9yIGV4YW1wbGUgQXJpYWwsIEhlbHZldGljYSwgX3NhbnMgY2F1c2VzIHRoZSBwbGF5ZXIgdG8gc2VhcmNoIGZvciBBcmlhbCwgdGhlbiBIZWx2ZXRpY2EgaWYgQXJpYWwgaXMgbm90IGZvdW5kLCB0aGVuIF9zYW5zIGlmIG5laXRoZXIgaXMgZm91bmQuCgkJICogPHA+RGVmYXVsdCB2YWx1ZSBpcyB1bmRlZmluZWQgaW5kaWNhdGluZyBub3Qgc2V0LjwvcD4KCQkgKiA8cD5JZiB1bmRlZmluZWQgZHVyaW5nIHRoZSBjYXNjYWRlIHRoaXMgcHJvcGVydHkgd2lsbCBpbmhlcml0IGl0cyB2YWx1ZSBmcm9tIGFuIGFuY2VzdG9yLiBJZiBubyBhbmNlc3RvciBoYXMgc2V0IHRoaXMgcHJvcGVydHksIGl0IHdpbGwgaGF2ZSBhIHZhbHVlIG9mIEFyaWFsLjwvcD4KCQkgKiAKCQkgKiBAdGhyb3dzIFJhbmdlRXJyb3Igd2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eQoJCSAqIAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCgkJICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQoJCSAqIEBsYW5ndmVyc2lvbiAzLjAKCQkgKi8KCQlwdWJsaWMgZnVuY3Rpb24gZ2V0IGZvbnRGYW1pbHkoKToqCgkJeyByZXR1cm4gX3N0eWxlcy5mb250RmFtaWx5OyB9CgkJcHVibGljIGZ1bmN0aW9uIHNldCBmb250RmFtaWx5KHZhbHVlOiopOnZvaWQKCQl7IHNldFN0eWxlQnlQcm9wZXJ0eShUZXh0TGF5b3V0Rm9ybWF0LmZvbnRGYW1pbHlQcm9wZXJ0eSx2YWx1ZSk7IH0KCgkJW0luc3BlY3RhYmxlKGVudW1lcmF0aW9uPSJub25lLHVuZGVybGluZSxpbmhlcml0IildCgkJLyoqCgkJICogRGVjb3JhdGlvbiBvbiB0ZXh0LiBVc2UgdG8gYXBwbHkgdW5kZXJsaW5pbmc7IGRlZmF1bHQgaXMgbm9uZS4KCQkgKiA8cD5MZWdhbCB2YWx1ZXMgYXJlIFRleHREZWNvcmF0aW9uLk5PTkUsIFRleHREZWNvcmF0aW9uLlVOREVSTElORSwgRm9ybWF0VmFsdWUuSU5IRVJJVC48L3A+CgkJICogPHA+RGVmYXVsdCB2YWx1ZSBpcyB1bmRlZmluZWQgaW5kaWNhdGluZyBub3Qgc2V0LjwvcD4KCQkgKiA8cD5JZiB1bmRlZmluZWQgZHVyaW5nIHRoZSBjYXNjYWRlIHRoaXMgcHJvcGVydHkgd2lsbCBpbmhlcml0IGl0cyB2YWx1ZSBmcm9tIGFuIGFuY2VzdG9yLiBJZiBubyBhbmNlc3RvciBoYXMgc2V0IHRoaXMgcHJvcGVydHksIGl0IHdpbGwgaGF2ZSBhIHZhbHVlIG9mIFRleHREZWNvcmF0aW9uLk5PTkUuPC9wPgoJCSAqIAoJCSAqIEB0aHJvd3MgUmFuZ2VFcnJvciB3aGVuIHNldCB2YWx1ZSBpcyBub3Qgd2l0aGluIHJhbmdlIGZvciB0aGlzIHByb3BlcnR5CgkJICogCgkJICogQHBsYXllcnZlcnNpb24gRmxhc2ggMTAKCQkgKiBAcGxheWVydmVyc2lvbiBBSVIgMS41CgkJICogQGxhbmd2ZXJzaW9uIDMuMAoJCSAqIEBzZWUgZmxhc2h4LnRleHRMYXlvdXQuZm9ybWF0cy5UZXh0RGVjb3JhdGlvbgoJCSAqLwoJCXB1YmxpYyBmdW5jdGlvbiBnZXQgdGV4dERlY29yYXRpb24oKToqCgkJeyByZXR1cm4gX3N0eWxlcy50ZXh0RGVjb3JhdGlvbjsgfQoJCXB1YmxpYyBmdW5jdGlvbiBzZXQgdGV4dERlY29yYXRpb24odmFsdWU6Kik6dm9pZAoJCXsgc2V0U3R5bGVCeVByb3BlcnR5KFRleHRMYXlvdXRGb3JtYXQudGV4dERlY29yYXRpb25Qcm9wZXJ0eSx2YWx1ZSk7IH0KCgkJW0luc3BlY3RhYmxlKGVudW1lcmF0aW9uPSJub3JtYWwsYm9sZCxpbmhlcml0IildCgkJLyoqCgkJICogV2VpZ2h0IG9mIHRleHQuIE1heSBiZSA8Y29kZT5Gb250V2VpZ2h0Lk5PUk1BTDwvY29kZT4gZm9yIHVzZSBpbiBwbGFpbiB0ZXh0LCBvciA8Y29kZT5Gb250V2VpZ2h0LkJPTEQ8L2NvZGU+LiBBcHBsaWVzIG9ubHkgdG8gZGV2aWNlIGZvbnRzICg8Y29kZT5mb250TG9va3VwPC9jb2RlPiBwcm9wZXJ0eSBpcyBzZXQgdG8gZmxhc2gudGV4dC5lbmdpbmUuRm9udExvb2t1cC5ERVZJQ0UpLgoJCSAqIDxwPkxlZ2FsIHZhbHVlcyBhcmUgRm9udFdlaWdodC5OT1JNQUwsIEZvbnRXZWlnaHQuQk9MRCwgRm9ybWF0VmFsdWUuSU5IRVJJVC48L3A+CgkJICogPHA+RGVmYXVsdCB2YWx1ZSBpcyB1bmRlZmluZWQgaW5kaWNhdGluZyBub3Qgc2V0LjwvcD4KCQkgKiA8cD5JZiB1bmRlZmluZWQgZHVyaW5nIHRoZSBjYXNjYWRlIHRoaXMgcHJvcGVydHkgd2lsbCBpbmhlcml0IGl0cyB2YWx1ZSBmcm9tIGFuIGFuY2VzdG9yLiBJZiBubyBhbmNlc3RvciBoYXMgc2V0IHRoaXMgcHJvcGVydHksIGl0IHdpbGwgaGF2ZSBhIHZhbHVlIG9mIEZvbnRXZWlnaHQuTk9STUFMLjwvcD4KCQkgKiAKCQkgKiBAdGhyb3dzIFJhbmdlRXJyb3Igd2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eQoJCSAqIAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCgkJICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQoJCSAqIEBsYW5ndmVyc2lvbiAzLjAKCQkgKiBAc2VlIGZsYXNoLnRleHQuZW5naW5lLkZvbnRXZWlnaHQKCQkgKi8KCQlwdWJsaWMgZnVuY3Rpb24gZ2V0IGZvbnRXZWlnaHQoKToqCgkJeyByZXR1cm4gX3N0eWxlcy5mb250V2VpZ2h0OyB9CgkJcHVibGljIGZ1bmN0aW9uIHNldCBmb250V2VpZ2h0KHZhbHVlOiopOnZvaWQKCQl7IHNldFN0eWxlQnlQcm9wZXJ0eShUZXh0TGF5b3V0Rm9ybWF0LmZvbnRXZWlnaHRQcm9wZXJ0eSx2YWx1ZSk7IH0KCgkJW0luc3BlY3RhYmxlKGVudW1lcmF0aW9uPSJub3JtYWwsaXRhbGljLGluaGVyaXQiKV0KCQkvKioKCQkgKiBTdHlsZSBvZiB0ZXh0LiBNYXkgYmUgPGNvZGU+Rm9udFBvc3R1cmUuTk9STUFMPC9jb2RlPiwgZm9yIHVzZSBpbiBwbGFpbiB0ZXh0LCBvciA8Y29kZT5Gb250UG9zdHVyZS5JVEFMSUM8L2NvZGU+IGZvciBpdGFsaWMuIFRoaXMgcHJvcGVydHkgYXBwbGllcyBvbmx5IHRvIGRldmljZSBmb250cyAoPGNvZGU+Zm9udExvb2t1cDwvY29kZT4gcHJvcGVydHkgaXMgc2V0IHRvIGZsYXNoLnRleHQuZW5naW5lLkZvbnRMb29rdXAuREVWSUNFKS4KCQkgKiA8cD5MZWdhbCB2YWx1ZXMgYXJlIEZvbnRQb3N0dXJlLk5PUk1BTCwgRm9udFBvc3R1cmUuSVRBTElDLCBGb3JtYXRWYWx1ZS5JTkhFUklULjwvcD4KCQkgKiA8cD5EZWZhdWx0IHZhbHVlIGlzIHVuZGVmaW5lZCBpbmRpY2F0aW5nIG5vdCBzZXQuPC9wPgoJCSAqIDxwPklmIHVuZGVmaW5lZCBkdXJpbmcgdGhlIGNhc2NhZGUgdGhpcyBwcm9wZXJ0eSB3aWxsIGluaGVyaXQgaXRzIHZhbHVlIGZyb20gYW4gYW5jZXN0b3IuIElmIG5vIGFuY2VzdG9yIGhhcyBzZXQgdGhpcyBwcm9wZXJ0eSwgaXQgd2lsbCBoYXZlIGEgdmFsdWUgb2YgRm9udFBvc3R1cmUuTk9STUFMLjwvcD4KCQkgKiAKCQkgKiBAdGhyb3dzIFJhbmdlRXJyb3Igd2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eQoJCSAqIAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCgkJICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQoJCSAqIEBsYW5ndmVyc2lvbiAzLjAKCQkgKiBAc2VlIGZsYXNoLnRleHQuZW5naW5lLkZvbnRQb3N0dXJlCgkJICovCgkJcHVibGljIGZ1bmN0aW9uIGdldCBmb250U3R5bGUoKToqCgkJeyByZXR1cm4gX3N0eWxlcy5mb250U3R5bGU7IH0KCQlwdWJsaWMgZnVuY3Rpb24gc2V0IGZvbnRTdHlsZSh2YWx1ZToqKTp2b2lkCgkJeyBzZXRTdHlsZUJ5UHJvcGVydHkoVGV4dExheW91dEZvcm1hdC5mb250U3R5bGVQcm9wZXJ0eSx2YWx1ZSk7IH0KCgkJW0luc3BlY3RhYmxlKGVudW1lcmF0aW9uPSJwcmVzZXJ2ZSxjb2xsYXBzZSxpbmhlcml0IildCgkJLyoqCgkJICogQ29sbGFwc2VzIG9yIHByZXNlcnZlcyB3aGl0ZXNwYWNlIHdoZW4gaW1wb3J0aW5nIHRleHQgaW50byBhIFRleHRGbG93LiA8Y29kZT5XaGl0ZVNwYWNlQ29sbGFwc2UuUFJFU0VSVkU8L2NvZGU+IHJldGFpbnMgYWxsIHdoaXRlc3BhY2UgY2hhcmFjdGVycy4gPGNvZGU+V2hpdGVTcGFjZUNvbGxhcHNlLkNPTExBUFNFPC9jb2RlPiByZW1vdmVzIG5ld2xpbmVzLCB0YWJzLCBhbmQgbGVhZGluZyBvciB0cmFpbGluZyBzcGFjZXMgd2l0aGluIGEgYmxvY2sgb2YgaW1wb3J0ZWQgdGV4dC4gTGluZSBicmVhayB0YWdzICg8YnIvPikgYW5kIFVuaWNvZGUgbGluZSBzZXBhcmF0b3IgY2hhcmFjdGVycyBhcmUgcmV0YWluZWQuCgkJICogPHA+TGVnYWwgdmFsdWVzIGFyZSBXaGl0ZVNwYWNlQ29sbGFwc2UuUFJFU0VSVkUsIFdoaXRlU3BhY2VDb2xsYXBzZS5DT0xMQVBTRSwgRm9ybWF0VmFsdWUuSU5IRVJJVC48L3A+CgkJICogPHA+RGVmYXVsdCB2YWx1ZSBpcyB1bmRlZmluZWQgaW5kaWNhdGluZyBub3Qgc2V0LjwvcD4KCQkgKiA8cD5JZiB1bmRlZmluZWQgZHVyaW5nIHRoZSBjYXNjYWRlIHRoaXMgcHJvcGVydHkgd2lsbCBpbmhlcml0IGl0cyB2YWx1ZSBmcm9tIGFuIGFuY2VzdG9yLiBJZiBubyBhbmNlc3RvciBoYXMgc2V0IHRoaXMgcHJvcGVydHksIGl0IHdpbGwgaGF2ZSBhIHZhbHVlIG9mIFdoaXRlU3BhY2VDb2xsYXBzZS5DT0xMQVBTRS48L3A+CgkJICogCgkJICogQHRocm93cyBSYW5nZUVycm9yIHdoZW4gc2V0IHZhbHVlIGlzIG5vdCB3aXRoaW4gcmFuZ2UgZm9yIHRoaXMgcHJvcGVydHkKCQkgKiAKCQkgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKCQkgKiBAbGFuZ3ZlcnNpb24gMy4wCgkJICogQHNlZSBmbGFzaHgudGV4dExheW91dC5mb3JtYXRzLldoaXRlU3BhY2VDb2xsYXBzZQoJCSAqLwoJCXB1YmxpYyBmdW5jdGlvbiBnZXQgd2hpdGVTcGFjZUNvbGxhcHNlKCk6KgoJCXsgcmV0dXJuIF9zdHlsZXMud2hpdGVTcGFjZUNvbGxhcHNlOyB9CgkJcHVibGljIGZ1bmN0aW9uIHNldCB3aGl0ZVNwYWNlQ29sbGFwc2UodmFsdWU6Kik6dm9pZAoJCXsgc2V0U3R5bGVCeVByb3BlcnR5KFRleHRMYXlvdXRGb3JtYXQud2hpdGVTcGFjZUNvbGxhcHNlUHJvcGVydHksdmFsdWUpOyB9CgoJCVtJbnNwZWN0YWJsZShlbnVtZXJhdGlvbj0ibm9ybWFsLGNmZixpbmhlcml0IildCgkJLyoqCgkJICogVGhlIHJlbmRlcmluZyBtb2RlIHVzZWQgZm9yIHRoaXMgdGV4dC4gIEFwcGxpZXMgb25seSB0byBlbWJlZGRlZCBmb250cyAoPGNvZGU+Zm9udExvb2t1cDwvY29kZT4gcHJvcGVydHkgaXMgc2V0IHRvIDxjb2RlPkZvbnRMb29rdXAuRU1CRURERURfQ0ZGPC9jb2RlPikuCgkJICogPHA+TGVnYWwgdmFsdWVzIGFyZSBSZW5kZXJpbmdNb2RlLk5PUk1BTCwgUmVuZGVyaW5nTW9kZS5DRkYsIEZvcm1hdFZhbHVlLklOSEVSSVQuPC9wPgoJCSAqIDxwPkRlZmF1bHQgdmFsdWUgaXMgdW5kZWZpbmVkIGluZGljYXRpbmcgbm90IHNldC48L3A+CgkJICogPHA+SWYgdW5kZWZpbmVkIGR1cmluZyB0aGUgY2FzY2FkZSB0aGlzIHByb3BlcnR5IHdpbGwgaW5oZXJpdCBpdHMgdmFsdWUgZnJvbSBhbiBhbmNlc3Rvci4gSWYgbm8gYW5jZXN0b3IgaGFzIHNldCB0aGlzIHByb3BlcnR5LCBpdCB3aWxsIGhhdmUgYSB2YWx1ZSBvZiBSZW5kZXJpbmdNb2RlLkNGRi48L3A+CgkJICogCgkJICogQHRocm93cyBSYW5nZUVycm9yIHdoZW4gc2V0IHZhbHVlIGlzIG5vdCB3aXRoaW4gcmFuZ2UgZm9yIHRoaXMgcHJvcGVydHkKCQkgKiAKCQkgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKCQkgKiBAbGFuZ3ZlcnNpb24gMy4wCgkJICogQHNlZSBmbGFzaC50ZXh0LmVuZ2luZS5SZW5kZXJpbmdNb2RlCgkJICovCgkJcHVibGljIGZ1bmN0aW9uIGdldCByZW5kZXJpbmdNb2RlKCk6KgoJCXsgcmV0dXJuIF9zdHlsZXMucmVuZGVyaW5nTW9kZTsgfQoJCXB1YmxpYyBmdW5jdGlvbiBzZXQgcmVuZGVyaW5nTW9kZSh2YWx1ZToqKTp2b2lkCgkJeyBzZXRTdHlsZUJ5UHJvcGVydHkoVGV4dExheW91dEZvcm1hdC5yZW5kZXJpbmdNb2RlUHJvcGVydHksdmFsdWUpOyB9CgoJCVtJbnNwZWN0YWJsZShlbnVtZXJhdGlvbj0ibm9uZSxob3Jpem9udGFsU3RlbSxpbmhlcml0IildCgkJLyoqCgkJICogVGhlIHR5cGUgb2YgQ0ZGIGhpbnRpbmcgdXNlZCBmb3IgdGhpcyB0ZXh0LiBDRkYgaGludGluZyBkZXRlcm1pbmVzIHdoZXRoZXIgdGhlIEZsYXNoIHJ1bnRpbWUgZm9yY2VzIHN0cm9uZyBob3Jpem9udGFsIHN0ZW1zIHRvIGZpdCB0byBhIHN1YiBwaXhlbCBncmlkIG9yIG5vdC4gVGhpcyBwcm9wZXJ0eSBhcHBsaWVzIG9ubHkgaWYgdGhlIDxjb2RlPnJlbmRlcmluZ01vZGU8L2NvZGU+IHByb3BlcnR5IGlzIHNldCB0byA8Y29kZT5SZW5kZXJpbmdNb2RlLkNGRjwvY29kZT4sIGFuZCB0aGUgZm9udCBpcyBlbWJlZGRlZCAoPGNvZGU+Zm9udExvb2t1cDwvY29kZT4gcHJvcGVydHkgaXMgc2V0IHRvIDxjb2RlPkZvbnRMb29rdXAuRU1CRURERURfQ0ZGPC9jb2RlPikuIEF0IHNtYWxsIHNjcmVlbiBzaXplcywgaGludGluZyBwcm9kdWNlcyBhIGNsZWFyLCBsZWdpYmxlIHRleHQgZm9yIGh1bWFuIHJlYWRlcnMuCgkJICogPHA+TGVnYWwgdmFsdWVzIGFyZSBDRkZIaW50aW5nLk5PTkUsIENGRkhpbnRpbmcuSE9SSVpPTlRBTF9TVEVNLCBGb3JtYXRWYWx1ZS5JTkhFUklULjwvcD4KCQkgKiA8cD5EZWZhdWx0IHZhbHVlIGlzIHVuZGVmaW5lZCBpbmRpY2F0aW5nIG5vdCBzZXQuPC9wPgoJCSAqIDxwPklmIHVuZGVmaW5lZCBkdXJpbmcgdGhlIGNhc2NhZGUgdGhpcyBwcm9wZXJ0eSB3aWxsIGluaGVyaXQgaXRzIHZhbHVlIGZyb20gYW4gYW5jZXN0b3IuIElmIG5vIGFuY2VzdG9yIGhhcyBzZXQgdGhpcyBwcm9wZXJ0eSwgaXQgd2lsbCBoYXZlIGEgdmFsdWUgb2YgQ0ZGSGludGluZy5IT1JJWk9OVEFMX1NURU0uPC9wPgoJCSAqIAoJCSAqIEB0aHJvd3MgUmFuZ2VFcnJvciB3aGVuIHNldCB2YWx1ZSBpcyBub3Qgd2l0aGluIHJhbmdlIGZvciB0aGlzIHByb3BlcnR5CgkJICogCgkJICogQHBsYXllcnZlcnNpb24gRmxhc2ggMTAKCQkgKiBAcGxheWVydmVyc2lvbiBBSVIgMS41CgkJICogQGxhbmd2ZXJzaW9uIDMuMAoJCSAqIEBzZWUgZmxhc2gudGV4dC5lbmdpbmUuQ0ZGSGludGluZwoJCSAqLwoJCXB1YmxpYyBmdW5jdGlvbiBnZXQgY2ZmSGludGluZygpOioKCQl7IHJldHVybiBfc3R5bGVzLmNmZkhpbnRpbmc7IH0KCQlwdWJsaWMgZnVuY3Rpb24gc2V0IGNmZkhpbnRpbmcodmFsdWU6Kik6dm9pZAoJCXsgc2V0U3R5bGVCeVByb3BlcnR5KFRleHRMYXlvdXRGb3JtYXQuY2ZmSGludGluZ1Byb3BlcnR5LHZhbHVlKTsgfQoKCQlbSW5zcGVjdGFibGUoZW51bWVyYXRpb249ImRldmljZSxlbWJlZGRlZENGRixpbmhlcml0IildCgkJLyoqCgkJICogRm9udCBsb29rdXAgdG8gdXNlLiBTcGVjaWZ5aW5nIDxjb2RlPkZvbnRMb29rdXAuREVWSUNFPC9jb2RlPiB1c2VzIHRoZSBmb250cyBpbnN0YWxsZWQgb24gdGhlIHN5c3RlbSB0aGF0IGlzIHJ1bm5pbmcgdGhlIFNXRiBmaWxlLiBEZXZpY2UgZm9udHMgcmVzdWx0IGluIGEgc21hbGxlciBtb3ZpZSBzaXplLCBidXQgdGV4dCBpcyBub3QgYWx3YXlzIHJlbmRlcmVkIHRoZSBzYW1lIGFjcm9zcyBkaWZmZXJlbnQgc3lzdGVtcyBhbmQgcGxhdGZvcm1zLiBTcGVjaWZ5aW5nIDxjb2RlPkZvbnRMb29rdXAuRU1CRURERURfQ0ZGPC9jb2RlPiB1c2VzIGZvbnQgb3V0bGluZXMgZW1iZWRkZWQgaW4gdGhlIHB1Ymxpc2hlZCBTV0YgZmlsZS4gRW1iZWRkZWQgZm9udHMgaW5jcmVhc2UgdGhlIHNpemUgb2YgdGhlIFNXRiBmaWxlIChzb21ldGltZXMgZHJhbWF0aWNhbGx5KSwgYnV0IHRleHQgaXMgY29uc2lzdGVudGx5IGRpc3BsYXllZCBpbiB0aGUgY2hvc2VuIGZvbnQuCgkJICogPHA+TGVnYWwgdmFsdWVzIGFyZSBGb250TG9va3VwLkRFVklDRSwgRm9udExvb2t1cC5FTUJFRERFRF9DRkYsIEZvcm1hdFZhbHVlLklOSEVSSVQuPC9wPgoJCSAqIDxwPkRlZmF1bHQgdmFsdWUgaXMgdW5kZWZpbmVkIGluZGljYXRpbmcgbm90IHNldC48L3A+CgkJICogPHA+SWYgdW5kZWZpbmVkIGR1cmluZyB0aGUgY2FzY2FkZSB0aGlzIHByb3BlcnR5IHdpbGwgaW5oZXJpdCBpdHMgdmFsdWUgZnJvbSBhbiBhbmNlc3Rvci4gSWYgbm8gYW5jZXN0b3IgaGFzIHNldCB0aGlzIHByb3BlcnR5LCBpdCB3aWxsIGhhdmUgYSB2YWx1ZSBvZiBGb250TG9va3VwLkRFVklDRS48L3A+CgkJICogCgkJICogQHRocm93cyBSYW5nZUVycm9yIHdoZW4gc2V0IHZhbHVlIGlzIG5vdCB3aXRoaW4gcmFuZ2UgZm9yIHRoaXMgcHJvcGVydHkKCQkgKiAKCQkgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKCQkgKiBAbGFuZ3ZlcnNpb24gMy4wCgkJICogQHNlZSBmbGFzaC50ZXh0LmVuZ2luZS5Gb250TG9va3VwCgkJICovCgkJcHVibGljIGZ1bmN0aW9uIGdldCBmb250TG9va3VwKCk6KgoJCXsgcmV0dXJuIF9zdHlsZXMuZm9udExvb2t1cDsgfQoJCXB1YmxpYyBmdW5jdGlvbiBzZXQgZm9udExvb2t1cCh2YWx1ZToqKTp2b2lkCgkJeyBzZXRTdHlsZUJ5UHJvcGVydHkoVGV4dExheW91dEZvcm1hdC5mb250TG9va3VwUHJvcGVydHksdmFsdWUpOyB9CgoJCVtJbnNwZWN0YWJsZShlbnVtZXJhdGlvbj0icm90YXRlMCxyb3RhdGUxODAscm90YXRlMjcwLHJvdGF0ZTkwLGF1dG8saW5oZXJpdCIpXQoJCS8qKgoJCSAqIERldGVybWluZXMgdGhlIG51bWJlciBvZiBkZWdyZWVzIHRvIHJvdGF0ZSB0aGlzIHRleHQuCgkJICogPHA+TGVnYWwgdmFsdWVzIGFyZSBUZXh0Um90YXRpb24uUk9UQVRFXzAsIFRleHRSb3RhdGlvbi5ST1RBVEVfMTgwLCBUZXh0Um90YXRpb24uUk9UQVRFXzI3MCwgVGV4dFJvdGF0aW9uLlJPVEFURV85MCwgVGV4dFJvdGF0aW9uLkFVVE8sIEZvcm1hdFZhbHVlLklOSEVSSVQuPC9wPgoJCSAqIDxwPkRlZmF1bHQgdmFsdWUgaXMgdW5kZWZpbmVkIGluZGljYXRpbmcgbm90IHNldC48L3A+CgkJICogPHA+SWYgdW5kZWZpbmVkIGR1cmluZyB0aGUgY2FzY2FkZSB0aGlzIHByb3BlcnR5IHdpbGwgaW5oZXJpdCBpdHMgdmFsdWUgZnJvbSBhbiBhbmNlc3Rvci4gSWYgbm8gYW5jZXN0b3IgaGFzIHNldCB0aGlzIHByb3BlcnR5LCBpdCB3aWxsIGhhdmUgYSB2YWx1ZSBvZiBUZXh0Um90YXRpb24uQVVUTy48L3A+CgkJICogCgkJICogQHRocm93cyBSYW5nZUVycm9yIHdoZW4gc2V0IHZhbHVlIGlzIG5vdCB3aXRoaW4gcmFuZ2UgZm9yIHRoaXMgcHJvcGVydHkKCQkgKiAKCQkgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKCQkgKiBAbGFuZ3ZlcnNpb24gMy4wCgkJICogQHNlZSBmbGFzaC50ZXh0LmVuZ2luZS5UZXh0Um90YXRpb24KCQkgKi8KCQlwdWJsaWMgZnVuY3Rpb24gZ2V0IHRleHRSb3RhdGlvbigpOioKCQl7IHJldHVybiBfc3R5bGVzLnRleHRSb3RhdGlvbjsgfQoJCXB1YmxpYyBmdW5jdGlvbiBzZXQgdGV4dFJvdGF0aW9uKHZhbHVlOiopOnZvaWQKCQl7IHNldFN0eWxlQnlQcm9wZXJ0eShUZXh0TGF5b3V0Rm9ybWF0LnRleHRSb3RhdGlvblByb3BlcnR5LHZhbHVlKTsgfQoKCQkvKioKCQkgKiBBIE51bWJlciB0aGF0IHNwZWNpZmllcywgaW4gcGl4ZWxzLCB0aGUgYW1vdW50IHRvIGluZGVudCB0aGUgZmlyc3QgbGluZSBvZiB0aGUgcGFyYWdyYXBoLgoJCSAqIEEgbmVnYXRpdmUgaW5kZW50IHdpbGwgcHVzaCB0aGUgbGluZSBpbnRvIHRoZSBtYXJnaW4sIGFuZCBwb3NzaWJseSBvdXQgb2YgdGhlIGNvbnRhaW5lci4KCQkgKiA8cD5MZWdhbCB2YWx1ZXMgYXJlIG51bWJlcnMgZnJvbSAtODAwMCB0byA4MDAwIGFuZCBGb3JtYXRWYWx1ZS5JTkhFUklULjwvcD4KCQkgKiA8cD5EZWZhdWx0IHZhbHVlIGlzIHVuZGVmaW5lZCBpbmRpY2F0aW5nIG5vdCBzZXQuPC9wPgoJCSAqIDxwPklmIHVuZGVmaW5lZCBkdXJpbmcgdGhlIGNhc2NhZGUgdGhpcyBwcm9wZXJ0eSB3aWxsIGluaGVyaXQgaXRzIHZhbHVlIGZyb20gYW4gYW5jZXN0b3IuIElmIG5vIGFuY2VzdG9yIGhhcyBzZXQgdGhpcyBwcm9wZXJ0eSwgaXQgd2lsbCBoYXZlIGEgdmFsdWUgb2YgMC48L3A+CgkJICogCgkJICogQHRocm93cyBSYW5nZUVycm9yIHdoZW4gc2V0IHZhbHVlIGlzIG5vdCB3aXRoaW4gcmFuZ2UgZm9yIHRoaXMgcHJvcGVydHkKCQkgKiAKCQkgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKCQkgKiBAbGFuZ3ZlcnNpb24gMy4wCgkJICovCgkJcHVibGljIGZ1bmN0aW9uIGdldCB0ZXh0SW5kZW50KCk6KgoJCXsgcmV0dXJuIF9zdHlsZXMudGV4dEluZGVudDsgfQoJCXB1YmxpYyBmdW5jdGlvbiBzZXQgdGV4dEluZGVudCh2YWx1ZToqKTp2b2lkCgkJeyBzZXRTdHlsZUJ5UHJvcGVydHkoVGV4dExheW91dEZvcm1hdC50ZXh0SW5kZW50UHJvcGVydHksdmFsdWUpOyB9CgoJCS8qKgoJCSAqIEEgTnVtYmVyIHRoYXQgc3BlY2lmaWVzLCBpbiBwaXhlbHMsIHRoZSBhbW91bnQgdG8gaW5kZW50IHRoZSBwYXJhZ3JhcGgncyBzdGFydCBlZGdlLiBSZWZlcnMgdG8gdGhlIGxlZnQgZWRnZSBpbiBsZWZ0LXRvLXJpZ2h0IHRleHQgYW5kIHRoZSByaWdodCBlZGdlIGluIHJpZ2h0LXRvLWxlZnQgdGV4dC4gCgkJICogPHA+TGVnYWwgdmFsdWVzIGFyZSBudW1iZXJzIGZyb20gMCB0byA4MDAwIGFuZCBGb3JtYXRWYWx1ZS5JTkhFUklULjwvcD4KCQkgKiA8cD5EZWZhdWx0IHZhbHVlIGlzIHVuZGVmaW5lZCBpbmRpY2F0aW5nIG5vdCBzZXQuPC9wPgoJCSAqIDxwPklmIHVuZGVmaW5lZCBkdXJpbmcgdGhlIGNhc2NhZGUgdGhpcyBwcm9wZXJ0eSB3aWxsIGluaGVyaXQgaXRzIHZhbHVlIGZyb20gYW4gYW5jZXN0b3IuIElmIG5vIGFuY2VzdG9yIGhhcyBzZXQgdGhpcyBwcm9wZXJ0eSwgaXQgd2lsbCBoYXZlIGEgdmFsdWUgb2YgMC48L3A+CgkJICogCgkJICogQHRocm93cyBSYW5nZUVycm9yIHdoZW4gc2V0IHZhbHVlIGlzIG5vdCB3aXRoaW4gcmFuZ2UgZm9yIHRoaXMgcHJvcGVydHkKCQkgKiAKCQkgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKCQkgKiBAbGFuZ3ZlcnNpb24gMy4wCgkJICovCgkJcHVibGljIGZ1bmN0aW9uIGdldCBwYXJhZ3JhcGhTdGFydEluZGVudCgpOioKCQl7IHJldHVybiBfc3R5bGVzLnBhcmFncmFwaFN0YXJ0SW5kZW50OyB9CgkJcHVibGljIGZ1bmN0aW9uIHNldCBwYXJhZ3JhcGhTdGFydEluZGVudCh2YWx1ZToqKTp2b2lkCgkJeyBzZXRTdHlsZUJ5UHJvcGVydHkoVGV4dExheW91dEZvcm1hdC5wYXJhZ3JhcGhTdGFydEluZGVudFByb3BlcnR5LHZhbHVlKTsgfQoKCQkvKioKCQkgKiBBIE51bWJlciB0aGF0IHNwZWNpZmllcywgaW4gcGl4ZWxzLCB0aGUgYW1vdW50IHRvIGluZGVudCB0aGUgcGFyYWdyYXBoJ3MgZW5kIGVkZ2UuIFJlZmVycyB0byB0aGUgcmlnaHQgZWRnZSBpbiBsZWZ0LXRvLXJpZ2h0IHRleHQgYW5kIHRoZSBsZWZ0IGVkZ2UgaW4gcmlnaHQtdG8tbGVmdCB0ZXh0LiAKCQkgKiA8cD5MZWdhbCB2YWx1ZXMgYXJlIG51bWJlcnMgZnJvbSAwIHRvIDgwMDAgYW5kIEZvcm1hdFZhbHVlLklOSEVSSVQuPC9wPgoJCSAqIDxwPkRlZmF1bHQgdmFsdWUgaXMgdW5kZWZpbmVkIGluZGljYXRpbmcgbm90IHNldC48L3A+CgkJICogPHA+SWYgdW5kZWZpbmVkIGR1cmluZyB0aGUgY2FzY2FkZSB0aGlzIHByb3BlcnR5IHdpbGwgaW5oZXJpdCBpdHMgdmFsdWUgZnJvbSBhbiBhbmNlc3Rvci4gSWYgbm8gYW5jZXN0b3IgaGFzIHNldCB0aGlzIHByb3BlcnR5LCBpdCB3aWxsIGhhdmUgYSB2YWx1ZSBvZiAwLjwvcD4KCQkgKiAKCQkgKiBAdGhyb3dzIFJhbmdlRXJyb3Igd2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eQoJCSAqIAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCgkJICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQoJCSAqIEBsYW5ndmVyc2lvbiAzLjAKCQkgKi8KCQlwdWJsaWMgZnVuY3Rpb24gZ2V0IHBhcmFncmFwaEVuZEluZGVudCgpOioKCQl7IHJldHVybiBfc3R5bGVzLnBhcmFncmFwaEVuZEluZGVudDsgfQoJCXB1YmxpYyBmdW5jdGlvbiBzZXQgcGFyYWdyYXBoRW5kSW5kZW50KHZhbHVlOiopOnZvaWQKCQl7IHNldFN0eWxlQnlQcm9wZXJ0eShUZXh0TGF5b3V0Rm9ybWF0LnBhcmFncmFwaEVuZEluZGVudFByb3BlcnR5LHZhbHVlKTsgfQoKCQkvKioKCQkgKiBBIE51bWJlciB0aGF0IHNwZWNpZmllcyB0aGUgYW1vdW50IG9mIHNwYWNlLCBpbiBwaXhlbHMsIHRvIGxlYXZlIGJlZm9yZSB0aGUgcGFyYWdyYXBoLiAKCQkgKiBDb2xsYXBzZXMgaW4gdGFuZGVtIHdpdGggPGNvZGU+cGFyYWdyYXBoU3BhY2VBZnRlcjwvY29kZT4uCgkJICogPHA+TGVnYWwgdmFsdWVzIGFyZSBudW1iZXJzIGZyb20gMCB0byA4MDAwIGFuZCBGb3JtYXRWYWx1ZS5JTkhFUklULjwvcD4KCQkgKiA8cD5EZWZhdWx0IHZhbHVlIGlzIHVuZGVmaW5lZCBpbmRpY2F0aW5nIG5vdCBzZXQuPC9wPgoJCSAqIDxwPklmIHVuZGVmaW5lZCBkdXJpbmcgdGhlIGNhc2NhZGUgdGhpcyBwcm9wZXJ0eSB3aWxsIGluaGVyaXQgaXRzIHZhbHVlIGZyb20gYW4gYW5jZXN0b3IuIElmIG5vIGFuY2VzdG9yIGhhcyBzZXQgdGhpcyBwcm9wZXJ0eSwgaXQgd2lsbCBoYXZlIGEgdmFsdWUgb2YgMC48L3A+CgkJICogCgkJICogQHRocm93cyBSYW5nZUVycm9yIHdoZW4gc2V0IHZhbHVlIGlzIG5vdCB3aXRoaW4gcmFuZ2UgZm9yIHRoaXMgcHJvcGVydHkKCQkgKiAKCQkgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKCQkgKiBAbGFuZ3ZlcnNpb24gMy4wCgkJICovCgkJcHVibGljIGZ1bmN0aW9uIGdldCBwYXJhZ3JhcGhTcGFjZUJlZm9yZSgpOioKCQl7IHJldHVybiBfc3R5bGVzLnBhcmFncmFwaFNwYWNlQmVmb3JlOyB9CgkJcHVibGljIGZ1bmN0aW9uIHNldCBwYXJhZ3JhcGhTcGFjZUJlZm9yZSh2YWx1ZToqKTp2b2lkCgkJeyBzZXRTdHlsZUJ5UHJvcGVydHkoVGV4dExheW91dEZvcm1hdC5wYXJhZ3JhcGhTcGFjZUJlZm9yZVByb3BlcnR5LHZhbHVlKTsgfQoKCQkvKioKCQkgKiBBIE51bWJlciB0aGF0IHNwZWNpZmllcyB0aGUgYW1vdW50IG9mIHNwYWNlLCBpbiBwaXhlbHMsIHRvIGxlYXZlIGFmdGVyIHRoZSBwYXJhZ3JhcGguCgkJICogQ29sbGFwc2VzIGluIHRhbmRlbSB3aXRoICA8Y29kZT5wYXJhZ3JhcGhTcGFjZUJlZm9yZTwvY29kZT4uCgkJICogPHA+TGVnYWwgdmFsdWVzIGFyZSBudW1iZXJzIGZyb20gMCB0byA4MDAwIGFuZCBGb3JtYXRWYWx1ZS5JTkhFUklULjwvcD4KCQkgKiA8cD5EZWZhdWx0IHZhbHVlIGlzIHVuZGVmaW5lZCBpbmRpY2F0aW5nIG5vdCBzZXQuPC9wPgoJCSAqIDxwPklmIHVuZGVmaW5lZCBkdXJpbmcgdGhlIGNhc2NhZGUgdGhpcyBwcm9wZXJ0eSB3aWxsIGluaGVyaXQgaXRzIHZhbHVlIGZyb20gYW4gYW5jZXN0b3IuIElmIG5vIGFuY2VzdG9yIGhhcyBzZXQgdGhpcyBwcm9wZXJ0eSwgaXQgd2lsbCBoYXZlIGEgdmFsdWUgb2YgMC48L3A+CgkJICogCgkJICogQHRocm93cyBSYW5nZUVycm9yIHdoZW4gc2V0IHZhbHVlIGlzIG5vdCB3aXRoaW4gcmFuZ2UgZm9yIHRoaXMgcHJvcGVydHkKCQkgKiAKCQkgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKCQkgKiBAbGFuZ3ZlcnNpb24gMy4wCgkJICovCgkJcHVibGljIGZ1bmN0aW9uIGdldCBwYXJhZ3JhcGhTcGFjZUFmdGVyKCk6KgoJCXsgcmV0dXJuIF9zdHlsZXMucGFyYWdyYXBoU3BhY2VBZnRlcjsgfQoJCXB1YmxpYyBmdW5jdGlvbiBzZXQgcGFyYWdyYXBoU3BhY2VBZnRlcih2YWx1ZToqKTp2b2lkCgkJeyBzZXRTdHlsZUJ5UHJvcGVydHkoVGV4dExheW91dEZvcm1hdC5wYXJhZ3JhcGhTcGFjZUFmdGVyUHJvcGVydHksdmFsdWUpOyB9CgoJCVtJbnNwZWN0YWJsZShlbnVtZXJhdGlvbj0ibGVmdCxyaWdodCxjZW50ZXIsanVzdGlmeSxzdGFydCxlbmQsaW5oZXJpdCIpXQoJCS8qKgoJCSAqIEFsaWdubWVudCBvZiBsaW5lcyBpbiB0aGUgcGFyYWdyYXBoIHJlbGF0aXZlIHRvIHRoZSBjb250YWluZXIuCgkJICogPGNvZGU+VGV4dEFsaWduLkxFRlQ8L2NvZGU+IGFsaWducyBsaW5lcyBhbG9uZyB0aGUgbGVmdCBlZGdlIG9mIHRoZSBjb250YWluZXIuIDxjb2RlPlRleHRBbGlnbi5SSUdIVDwvY29kZT4gYWxpZ25zIG9uIHRoZSByaWdodCBlZGdlLiA8Y29kZT5UZXh0QWxpZ24uQ0VOVEVSPC9jb2RlPiBwb3NpdGlvbnMgdGhlIGxpbmUgZXF1aWRpc3RhbnQgZnJvbSB0aGUgbGVmdCBhbmQgcmlnaHQgZWRnZXMuIDxjb2RlPlRleHRBbGlnbi5KVVNUSUZZPC9jb2RlPiBzcHJlYWRzIHRoZSBsaW5lcyBvdXQgc28gdGhleSBmaWxsIHRoZSBzcGFjZS4gPGNvZGU+VGV4dEFsaWduLlNUQVJUPC9jb2RlPiBpcyBlcXVpdmFsZW50IHRvIHNldHRpbmcgbGVmdCBpbiBsZWZ0LXRvLXJpZ2h0IHRleHQsIG9yIHJpZ2h0IGluIHJpZ2h0LXRvLWxlZnQgdGV4dC4gPGNvZGU+VGV4dEFsaWduLkVORDwvY29kZT4gaXMgZXF1aXZhbGVudCB0byBzZXR0aW5nIHJpZ2h0IGluIGxlZnQtdG8tcmlnaHQgdGV4dCwgb3IgbGVmdCBpbiByaWdodC10by1sZWZ0IHRleHQuCgkJICogPHA+TGVnYWwgdmFsdWVzIGFyZSBUZXh0QWxpZ24uTEVGVCwgVGV4dEFsaWduLlJJR0hULCBUZXh0QWxpZ24uQ0VOVEVSLCBUZXh0QWxpZ24uSlVTVElGWSwgVGV4dEFsaWduLlNUQVJULCBUZXh0QWxpZ24uRU5ELCBGb3JtYXRWYWx1ZS5JTkhFUklULjwvcD4KCQkgKiA8cD5EZWZhdWx0IHZhbHVlIGlzIHVuZGVmaW5lZCBpbmRpY2F0aW5nIG5vdCBzZXQuPC9wPgoJCSAqIDxwPklmIHVuZGVmaW5lZCBkdXJpbmcgdGhlIGNhc2NhZGUgdGhpcyBwcm9wZXJ0eSB3aWxsIGluaGVyaXQgaXRzIHZhbHVlIGZyb20gYW4gYW5jZXN0b3IuIElmIG5vIGFuY2VzdG9yIGhhcyBzZXQgdGhpcyBwcm9wZXJ0eSwgaXQgd2lsbCBoYXZlIGEgdmFsdWUgb2YgVGV4dEFsaWduLlNUQVJULjwvcD4KCQkgKiAKCQkgKiBAdGhyb3dzIFJhbmdlRXJyb3Igd2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eQoJCSAqIAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCgkJICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQoJCSAqIEBsYW5ndmVyc2lvbiAzLjAKCQkgKiBAc2VlIGZsYXNoeC50ZXh0TGF5b3V0LmZvcm1hdHMuVGV4dEFsaWduCgkJICovCgkJcHVibGljIGZ1bmN0aW9uIGdldCB0ZXh0QWxpZ24oKToqCgkJeyByZXR1cm4gX3N0eWxlcy50ZXh0QWxpZ247IH0KCQlwdWJsaWMgZnVuY3Rpb24gc2V0IHRleHRBbGlnbih2YWx1ZToqKTp2b2lkCgkJeyBzZXRTdHlsZUJ5UHJvcGVydHkoVGV4dExheW91dEZvcm1hdC50ZXh0QWxpZ25Qcm9wZXJ0eSx2YWx1ZSk7IH0KCgkJW0luc3BlY3RhYmxlKGVudW1lcmF0aW9uPSJsZWZ0LHJpZ2h0LGNlbnRlcixqdXN0aWZ5LHN0YXJ0LGVuZCxpbmhlcml0IildCgkJLyoqCgkJICogQWxpZ25tZW50IG9mIHRoZSBsYXN0IChvciBvbmx5KSBsaW5lIGluIHRoZSBwYXJhZ3JhcGggcmVsYXRpdmUgdG8gdGhlIGNvbnRhaW5lciBpbiBqdXN0aWZpZWQgdGV4dC4KCQkgKiBJZiA8Y29kZT50ZXh0QWxpZ248L2NvZGU+IGlzIHNldCB0byA8Y29kZT5UZXh0QWxpZ24uSlVTVElGWTwvY29kZT4sIDxjb2RlPnRleHRBbGlnbkxhc3Q8L2NvZGU+IHNwZWNpZmllcyBob3cgdGhlIGxhc3QgbGluZSAob3Igb25seSBsaW5lLCBpZiB0aGlzIGlzIGEgb25lIGxpbmUgYmxvY2spIGlzIGFsaWduZWQuIFZhbHVlcyBhcmUgc2ltaWxhciB0byA8Y29kZT50ZXh0QWxpZ248L2NvZGU+LgoJCSAqIDxwPkxlZ2FsIHZhbHVlcyBhcmUgVGV4dEFsaWduLkxFRlQsIFRleHRBbGlnbi5SSUdIVCwgVGV4dEFsaWduLkNFTlRFUiwgVGV4dEFsaWduLkpVU1RJRlksIFRleHRBbGlnbi5TVEFSVCwgVGV4dEFsaWduLkVORCwgRm9ybWF0VmFsdWUuSU5IRVJJVC48L3A+CgkJICogPHA+RGVmYXVsdCB2YWx1ZSBpcyB1bmRlZmluZWQgaW5kaWNhdGluZyBub3Qgc2V0LjwvcD4KCQkgKiA8cD5JZiB1bmRlZmluZWQgZHVyaW5nIHRoZSBjYXNjYWRlIHRoaXMgcHJvcGVydHkgd2lsbCBpbmhlcml0IGl0cyB2YWx1ZSBmcm9tIGFuIGFuY2VzdG9yLiBJZiBubyBhbmNlc3RvciBoYXMgc2V0IHRoaXMgcHJvcGVydHksIGl0IHdpbGwgaGF2ZSBhIHZhbHVlIG9mIFRleHRBbGlnbi5TVEFSVC48L3A+CgkJICogCgkJICogQHRocm93cyBSYW5nZUVycm9yIHdoZW4gc2V0IHZhbHVlIGlzIG5vdCB3aXRoaW4gcmFuZ2UgZm9yIHRoaXMgcHJvcGVydHkKCQkgKiAKCQkgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKCQkgKiBAbGFuZ3ZlcnNpb24gMy4wCgkJICogQHNlZSBmbGFzaHgudGV4dExheW91dC5mb3JtYXRzLlRleHRBbGlnbgoJCSAqLwoJCXB1YmxpYyBmdW5jdGlvbiBnZXQgdGV4dEFsaWduTGFzdCgpOioKCQl7IHJldHVybiBfc3R5bGVzLnRleHRBbGlnbkxhc3Q7IH0KCQlwdWJsaWMgZnVuY3Rpb24gc2V0IHRleHRBbGlnbkxhc3QodmFsdWU6Kik6dm9pZAoJCXsgc2V0U3R5bGVCeVByb3BlcnR5KFRleHRMYXlvdXRGb3JtYXQudGV4dEFsaWduTGFzdFByb3BlcnR5LHZhbHVlKTsgfQoKCQlbSW5zcGVjdGFibGUoZW51bWVyYXRpb249ImludGVyV29yZCxkaXN0cmlidXRlLGluaGVyaXQiKV0KCQkvKioKCQkgKiBTcGVjaWZpZXMgb3B0aW9ucyBmb3IganVzdGlmeWluZyB0ZXh0LgoJCSAqIERlZmF1bHQgdmFsdWUgaXMgPGNvZGU+VGV4dEp1c3RpZnkuSU5URVJfV09SRDwvY29kZT4sIG1lYW5pbmcgdGhhdCBleHRyYSBzcGFjZSBpcyBhZGRlZCB0byB0aGUgc3BhY2UgY2hhcmFjdGVycy4gPGNvZGU+VGV4dEp1c3RpZnkuRElTVFJJQlVURTwvY29kZT4gYWRkcyBleHRyYSBzcGFjZSB0byBzcGFjZSBjaGFyYWN0ZXJzIGFuZCBiZXR3ZWVuIGluZGl2aWR1YWwgbGV0dGVycy4gVXNlZCBvbmx5IGluIGNvbmp1bmN0aW9uIHdpdGggYSA8Y29kZT5qdXN0aWZpY2F0aW9uUnVsZTwvY29kZT4gdmFsdWUgb2YgPGNvZGU+SnVzdGlmaWNhdGlvblJ1bGUuU1BBQ0U8L2NvZGU+LgoJCSAqIDxwPkxlZ2FsIHZhbHVlcyBhcmUgVGV4dEp1c3RpZnkuSU5URVJfV09SRCwgVGV4dEp1c3RpZnkuRElTVFJJQlVURSwgRm9ybWF0VmFsdWUuSU5IRVJJVC48L3A+CgkJICogPHA+RGVmYXVsdCB2YWx1ZSBpcyB1bmRlZmluZWQgaW5kaWNhdGluZyBub3Qgc2V0LjwvcD4KCQkgKiA8cD5JZiB1bmRlZmluZWQgZHVyaW5nIHRoZSBjYXNjYWRlIHRoaXMgcHJvcGVydHkgd2lsbCBpbmhlcml0IGl0cyB2YWx1ZSBmcm9tIGFuIGFuY2VzdG9yLiBJZiBubyBhbmNlc3RvciBoYXMgc2V0IHRoaXMgcHJvcGVydHksIGl0IHdpbGwgaGF2ZSBhIHZhbHVlIG9mIFRleHRKdXN0aWZ5LklOVEVSX1dPUkQuPC9wPgoJCSAqIAoJCSAqIEB0aHJvd3MgUmFuZ2VFcnJvciB3aGVuIHNldCB2YWx1ZSBpcyBub3Qgd2l0aGluIHJhbmdlIGZvciB0aGlzIHByb3BlcnR5CgkJICogCgkJICogQHBsYXllcnZlcnNpb24gRmxhc2ggMTAKCQkgKiBAcGxheWVydmVyc2lvbiBBSVIgMS41CgkJICogQGxhbmd2ZXJzaW9uIDMuMAoJCSAqIEBzZWUgZmxhc2h4LnRleHRMYXlvdXQuZm9ybWF0cy5UZXh0SnVzdGlmeQoJCSAqLwoJCXB1YmxpYyBmdW5jdGlvbiBnZXQgdGV4dEp1c3RpZnkoKToqCgkJeyByZXR1cm4gX3N0eWxlcy50ZXh0SnVzdGlmeTsgfQoJCXB1YmxpYyBmdW5jdGlvbiBzZXQgdGV4dEp1c3RpZnkodmFsdWU6Kik6dm9pZAoJCXsgc2V0U3R5bGVCeVByb3BlcnR5KFRleHRMYXlvdXRGb3JtYXQudGV4dEp1c3RpZnlQcm9wZXJ0eSx2YWx1ZSk7IH0KCgkJW0luc3BlY3RhYmxlKGVudW1lcmF0aW9uPSJlYXN0QXNpYW4sc3BhY2UsYXV0byxpbmhlcml0IildCgkJLyoqCgkJICogUnVsZSB1c2VkIHRvIGp1c3RpZnkgdGV4dCBpbiBhIHBhcmFncmFwaC4KCQkgKiBEZWZhdWx0IHZhbHVlIGlzIDxjb2RlPkZvcm1hdFZhbHVlLkFVVE88L2NvZGU+LCB3aGljaCBqdXN0aWZpZXMgdGV4dCBiYXNlZCBvbiB0aGUgcGFyYWdyYXBoJ3MgPGNvZGU+bG9jYWxlPC9jb2RlPiBwcm9wZXJ0eS4gRm9yIGFsbCBsYW5ndWFnZXMgZXhjZXB0IEphcGFuZXNlIGFuZCBDaGluZXNlLCA8Y29kZT5Gb3JtYXRWYWx1ZS5BVVRPPC9jb2RlPiBiZWNvbWVzIDxjb2RlPkp1c3RpZmljYXRpb25SdWxlLlNQQUNFPC9jb2RlPiwgd2hpY2ggYWRkcyBleHRyYSBzcGFjZSB0byB0aGUgc3BhY2UgY2hhcmFjdGVycy4gIEZvciBKYXBhbmVzZSBhbmQgQ2hpbmVzZSwgPGNvZGU+Rm9ybWF0VmFsdWUuQVVUTzwvY29kZT4gYmVjb21lcyA8Y29kZT5KdXN0ZmljYXRpb25SdWxlLkVBU1RfQVNJQU48L2NvZGU+LiBJbiBwYXJ0LCBqdXN0aWZpY2F0aW9uIGNoYW5nZXMgdGhlIHNwYWNpbmcgb2YgcHVuY3R1YXRpb24uIEluIFJvbWFuIHRleHQgdGhlIGNvbW1hIGFuZCBKYXBhbmVzZSBwZXJpb2RzIHRha2UgYSBmdWxsIGNoYXJhY3RlcidzIHdpZHRoIGJ1dCBpbiBFYXN0IEFzaWFuIHRleHQgb25seSBoYWxmIG9mIGEgY2hhcmFjdGVyJ3Mgd2lkdGguIEFsc28sIGluIHRoZSBFYXN0IEFzaWFuIHRleHQgdGhlIHNwYWNpbmcgYmV0d2VlbiBzZXF1ZW50aWFsIHB1bmN0dWF0aW9uIG1hcmtzIGJlY29tZXMgdGlnaHRlciwgb2JleWluZyB0cmFkaXRpb25hbCBFYXN0IEFzaWFuIHR5cG9ncmFwaGljIGNvbnZlbnRpb25zLiBOb3RlLCB0b28sIGluIHRoZSBleGFtcGxlIGJlbG93IHRoZSBsZWFkaW5nIHRoYXQgaXMgYXBwbGllZCB0byB0aGUgc2Vjb25kIGxpbmUgb2YgdGhlIHBhcmFncmFwaHMuIEluIHRoZSBFYXN0IEFzaWFuIHZlcnNpb24sIHRoZSBsYXN0IHR3byBsaW5lcyBwdXNoIGxlZnQuIEluIHRoZSBSb21hbiB2ZXJzaW9uLCB0aGUgc2Vjb25kIGFuZCBmb2xsb3dpbmcgbGluZXMgcHVzaCBsZWZ0LjxwPjxpbWcgc3JjPScuLi8uLi8uLi9pbWFnZXMvdGV4dExheW91dF9qdXN0aWZpY2F0aW9ucnVsZS5wbmcnIGFsdD0nanVzdGlmaWNhdGlvblJ1bGUnIC8+PC9wPgoJCSAqIDxwPkxlZ2FsIHZhbHVlcyBhcmUgSnVzdGlmaWNhdGlvblJ1bGUuRUFTVF9BU0lBTiwgSnVzdGlmaWNhdGlvblJ1bGUuU1BBQ0UsIEZvcm1hdFZhbHVlLkFVVE8sIEZvcm1hdFZhbHVlLklOSEVSSVQuPC9wPgoJCSAqIDxwPkRlZmF1bHQgdmFsdWUgaXMgdW5kZWZpbmVkIGluZGljYXRpbmcgbm90IHNldC48L3A+CgkJICogPHA+SWYgdW5kZWZpbmVkIGR1cmluZyB0aGUgY2FzY2FkZSB0aGlzIHByb3BlcnR5IHdpbGwgaW5oZXJpdCBpdHMgdmFsdWUgZnJvbSBhbiBhbmNlc3Rvci4gSWYgbm8gYW5jZXN0b3IgaGFzIHNldCB0aGlzIHByb3BlcnR5LCBpdCB3aWxsIGhhdmUgYSB2YWx1ZSBvZiBGb3JtYXRWYWx1ZS5BVVRPLjwvcD4KCQkgKiAKCQkgKiBAdGhyb3dzIFJhbmdlRXJyb3Igd2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eQoJCSAqIAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCgkJICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQoJCSAqIEBsYW5ndmVyc2lvbiAzLjAKCQkgKiBAc2VlIGZsYXNoeC50ZXh0TGF5b3V0LmZvcm1hdHMuSnVzdGlmaWNhdGlvblJ1bGUKCQkgKi8KCQlwdWJsaWMgZnVuY3Rpb24gZ2V0IGp1c3RpZmljYXRpb25SdWxlKCk6KgoJCXsgcmV0dXJuIF9zdHlsZXMuanVzdGlmaWNhdGlvblJ1bGU7IH0KCQlwdWJsaWMgZnVuY3Rpb24gc2V0IGp1c3RpZmljYXRpb25SdWxlKHZhbHVlOiopOnZvaWQKCQl7IHNldFN0eWxlQnlQcm9wZXJ0eShUZXh0TGF5b3V0Rm9ybWF0Lmp1c3RpZmljYXRpb25SdWxlUHJvcGVydHksdmFsdWUpOyB9CgoJCVtJbnNwZWN0YWJsZShlbnVtZXJhdGlvbj0icHJpb3JpdGl6ZUxlYXN0QWRqdXN0bWVudCxwdXNoSW5LaW5zb2t1LHB1c2hPdXRPbmx5LGF1dG8saW5oZXJpdCIpXQoJCS8qKgoJCSAqIFRoZSBzdHlsZSB1c2VkIGZvciBqdXN0aWZpY2F0aW9uIG9mIHRoZSBwYXJhZ3JhcGguIFVzZWQgb25seSBpbiBjb25qdW5jdGlvbiB3aXRoIGEgPGNvZGU+anVzdGlmaWNhdGlvblJ1bGU8L2NvZGU+IHNldHRpbmcgb2YgPGNvZGU+SnVzdGlmaWNhdGlvblJ1bGUuRUFTVF9BU0lBTjwvY29kZT4uCgkJICogRGVmYXVsdCB2YWx1ZSBvZiA8Y29kZT5Gb3JtYXRWYWx1ZS5BVVRPPC9jb2RlPiBpcyByZXNvbHZlZCB0byA8Y29kZT5KdXN0aWZpY2F0aW9uU3R5bGUuUFVTSF9JTl9LSU5TT0tVPC9jb2RlPiBmb3IgYWxsIGxvY2FsZXMuICBUaGUgY29uc3RhbnRzIGRlZmluZWQgYnkgdGhlIEp1c3RpZmljYXRpb25TdHlsZSBjbGFzcyBzcGVjaWZ5IG9wdGlvbnMgZm9yIGhhbmRsaW5nIGtpbnNva3UgY2hhcmFjdGVycywgd2hpY2ggYXJlIEphcGFuZXNlIGNoYXJhY3RlcnMgdGhhdCBjYW5ub3QgYXBwZWFyIGF0IGVpdGhlciB0aGUgYmVnaW5uaW5nIG9yIGVuZCBvZiBhIGxpbmUuIElmIHlvdSB3YW50IGxvb3NlciB0ZXh0LCBzcGVjaWZ5IDxjb2RlPkp1c3RpZmljYXRpb25TdHlsZS5QVVNILU9VVC1PTkxZPC9jb2RlPi4gSWYgeW91IHdhbnQgYmVoYXZpb3IgdGhhdCBpcyBsaWtlIHdoYXQgeW91IGdldCB3aXRoIHRoZSAgPGNvZGU+anVzdGlmaWNhdGlvblJ1bGU8L2NvZGU+IG9mIDxjb2RlPkp1c3RpZmljYXRpb25SdWxlLlNQQUNFPC9jb2RlPiwgdXNlIDxjb2RlPkp1c3RpZmljYXRpb25TdHlsZS5QUklPUklUSVpFLUxFQVNULUFESlVTVE1FTlQ8L2NvZGU+LgoJCSAqIDxwPkxlZ2FsIHZhbHVlcyBhcmUgSnVzdGlmaWNhdGlvblN0eWxlLlBSSU9SSVRJWkVfTEVBU1RfQURKVVNUTUVOVCwgSnVzdGlmaWNhdGlvblN0eWxlLlBVU0hfSU5fS0lOU09LVSwgSnVzdGlmaWNhdGlvblN0eWxlLlBVU0hfT1VUX09OTFksIEZvcm1hdFZhbHVlLkFVVE8sIEZvcm1hdFZhbHVlLklOSEVSSVQuPC9wPgoJCSAqIDxwPkRlZmF1bHQgdmFsdWUgaXMgdW5kZWZpbmVkIGluZGljYXRpbmcgbm90IHNldC48L3A+CgkJICogPHA+SWYgdW5kZWZpbmVkIGR1cmluZyB0aGUgY2FzY2FkZSB0aGlzIHByb3BlcnR5IHdpbGwgaW5oZXJpdCBpdHMgdmFsdWUgZnJvbSBhbiBhbmNlc3Rvci4gSWYgbm8gYW5jZXN0b3IgaGFzIHNldCB0aGlzIHByb3BlcnR5LCBpdCB3aWxsIGhhdmUgYSB2YWx1ZSBvZiBGb3JtYXRWYWx1ZS5BVVRPLjwvcD4KCQkgKiAKCQkgKiBAdGhyb3dzIFJhbmdlRXJyb3Igd2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eQoJCSAqIAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCgkJICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQoJCSAqIEBsYW5ndmVyc2lvbiAzLjAKCQkgKiBAc2VlIGZsYXNoLnRleHQuZW5naW5lLkp1c3RpZmljYXRpb25TdHlsZQoJCSAqLwoJCXB1YmxpYyBmdW5jdGlvbiBnZXQganVzdGlmaWNhdGlvblN0eWxlKCk6KgoJCXsgcmV0dXJuIF9zdHlsZXMuanVzdGlmaWNhdGlvblN0eWxlOyB9CgkJcHVibGljIGZ1bmN0aW9uIHNldCBqdXN0aWZpY2F0aW9uU3R5bGUodmFsdWU6Kik6dm9pZAoJCXsgc2V0U3R5bGVCeVByb3BlcnR5KFRleHRMYXlvdXRGb3JtYXQuanVzdGlmaWNhdGlvblN0eWxlUHJvcGVydHksdmFsdWUpOyB9CgoJCVtJbnNwZWN0YWJsZShlbnVtZXJhdGlvbj0ibHRyLHJ0bCxpbmhlcml0IildCgkJLyoqCgkJICogU3BlY2lmaWVzIHRoZSBkZWZhdWx0IGJpZGlyZWN0aW9uYWwgZW1iZWRkaW5nIGxldmVsIG9mIHRoZSB0ZXh0IGluIHRoZSB0ZXh0IGJsb2NrLiAKCQkgKiBMZWZ0LXRvLXJpZ2h0IHJlYWRpbmcgb3JkZXIsIGFzIGluIExhdGluLXN0eWxlIHNjcmlwdHMsIG9yIHJpZ2h0LXRvLWxlZnQgcmVhZGluZyBvcmRlciwgYXMgaW4gQXJhYmljIG9yIEhlYnJldy4gVGhpcyBwcm9wZXJ0eSBhbHNvIGFmZmVjdHMgY29sdW1uIGRpcmVjdGlvbiB3aGVuIGl0IGlzIGFwcGxpZWQgYXQgdGhlIGNvbnRhaW5lciBsZXZlbC4gQ29sdW1ucyBjYW4gYmUgZWl0aGVyIGxlZnQtdG8tcmlnaHQgb3IgcmlnaHQtdG8tbGVmdCwganVzdCBsaWtlIHRleHQuIEJlbG93IGFyZSBzb21lIGV4YW1wbGVzOjxwPjxpbWcgc3JjPScuLi8uLi8uLi9pbWFnZXMvdGV4dExheW91dF9kaXJlY3Rpb24uZ2lmJyBhbHQ9J2RpcmVjdGlvbicgLz48L3A+CgkJICogPHA+TGVnYWwgdmFsdWVzIGFyZSBEaXJlY3Rpb24uTFRSLCBEaXJlY3Rpb24uUlRMLCBGb3JtYXRWYWx1ZS5JTkhFUklULjwvcD4KCQkgKiA8cD5EZWZhdWx0IHZhbHVlIGlzIHVuZGVmaW5lZCBpbmRpY2F0aW5nIG5vdCBzZXQuPC9wPgoJCSAqIDxwPklmIHVuZGVmaW5lZCBkdXJpbmcgdGhlIGNhc2NhZGUgdGhpcyBwcm9wZXJ0eSB3aWxsIGluaGVyaXQgaXRzIHZhbHVlIGZyb20gYW4gYW5jZXN0b3IuIElmIG5vIGFuY2VzdG9yIGhhcyBzZXQgdGhpcyBwcm9wZXJ0eSwgaXQgd2lsbCBoYXZlIGEgdmFsdWUgb2YgRGlyZWN0aW9uLkxUUi48L3A+CgkJICogCgkJICogQHRocm93cyBSYW5nZUVycm9yIHdoZW4gc2V0IHZhbHVlIGlzIG5vdCB3aXRoaW4gcmFuZ2UgZm9yIHRoaXMgcHJvcGVydHkKCQkgKiAKCQkgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKCQkgKiBAbGFuZ3ZlcnNpb24gMy4wCgkJICogQHNlZSBmbGFzaHgudGV4dExheW91dC5mb3JtYXRzLkRpcmVjdGlvbgoJCSAqLwoJCXB1YmxpYyBmdW5jdGlvbiBnZXQgZGlyZWN0aW9uKCk6KgoJCXsgcmV0dXJuIF9zdHlsZXMuZGlyZWN0aW9uOyB9CgkJcHVibGljIGZ1bmN0aW9uIHNldCBkaXJlY3Rpb24odmFsdWU6Kik6dm9pZAoJCXsgc2V0U3R5bGVCeVByb3BlcnR5KFRleHRMYXlvdXRGb3JtYXQuZGlyZWN0aW9uUHJvcGVydHksdmFsdWUpOyB9CgoJCS8qKgoJCSAqIFNwZWNpZmllcyB0aGUgb3B0aW11bSwgbWluaW11bSwgYW5kIG1heGltdW0gc3BhY2luZyAoYXMgYSBtdWx0aXBsaWVyIG9mIHRoZSB3aWR0aCBvZiBhIG5vcm1hbCBzcGFjZSkgYmV0d2VlbiB3b3JkcyB0byB1c2UgZHVyaW5nIGp1c3RpZmljYXRpb24uCgkJICogVGhlIG9wdGltdW0gc3BhY2UgaXMgdXNlZCB0byBpbmRpY2F0ZSB0aGUgZGVzaXJlZCBzaXplIG9mIGEgc3BhY2UsIGFzIGEgZnJhY3Rpb24gb2YgdGhlIHZhbHVlIGRlZmluZWQgaW4gdGhlIGZvbnQuIFRoZSBtaW5pbXVtIGFuZCBtYXhpbXVtIHZhbHVlcyBhcmUgdGhlIHVzZWQgd2hlbiB0ZXh0SnVzdGlmeSBpcyBkaXN0cmlidXRlIHRvIGRldGVybWluZSBob3cgd2lkZSBvciBuYXJyb3cgdGhlIHNwYWNlcyBiZXR3ZWVuIHRoZSB3b3JkcyBtYXkgZ3JvdyBiZWZvcmUgbGV0dGVyIHNwYWNpbmcgaXMgdXNlZCB0byBqdXN0aWZ5IHRoZSBsaW5lLgoJCSAqIDxwPkxlZ2FsIHZhbHVlcyBhcyBhIHBlcmNlbnQgYXJlIG51bWJlcnMgZnJvbSAtMTAwMCUgdG8gMTAwMCUuPC9wPgoJCSAqIDxwPkxlZ2FsIHZhbHVlcyBpbmNsdWRlIEZvcm1hdFZhbHVlLklOSEVSSVQuPC9wPgoJCSAqIDxwPkRlZmF1bHQgdmFsdWUgaXMgdW5kZWZpbmVkIGluZGljYXRpbmcgbm90IHNldC48L3A+CgkJICogPHA+SWYgdW5kZWZpbmVkIGR1cmluZyB0aGUgY2FzY2FkZSB0aGlzIHByb3BlcnR5IHdpbGwgaW5oZXJpdCBpdHMgdmFsdWUgZnJvbSBhbiBhbmNlc3Rvci4gSWYgbm8gYW5jZXN0b3IgaGFzIHNldCB0aGlzIHByb3BlcnR5LCBpdCB3aWxsIGhhdmUgYSB2YWx1ZSBvZiAxMDAlLCA1MCUsIDE1MCUuPC9wPgoJCSAqIAoJCSAqIEB0aHJvd3MgUmFuZ2VFcnJvciB3aGVuIHNldCB2YWx1ZSBpcyBub3Qgd2l0aGluIHJhbmdlIGZvciB0aGlzIHByb3BlcnR5CgkJICogCgkJICogQHBsYXllcnZlcnNpb24gRmxhc2ggMTAKCQkgKiBAcGxheWVydmVyc2lvbiBBSVIgMS41CgkJICogQGxhbmd2ZXJzaW9uIDMuMAoJCSAqLwoJCXB1YmxpYyBmdW5jdGlvbiBnZXQgd29yZFNwYWNpbmcoKToqCgkJeyByZXR1cm4gX3N0eWxlcy53b3JkU3BhY2luZzsgfQoJCXB1YmxpYyBmdW5jdGlvbiBzZXQgd29yZFNwYWNpbmcodmFsdWU6Kik6dm9pZAoJCXsgc2V0U3R5bGVCeVByb3BlcnR5KFRleHRMYXlvdXRGb3JtYXQud29yZFNwYWNpbmdQcm9wZXJ0eSx2YWx1ZSk7IH0KCgkJLyoqCgkJICogU3BlY2lmaWVzIHRoZSB0YWIgc3RvcHMgYXNzb2NpYXRlZCB3aXRoIHRoZSBwYXJhZ3JhcGguCgkJICogU2V0dGVycyBjYW4gdGFrZSBhbiBhcnJheSBvZiBUYWJTdG9wRm9ybWF0LCBhIGNvbmRlbnNlZCBzdHJpbmcgcmVwcmVzZW50YXRpb24sIHVuZGVmaW5lZCwgb3IgPGNvZGU+Rm9ybWF0VmFsdWUuSU5IRVJJVDwvY29kZT4uIFRoZSBjb25kZW5zZWQgc3RyaW5nIHJlcHJlc2VudGF0aW9uIGlzIGFsd2F5cyBjb252ZXJ0ZWQgaW50byBhbiBhcnJheSBvZiBUYWJTdG9wRm9ybWF0LiA8cD5UaGUgc3RyaW5nLWJhc2VkIGZvcm1hdCBpcyBhIGxpc3Qgb2YgdGFiIHN0b3BzLCB3aGVyZSBlYWNoIHRhYiBzdG9wIGlzIGRlbGltaXRlZCBieSBvbmUgb3IgbW9yZSBzcGFjZXMuPC9wPjxwPkEgdGFiIHN0b3AgdGFrZXMgdGhlIGZvbGxvd2luZyBmb3JtOiAmbHQ7YWxpZ25tZW50IHR5cGUmZ3Q7Jmx0O2FsaWdubWVudCBwb3NpdGlvbiZndDt8Jmx0O2FsaWdubWVudCB0b2tlbiZndDsuPC9wPjxwPlRoZSBhbGlnbm1lbnQgdHlwZSBpcyBhIHNpbmdsZSBjaGFyYWN0ZXIsIGFuZCBjYW4gYmUgUywgRSwgQywgb3IgRCAob3IgbG93ZXItY2FzZSBlcXVpdmFsZW50cykuIFMgb3IgcyBmb3Igc3RhcnQsIEUgb3IgZSBmb3IgZW5kLCBDIG9yIGMgZm9yIGNlbnRlciwgRCBvciBkIGZvciBkZWNpbWFsLiBUaGUgYWxpZ25tZW50IHR5cGUgaXMgb3B0aW9uYWwsIGFuZCBpZiBpdHMgbm90IHNwZWNpZmllZCB3aWxsIGRlZmF1bHQgdG8gUy48L3A+PHA+VGhlIGFsaWdubWVudCBwb3NpdGlvbiBpcyBhIE51bWJlciwgYW5kIGlzIHNwZWNpZmllZCBhY2NvcmRpbmcgdG8gRlhHIHNwZWMgZm9yIE51bWJlcnMgKGRlY2ltYWwgb3Igc2NpZW50aWZpYyBub3RhdGlvbikuIFRoZSBhbGlnbm1lbnQgcG9zaXRpb24gaXMgcmVxdWlyZWQuPC9wPjxwPlRoZSB2ZXJ0aWNhbCBiYXIgaXMgdXNlZCB0byBzZXBhcmF0ZSB0aGUgYWxpZ25tZW50IHBvc2l0aW9uIGZyb20gdGhlIGFsaWdubWVudCB0b2tlbiwgYW5kIHNob3VsZCBvbmx5IGJlIHByZXNlbnQgaWYgdGhlIGFsaWdubWVudCB0b2tlbiBpcyBwcmVzZW50LjwvcD48cD4gVGhlIGFsaWdubWVudCB0b2tlbiBpcyBvcHRpb25hbCBpZiB0aGUgYWxpZ25tZW50IHR5cGUgaXMgRCwgYW5kIHNob3VsZCBub3QgYmUgcHJlc2VudCBpZiB0aGUgYWxpZ25tZW50IHR5cGUgaXMgYW55dGhpbmcgb3RoZXIgdGhhbiBELiBUaGUgYWxpZ25tZW50IHRva2VuIG1heSBiZSBhbnkgc2VxdWVuY2Ugb2YgY2hhcmFjdGVycyB0ZXJtaW5hdGVkIGJ5IHRoZSBzcGFjZSB0aGF0IGVuZHMgdGhlIHRhYiBzdG9wIChmb3IgdGhlIGxhc3QgdGFiIHN0b3AsIHRoZSB0ZXJtaW5hdGluZyBzcGFjZSBpcyBvcHRpb25hbDsgZW5kIG9mIGFsaWdubWVudCB0b2tlbiBpcyBpbXBsaWVkKS4gQSBzcGFjZSBtYXkgYmUgcGFydCBvZiB0aGUgYWxpZ25tZW50IHRva2VuIGlmIGl0IGlzIGVzY2FwZWQgd2l0aCBhIGJhY2tzbGFzaCAoXCApLiBBIGJhY2tzbGFzaCBtYXkgYmUgcGFydCBvZiB0aGUgYWxpZ25tZW50IHRva2VuIGlmIGl0IGlzIGVzY2FwZWQgd2l0aCBhbm90aGVyIGJhY2tzbGFzaCAoXFwpLiBJZiB0aGUgYWxpZ25tZW50IHR5cGUgaXMgRCwgYW5kIHRoZSBhbGlnbm1lbnQgdG9rZW4gaXMgbm90IHNwZWNpZmllZCwgaXQgd2lsbCB0YWtlIG9uIHRoZSBkZWZhdWx0IHZhbHVlIG9mIG51bGwuPC9wPgoJCSAqIDxwPkRlZmF1bHQgdmFsdWUgaXMgdW5kZWZpbmVkIGluZGljYXRpbmcgbm90IHNldC48L3A+CgkJICogPHA+SWYgdW5kZWZpbmVkIGR1cmluZyB0aGUgY2FzY2FkZSB0aGlzIHByb3BlcnR5IHdpbGwgaW5oZXJpdCBpdHMgdmFsdWUgZnJvbSBhbiBhbmNlc3Rvci4gSWYgbm8gYW5jZXN0b3IgaGFzIHNldCB0aGlzIHByb3BlcnR5LCBpdCB3aWxsIGhhdmUgYSB2YWx1ZSBvZiBudWxsLjwvcD4KCQkgKiBAc2VlIGZsYXNoeC50ZXh0TGF5b3V0LmZvcm1hdHMuVGFiU3RvcEZvcm1hdAoJCSAqIAoJCSAqIEB0aHJvd3MgUmFuZ2VFcnJvciB3aGVuIHNldCB2YWx1ZSBpcyBub3Qgd2l0aGluIHJhbmdlIGZvciB0aGlzIHByb3BlcnR5CgkJICogCgkJICogQHBsYXllcnZlcnNpb24gRmxhc2ggMTAKCQkgKiBAcGxheWVydmVyc2lvbiBBSVIgMS41CgkJICogQGxhbmd2ZXJzaW9uIDMuMAoJCSAqLwoJCXB1YmxpYyBmdW5jdGlvbiBnZXQgdGFiU3RvcHMoKToqCgkJeyByZXR1cm4gX3N0eWxlcy50YWJTdG9wczsgfQoJCXB1YmxpYyBmdW5jdGlvbiBzZXQgdGFiU3RvcHModmFsdWU6Kik6dm9pZAoJCXsgc2V0U3R5bGVCeVByb3BlcnR5KFRleHRMYXlvdXRGb3JtYXQudGFiU3RvcHNQcm9wZXJ0eSx2YWx1ZSk7IH0KCgkJW0luc3BlY3RhYmxlKGVudW1lcmF0aW9uPSJyb21hblVwLGlkZW9ncmFwaGljVG9wVXAsaWRlb2dyYXBoaWNDZW50ZXJVcCxpZGVvZ3JhcGhpY1RvcERvd24saWRlb2dyYXBoaWNDZW50ZXJEb3duLGFwcHJveGltYXRlVGV4dEZpZWxkLGFzY2VudERlc2NlbnRVcCxib3gsYXV0byxpbmhlcml0IildCgkJLyoqCgkJICogU3BlY2lmaWVzIHRoZSBsZWFkaW5nIG1vZGVsLCB3aGljaCBpcyBhIGNvbWJpbmF0aW9uIG9mIGxlYWRpbmcgYmFzaXMgYW5kIGxlYWRpbmcgZGlyZWN0aW9uLgoJCSAqIExlYWRpbmcgYmFzaXMgaXMgdGhlIGJhc2VsaW5lIHRvIHdoaWNoIHRoZSA8Y29kZT5saW5lSGVpZ2h0PC9jb2RlPiBwcm9wZXJ0eSByZWZlcnMuIExlYWRpbmcgZGlyZWN0aW9uIGRldGVybWluZXMgd2hldGhlciB0aGUgPGNvZGU+bGluZUhlaWdodDwvY29kZT4gcHJvcGVydHkgcmVmZXJzIHRvIHRoZSBkaXN0YW5jZSBvZiBhIGxpbmUncyBiYXNlbGluZSBmcm9tIHRoYXQgb2YgdGhlIGxpbmUgYmVmb3JlIGl0IG9yIHRoZSBsaW5lIGFmdGVyIGl0LiBUaGUgZGVmYXVsdCB2YWx1ZSBvZiA8Y29kZT5Gb3JtYXRWYWx1ZS5BVVRPPC9jb2RlPiBpcyByZXNvbHZlZCBiYXNlZCBvbiB0aGUgcGFyYWdyYXBoJ3MgPGNvZGU+bG9jYWxlPC9jb2RlPiBwcm9wZXJ0eS4gIEZvciBKYXBhbmVzZSBhbmQgQ2hpbmVzZSwgaXQgaXMgPGNvZGU+TGVhZGluZ01vZGVsLklERU9HUkFQSElDX1RPUF9ET1dOPC9jb2RlPiBhbmQgZm9yIGFsbCBvdGhlcnMgaXQgaXMgPGNvZGU+TGVhZGluZ01vZGVsLlJPTUFOX1VQPC9jb2RlPi48cD48c3Ryb25nPkxlYWRpbmcgQmFzaXM6PC9zdHJvbmc+PC9wPjxwPjxpbWcgc3JjPScuLi8uLi8uLi9pbWFnZXMvdGV4dExheW91dF9MQjEucG5nJyBhbHQ9J2xlYWRpbmdCYXNpczEnIC8+ICAgIDxpbWcgc3JjPScuLi8uLi8uLi9pbWFnZXMvdGV4dExheW91dF9MQjIucG5nJyBhbHQ9J2xlYWRpbmdCYXNpczInIC8+ICAgIDxpbWcgc3JjPScuLi8uLi8uLi9pbWFnZXMvdGV4dExheW91dF9MQjMucG5nJyBhbHQ9J2xlYWRpbmdCYXNpczMnIC8+PC9wPjxwPjxzdHJvbmc+TGVhZGluZyBEaXJlY3Rpb246PC9zdHJvbmc+PC9wPjxwPjxpbWcgc3JjPScuLi8uLi8uLi9pbWFnZXMvdGV4dExheW91dF9MRDEucG5nJyBhbHQ9J2xlYWRpbmdEaXJlY3Rpb24xJyAvPiAgICA8aW1nIHNyYz0nLi4vLi4vLi4vaW1hZ2VzL3RleHRMYXlvdXRfTEQyLnBuZycgYWx0PSdsZWFkaW5nRGlyZWN0aW9uMicgLz4gICAgPGltZyBzcmM9Jy4uLy4uLy4uL2ltYWdlcy90ZXh0TGF5b3V0X0xEMy5wbmcnIGFsdD0nbGVhZGluZ0RpcmVjdGlvbjMnIC8+PC9wPgoJCSAqIDxwPkxlZ2FsIHZhbHVlcyBhcmUgTGVhZGluZ01vZGVsLlJPTUFOX1VQLCBMZWFkaW5nTW9kZWwuSURFT0dSQVBISUNfVE9QX1VQLCBMZWFkaW5nTW9kZWwuSURFT0dSQVBISUNfQ0VOVEVSX1VQLCBMZWFkaW5nTW9kZWwuSURFT0dSQVBISUNfVE9QX0RPV04sIExlYWRpbmdNb2RlbC5JREVPR1JBUEhJQ19DRU5URVJfRE9XTiwgTGVhZGluZ01vZGVsLkFQUFJPWElNQVRFX1RFWFRfRklFTEQsIExlYWRpbmdNb2RlbC5BU0NFTlRfREVTQ0VOVF9VUCwgTGVhZGluZ01vZGVsLkJPWCwgTGVhZGluZ01vZGVsLkFVVE8sIEZvcm1hdFZhbHVlLklOSEVSSVQuPC9wPgoJCSAqIDxwPkRlZmF1bHQgdmFsdWUgaXMgdW5kZWZpbmVkIGluZGljYXRpbmcgbm90IHNldC48L3A+CgkJICogPHA+SWYgdW5kZWZpbmVkIGR1cmluZyB0aGUgY2FzY2FkZSB0aGlzIHByb3BlcnR5IHdpbGwgaW5oZXJpdCBpdHMgdmFsdWUgZnJvbSBhbiBhbmNlc3Rvci4gSWYgbm8gYW5jZXN0b3IgaGFzIHNldCB0aGlzIHByb3BlcnR5LCBpdCB3aWxsIGhhdmUgYSB2YWx1ZSBvZiBMZWFkaW5nTW9kZWwuQVVUTy48L3A+CgkJICogCgkJICogQHRocm93cyBSYW5nZUVycm9yIHdoZW4gc2V0IHZhbHVlIGlzIG5vdCB3aXRoaW4gcmFuZ2UgZm9yIHRoaXMgcHJvcGVydHkKCQkgKiAKCQkgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKCQkgKiBAbGFuZ3ZlcnNpb24gMy4wCgkJICogQHNlZSBmbGFzaHgudGV4dExheW91dC5mb3JtYXRzLkxlYWRpbmdNb2RlbAoJCSAqLwoJCXB1YmxpYyBmdW5jdGlvbiBnZXQgbGVhZGluZ01vZGVsKCk6KgoJCXsgcmV0dXJuIF9zdHlsZXMubGVhZGluZ01vZGVsOyB9CgkJcHVibGljIGZ1bmN0aW9uIHNldCBsZWFkaW5nTW9kZWwodmFsdWU6Kik6dm9pZAoJCXsgc2V0U3R5bGVCeVByb3BlcnR5KFRleHRMYXlvdXRGb3JtYXQubGVhZGluZ01vZGVsUHJvcGVydHksdmFsdWUpOyB9CgoJCS8qKgoJCSAqIFNwZWNpZmllcyB0aGUgYW1vdW50IG9mIGd1dHRlciBzcGFjZSwgaW4gcGl4ZWxzLCB0byBsZWF2ZSBiZXR3ZWVuIHRoZSBjb2x1bW5zIChhZG9wdHMgZGVmYXVsdCB2YWx1ZSBpZiB1bmRlZmluZWQgZHVyaW5nIGNhc2NhZGUpLgoJCSAqIFZhbHVlIGlzIGEgTnVtYmVyCgkJICogPHA+TGVnYWwgdmFsdWVzIGFyZSBudW1iZXJzIGZyb20gMCB0byAxMDAwIGFuZCBGb3JtYXRWYWx1ZS5JTkhFUklULjwvcD4KCQkgKiA8cD5EZWZhdWx0IHZhbHVlIGlzIHVuZGVmaW5lZCBpbmRpY2F0aW5nIG5vdCBzZXQuPC9wPgoJCSAqIDxwPklmIHVuZGVmaW5lZCBkdXJpbmcgdGhlIGNhc2NhZGUgdGhpcyBwcm9wZXJ0eSB3aWxsIGhhdmUgYSB2YWx1ZSBvZiAyMC48L3A+CgkJICogCgkJICogQHRocm93cyBSYW5nZUVycm9yIHdoZW4gc2V0IHZhbHVlIGlzIG5vdCB3aXRoaW4gcmFuZ2UgZm9yIHRoaXMgcHJvcGVydHkKCQkgKiAKCQkgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKCQkgKiBAbGFuZ3ZlcnNpb24gMy4wCgkJICovCgkJcHVibGljIGZ1bmN0aW9uIGdldCBjb2x1bW5HYXAoKToqCgkJeyByZXR1cm4gX3N0eWxlcy5jb2x1bW5HYXA7IH0KCQlwdWJsaWMgZnVuY3Rpb24gc2V0IGNvbHVtbkdhcCh2YWx1ZToqKTp2b2lkCgkJeyBzZXRTdHlsZUJ5UHJvcGVydHkoVGV4dExheW91dEZvcm1hdC5jb2x1bW5HYXBQcm9wZXJ0eSx2YWx1ZSk7IH0KCgkJLyoqCgkJICogTGVmdCBpbnNldCBpbiBwaXhlbHMuICBEZWZhdWx0IG9mIGF1dG8gaXMgemVybyBleGNlcHQgaW4gbGlzdHMgd2hpY2ggZ2V0IGEgc3RhcnQgc2lkZSBwYWRkaW5nIG9mIDQ1LiAoYWRvcHRzIGRlZmF1bHQgdmFsdWUgaWYgdW5kZWZpbmVkIGR1cmluZyBjYXNjYWRlKS4KCQkgKiBTcGFjZSBiZXR3ZWVuIHRoZSBsZWZ0IGVkZ2Ugb2YgdGhlIGNvbnRhaW5lciBhbmQgdGhlIHRleHQuICBWYWx1ZSBpcyBhIE51bWJlciBvciBhdXRvLjxwPiBXaXRoIHZlcnRpY2FsIHRleHQsIGluIHNjcm9sbGFibGUgY29udGFpbmVycyB3aXRoIG11bHRpcGxlIGNvbHVtbnMsIHRoZSBmaXJzdCBhbmQgZm9sbG93aW5nIGNvbHVtbnMgd2lsbCBzaG93IHRoZSBwYWRkaW5nIGFzIGJsYW5rIHNwYWNlIGF0IHRoZSBlbmQgb2YgdGhlIGNvbnRhaW5lciwgYnV0IGZvciB0aGUgbGFzdCBjb2x1bW4sIGlmIHRoZSB0ZXh0IGRvZXNuJ3QgYWxsIGZpdCwgeW91IG1heSBoYXZlIHRvIHNjcm9sbCBpbiBvcmRlciB0byBzZWUgdGhlIHBhZGRpbmcuPC9wPgoJCSAqIDxwPkxlZ2FsIHZhbHVlcyBhcyBhIHN0cmluZyBhcmUgRm9ybWF0VmFsdWUuQVVUTywgRm9ybWF0VmFsdWUuSU5IRVJJVCBhbmQgbnVtYmVycyBmcm9tIC04MDAwIHRvIDgwMDAuPC9wPgoJCSAqIDxwPkRlZmF1bHQgdmFsdWUgaXMgdW5kZWZpbmVkIGluZGljYXRpbmcgbm90IHNldC48L3A+CgkJICogPHA+SWYgdW5kZWZpbmVkIGR1cmluZyB0aGUgY2FzY2FkZSB0aGlzIHByb3BlcnR5IHdpbGwgaGF2ZSBhIHZhbHVlIG9mIEZvcm1hdFZhbHVlLkFVVE8uPC9wPgoJCSAqIEBzZWUgZmxhc2h4LnRleHRMYXlvdXQuZWxlbWVudHMuQ29uZmlndXJhdGlvbiNhdXRvTGlzdEVsZW1lbnRTdGFydFBhZGRpbmcKCQkgKiAKCQkgKiBAdGhyb3dzIFJhbmdlRXJyb3Igd2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eQoJCSAqIAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCgkJICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQoJCSAqIEBsYW5ndmVyc2lvbiAzLjAKCQkgKiBAc2VlIGZsYXNoeC50ZXh0TGF5b3V0LmZvcm1hdHMuRm9ybWF0VmFsdWUKCQkgKi8KCQlwdWJsaWMgZnVuY3Rpb24gZ2V0IHBhZGRpbmdMZWZ0KCk6KgoJCXsgcmV0dXJuIF9zdHlsZXMucGFkZGluZ0xlZnQ7IH0KCQlwdWJsaWMgZnVuY3Rpb24gc2V0IHBhZGRpbmdMZWZ0KHZhbHVlOiopOnZvaWQKCQl7IHNldFN0eWxlQnlQcm9wZXJ0eShUZXh0TGF5b3V0Rm9ybWF0LnBhZGRpbmdMZWZ0UHJvcGVydHksdmFsdWUpOyB9CgoJCS8qKgoJCSAqIFRvcCBpbnNldCBpbiBwaXhlbHMuICBEZWZhdWx0IG9mIGF1dG8gaXMgemVybyBleGNlcHQgaW4gbGlzdHMgd2hpY2ggZ2V0IGEgc3RhcnQgc2lkZSBwYWRkaW5nIG9mIDQ1LiAoYWRvcHRzIGRlZmF1bHQgdmFsdWUgaWYgdW5kZWZpbmVkIGR1cmluZyBjYXNjYWRlKS4KCQkgKiBTcGFjZSBiZXR3ZWVuIHRoZSB0b3AgZWRnZSBvZiB0aGUgY29udGFpbmVyIGFuZCB0aGUgdGV4dC4gIFZhbHVlIGlzIGEgTnVtYmVyIG9yIGF1dG8uCgkJICogPHA+TGVnYWwgdmFsdWVzIGFzIGEgc3RyaW5nIGFyZSBGb3JtYXRWYWx1ZS5BVVRPLCBGb3JtYXRWYWx1ZS5JTkhFUklUIGFuZCBudW1iZXJzIGZyb20gLTgwMDAgdG8gODAwMC48L3A+CgkJICogPHA+RGVmYXVsdCB2YWx1ZSBpcyB1bmRlZmluZWQgaW5kaWNhdGluZyBub3Qgc2V0LjwvcD4KCQkgKiA8cD5JZiB1bmRlZmluZWQgZHVyaW5nIHRoZSBjYXNjYWRlIHRoaXMgcHJvcGVydHkgd2lsbCBoYXZlIGEgdmFsdWUgb2YgRm9ybWF0VmFsdWUuQVVUTy48L3A+CgkJICogQHNlZSBmbGFzaHgudGV4dExheW91dC5lbGVtZW50cy5Db25maWd1cmF0aW9uI2F1dG9MaXN0RWxlbWVudFN0YXJ0UGFkZGluZwoJCSAqIAoJCSAqIEB0aHJvd3MgUmFuZ2VFcnJvciB3aGVuIHNldCB2YWx1ZSBpcyBub3Qgd2l0aGluIHJhbmdlIGZvciB0aGlzIHByb3BlcnR5CgkJICogCgkJICogQHBsYXllcnZlcnNpb24gRmxhc2ggMTAKCQkgKiBAcGxheWVydmVyc2lvbiBBSVIgMS41CgkJICogQGxhbmd2ZXJzaW9uIDMuMAoJCSAqIEBzZWUgZmxhc2h4LnRleHRMYXlvdXQuZm9ybWF0cy5Gb3JtYXRWYWx1ZQoJCSAqLwoJCXB1YmxpYyBmdW5jdGlvbiBnZXQgcGFkZGluZ1RvcCgpOioKCQl7IHJldHVybiBfc3R5bGVzLnBhZGRpbmdUb3A7IH0KCQlwdWJsaWMgZnVuY3Rpb24gc2V0IHBhZGRpbmdUb3AodmFsdWU6Kik6dm9pZAoJCXsgc2V0U3R5bGVCeVByb3BlcnR5KFRleHRMYXlvdXRGb3JtYXQucGFkZGluZ1RvcFByb3BlcnR5LHZhbHVlKTsgfQoKCQkvKioKCQkgKiBSaWdodCBpbnNldCBpbiBwaXhlbHMuICBEZWZhdWx0IG9mIGF1dG8gaXMgemVybyBleGNlcHQgaW4gbGlzdHMgd2hpY2ggZ2V0IGEgc3RhcnQgc2lkZSBwYWRkaW5nIG9mIDQ1LiAoYWRvcHRzIGRlZmF1bHQgdmFsdWUgaWYgdW5kZWZpbmVkIGR1cmluZyBjYXNjYWRlKS4KCQkgKiBTcGFjZSBiZXR3ZWVuIHRoZSByaWdodCBlZGdlIG9mIHRoZSBjb250YWluZXIgYW5kIHRoZSB0ZXh0LiAgVmFsdWUgaXMgYSBOdW1iZXIgb3IgYXV0by4gCgkJICogPHA+TGVnYWwgdmFsdWVzIGFzIGEgc3RyaW5nIGFyZSBGb3JtYXRWYWx1ZS5BVVRPLCBGb3JtYXRWYWx1ZS5JTkhFUklUIGFuZCBudW1iZXJzIGZyb20gLTgwMDAgdG8gODAwMC48L3A+CgkJICogPHA+RGVmYXVsdCB2YWx1ZSBpcyB1bmRlZmluZWQgaW5kaWNhdGluZyBub3Qgc2V0LjwvcD4KCQkgKiA8cD5JZiB1bmRlZmluZWQgZHVyaW5nIHRoZSBjYXNjYWRlIHRoaXMgcHJvcGVydHkgd2lsbCBoYXZlIGEgdmFsdWUgb2YgRm9ybWF0VmFsdWUuQVVUTy48L3A+CgkJICogQHNlZSBmbGFzaHgudGV4dExheW91dC5lbGVtZW50cy5Db25maWd1cmF0aW9uI2F1dG9MaXN0RWxlbWVudFN0YXJ0UGFkZGluZwoJCSAqIAoJCSAqIEB0aHJvd3MgUmFuZ2VFcnJvciB3aGVuIHNldCB2YWx1ZSBpcyBub3Qgd2l0aGluIHJhbmdlIGZvciB0aGlzIHByb3BlcnR5CgkJICogCgkJICogQHBsYXllcnZlcnNpb24gRmxhc2ggMTAKCQkgKiBAcGxheWVydmVyc2lvbiBBSVIgMS41CgkJICogQGxhbmd2ZXJzaW9uIDMuMAoJCSAqIEBzZWUgZmxhc2h4LnRleHRMYXlvdXQuZm9ybWF0cy5Gb3JtYXRWYWx1ZQoJCSAqLwoJCXB1YmxpYyBmdW5jdGlvbiBnZXQgcGFkZGluZ1JpZ2h0KCk6KgoJCXsgcmV0dXJuIF9zdHlsZXMucGFkZGluZ1JpZ2h0OyB9CgkJcHVibGljIGZ1bmN0aW9uIHNldCBwYWRkaW5nUmlnaHQodmFsdWU6Kik6dm9pZAoJCXsgc2V0U3R5bGVCeVByb3BlcnR5KFRleHRMYXlvdXRGb3JtYXQucGFkZGluZ1JpZ2h0UHJvcGVydHksdmFsdWUpOyB9CgoJCS8qKgoJCSAqIEJvdHRvbSBpbnNldCBpbiBwaXhlbHMuICBEZWZhdWx0IG9mIGF1dG8gaXMgemVybyBleGNlcHQgaW4gbGlzdHMgd2hpY2ggZ2V0IGEgc3RhcnQgc2lkZSBwYWRkaW5nIG9mIDQ1LiAgKGFkb3B0cyBkZWZhdWx0IHZhbHVlIGlmIHVuZGVmaW5lZCBkdXJpbmcgY2FzY2FkZSkuCgkJICogU3BhY2UgYmV0d2VlbiB0aGUgYm90dG9tIGVkZ2Ugb2YgdGhlIGNvbnRhaW5lciBhbmQgdGhlIHRleHQuICBWYWx1ZSBpcyBhIE51bWJlciAgb3IgYXV0by4gPHA+IFdpdGggaG9yaXpvbnRhbCB0ZXh0LCBpbiBzY3JvbGxhYmxlIGNvbnRhaW5lcnMgd2l0aCBtdWx0aXBsZSBjb2x1bW5zLCB0aGUgZmlyc3QgYW5kIGZvbGxvd2luZyBjb2x1bW5zIHdpbGwgc2hvdyB0aGUgcGFkZGluZyBhcyBibGFuayBzcGFjZSBhdCB0aGUgYm90dG9tIG9mIHRoZSBjb250YWluZXIsIGJ1dCBmb3IgdGhlIGxhc3QgY29sdW1uLCBpZiB0aGUgdGV4dCBkb2Vzbid0IGFsbCBmaXQsIHlvdSBtYXkgaGF2ZSB0byBzY3JvbGwgaW4gb3JkZXIgdG8gc2VlIHRoZSBwYWRkaW5nLjwvcD4KCQkgKiA8cD5MZWdhbCB2YWx1ZXMgYXMgYSBzdHJpbmcgYXJlIEZvcm1hdFZhbHVlLkFVVE8sIEZvcm1hdFZhbHVlLklOSEVSSVQgYW5kIG51bWJlcnMgZnJvbSAtODAwMCB0byA4MDAwLjwvcD4KCQkgKiA8cD5EZWZhdWx0IHZhbHVlIGlzIHVuZGVmaW5lZCBpbmRpY2F0aW5nIG5vdCBzZXQuPC9wPgoJCSAqIDxwPklmIHVuZGVmaW5lZCBkdXJpbmcgdGhlIGNhc2NhZGUgdGhpcyBwcm9wZXJ0eSB3aWxsIGhhdmUgYSB2YWx1ZSBvZiBGb3JtYXRWYWx1ZS5BVVRPLjwvcD4KCQkgKiBAc2VlIGZsYXNoeC50ZXh0TGF5b3V0LmVsZW1lbnRzLkNvbmZpZ3VyYXRpb24jYXV0b0xpc3RFbGVtZW50U3RhcnRQYWRkaW5nCgkJICogCgkJICogQHRocm93cyBSYW5nZUVycm9yIHdoZW4gc2V0IHZhbHVlIGlzIG5vdCB3aXRoaW4gcmFuZ2UgZm9yIHRoaXMgcHJvcGVydHkKCQkgKiAKCQkgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKCQkgKiBAbGFuZ3ZlcnNpb24gMy4wCgkJICogQHNlZSBmbGFzaHgudGV4dExheW91dC5mb3JtYXRzLkZvcm1hdFZhbHVlCgkJICovCgkJcHVibGljIGZ1bmN0aW9uIGdldCBwYWRkaW5nQm90dG9tKCk6KgoJCXsgcmV0dXJuIF9zdHlsZXMucGFkZGluZ0JvdHRvbTsgfQoJCXB1YmxpYyBmdW5jdGlvbiBzZXQgcGFkZGluZ0JvdHRvbSh2YWx1ZToqKTp2b2lkCgkJeyBzZXRTdHlsZUJ5UHJvcGVydHkoVGV4dExheW91dEZvcm1hdC5wYWRkaW5nQm90dG9tUHJvcGVydHksdmFsdWUpOyB9CgoJCS8qKgoJCSAqIE51bWJlciBvZiB0ZXh0IGNvbHVtbnMgKGFkb3B0cyBkZWZhdWx0IHZhbHVlIGlmIHVuZGVmaW5lZCBkdXJpbmcgY2FzY2FkZSkuCgkJICogVGhlIGNvbHVtbiBudW1iZXIgb3ZlcnJpZGVzIHRoZSAgb3RoZXIgY29sdW1uIHNldHRpbmdzLiBWYWx1ZSBpcyBhbiBpbnRlZ2VyLCBvciA8Y29kZT5Gb3JtYXRWYWx1ZS5BVVRPPC9jb2RlPiBpZiB1bnNwZWNpZmllZC4gSWYgPGNvZGU+Y29sdW1uQ291bnQ8L2NvZGU+IGlzIG5vdCBzcGVjaWZpZWQsPGNvZGU+Y29sdW1uV2lkdGg8L2NvZGU+IGlzIHVzZWQgdG8gY3JlYXRlIGFzIG1hbnkgY29sdW1ucyBhcyBjYW4gZml0IGluIHRoZSBjb250YWluZXIuCgkJICogPHA+TGVnYWwgdmFsdWVzIGFzIGEgc3RyaW5nIGFyZSBGb3JtYXRWYWx1ZS5BVVRPLCBGb3JtYXRWYWx1ZS5JTkhFUklUIGFuZCBmcm9tIGludHMgZnJvbSAxIHRvIDUwLjwvcD4KCQkgKiA8cD5EZWZhdWx0IHZhbHVlIGlzIHVuZGVmaW5lZCBpbmRpY2F0aW5nIG5vdCBzZXQuPC9wPgoJCSAqIDxwPklmIHVuZGVmaW5lZCBkdXJpbmcgdGhlIGNhc2NhZGUgdGhpcyBwcm9wZXJ0eSB3aWxsIGhhdmUgYSB2YWx1ZSBvZiBGb3JtYXRWYWx1ZS5BVVRPLjwvcD4KCQkgKiAKCQkgKiBAdGhyb3dzIFJhbmdlRXJyb3Igd2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eQoJCSAqIAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCgkJICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQoJCSAqIEBsYW5ndmVyc2lvbiAzLjAKCQkgKiBAc2VlIGZsYXNoeC50ZXh0TGF5b3V0LmZvcm1hdHMuRm9ybWF0VmFsdWUKCQkgKi8KCQlwdWJsaWMgZnVuY3Rpb24gZ2V0IGNvbHVtbkNvdW50KCk6KgoJCXsgcmV0dXJuIF9zdHlsZXMuY29sdW1uQ291bnQ7IH0KCQlwdWJsaWMgZnVuY3Rpb24gc2V0IGNvbHVtbkNvdW50KHZhbHVlOiopOnZvaWQKCQl7IHNldFN0eWxlQnlQcm9wZXJ0eShUZXh0TGF5b3V0Rm9ybWF0LmNvbHVtbkNvdW50UHJvcGVydHksdmFsdWUpOyB9CgoJCS8qKgoJCSAqIENvbHVtbiB3aWR0aCBpbiBwaXhlbHMgKGFkb3B0cyBkZWZhdWx0IHZhbHVlIGlmIHVuZGVmaW5lZCBkdXJpbmcgY2FzY2FkZSkuCgkJICogSWYgeW91IHNwZWNpZnkgdGhlIHdpZHRoIG9mIHRoZSBjb2x1bW5zLCBidXQgbm90IHRoZSBjb3VudCwgVGV4dExheW91dCB3aWxsIGNyZWF0ZSBhcyBtYW55IGNvbHVtbnMgb2YgdGhhdCB3aWR0aCBhcyBwb3NzaWJsZSwgZ2l2ZW4gdGhlICBjb250YWluZXIgd2lkdGggYW5kIDxjb2RlPmNvbHVtbkdhcDwvY29kZT4gc2V0dGluZ3MuIEFueSByZW1haW5kZXIgc3BhY2UgaXMgbGVmdCBhZnRlciB0aGUgbGFzdCBjb2x1bW4uIFZhbHVlIGlzIGEgTnVtYmVyLgoJCSAqIDxwPkxlZ2FsIHZhbHVlcyBhcyBhIHN0cmluZyBhcmUgRm9ybWF0VmFsdWUuQVVUTywgRm9ybWF0VmFsdWUuSU5IRVJJVCBhbmQgbnVtYmVycyBmcm9tIDAgdG8gODAwMC48L3A+CgkJICogPHA+RGVmYXVsdCB2YWx1ZSBpcyB1bmRlZmluZWQgaW5kaWNhdGluZyBub3Qgc2V0LjwvcD4KCQkgKiA8cD5JZiB1bmRlZmluZWQgZHVyaW5nIHRoZSBjYXNjYWRlIHRoaXMgcHJvcGVydHkgd2lsbCBoYXZlIGEgdmFsdWUgb2YgRm9ybWF0VmFsdWUuQVVUTy48L3A+CgkJICogCgkJICogQHRocm93cyBSYW5nZUVycm9yIHdoZW4gc2V0IHZhbHVlIGlzIG5vdCB3aXRoaW4gcmFuZ2UgZm9yIHRoaXMgcHJvcGVydHkKCQkgKiAKCQkgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKCQkgKiBAbGFuZ3ZlcnNpb24gMy4wCgkJICogQHNlZSBmbGFzaHgudGV4dExheW91dC5mb3JtYXRzLkZvcm1hdFZhbHVlCgkJICovCgkJcHVibGljIGZ1bmN0aW9uIGdldCBjb2x1bW5XaWR0aCgpOioKCQl7IHJldHVybiBfc3R5bGVzLmNvbHVtbldpZHRoOyB9CgkJcHVibGljIGZ1bmN0aW9uIHNldCBjb2x1bW5XaWR0aCh2YWx1ZToqKTp2b2lkCgkJeyBzZXRTdHlsZUJ5UHJvcGVydHkoVGV4dExheW91dEZvcm1hdC5jb2x1bW5XaWR0aFByb3BlcnR5LHZhbHVlKTsgfQoKCQkvKioKCQkgKiBTcGVjaWZpZXMgdGhlIGJhc2VsaW5lIHBvc2l0aW9uIG9mIHRoZSBmaXJzdCBsaW5lIGluIHRoZSBjb250YWluZXIuIFdoaWNoIGJhc2VsaW5lIHRoaXMgcHJvcGVydHkgcmVmZXJzIHRvIGRlcGVuZHMgb24gdGhlIGNvbnRhaW5lci1sZXZlbCBsb2NhbGUuICBGb3IgSmFwYW5lc2UgYW5kIENoaW5lc2UsIGl0IGlzIDxjb2RlPlRleHRCYXNlbGluZS5JREVPR1JBUEhJQ19CT1RUT008L2NvZGU+OyBmb3IgYWxsIG90aGVycyBpdCBpcyA8Y29kZT5UZXh0QmFzZWxpbmUuUk9NQU48L2NvZGU+LgoJCSAqIFRoZSBvZmZzZXQgZnJvbSB0aGUgdG9wIGluc2V0IChvciByaWdodCBpbnNldCBpZiA8Y29kZT5ibG9ja1Byb2dyZXNzaW9uPC9jb2RlPiBpcyBSTCkgb2YgdGhlIGNvbnRhaW5lciB0byB0aGUgYmFzZWxpbmUgb2YgdGhlIGZpcnN0IGxpbmUgY2FuIGJlIGVpdGhlciA8Y29kZT5CYXNlbGluZU9mZnNldC5BU0NFTlQ8L2NvZGU+LCBtZWFuaW5nIGVxdWFsIHRvIHRoZSBhc2NlbnQgb2YgdGhlIGxpbmUsIDxjb2RlPkJhc2VsaW5lT2Zmc2V0LkxJTkVfSEVJR0hUPC9jb2RlPiwgbWVhbmluZyBlcXVhbCB0byB0aGUgaGVpZ2h0IG9mIHRoYXQgZmlyc3QgbGluZSwgb3IgYW55IGZpeGVkLXZhbHVlIG51bWJlciB0byBzcGVjaWZ5IGFuIGFic29sdXRlIGRpc3RhbmNlLiA8Y29kZT5CYXNlbGluZU9mZnNldC5BVVRPPC9jb2RlPiBhbGlnbnMgdGhlIGFzY2VudCBvZiB0aGUgbGluZSB3aXRoIHRoZSBjb250YWluZXIgdG9wIGluc2V0LjxwPjxpbWcgc3JjPScuLi8uLi8uLi9pbWFnZXMvdGV4dExheW91dF9GQk8xLnBuZycgYWx0PSdmaXJzdEJhc2VsaW5lT2Zmc2V0MScgLz48aW1nIHNyYz0nLi4vLi4vLi4vaW1hZ2VzL3RleHRMYXlvdXRfRkJPMi5wbmcnIGFsdD0nZmlyc3RCYXNlbGluZU9mZnNldDInIC8+PGltZyBzcmM9Jy4uLy4uLy4uL2ltYWdlcy90ZXh0TGF5b3V0X0ZCTzMucG5nJyBhbHQ9J2ZpcnN0QmFzZWxpbmVPZmZzZXQzJyAvPjxpbWcgc3JjPScuLi8uLi8uLi9pbWFnZXMvdGV4dExheW91dF9GQk80LnBuZycgYWx0PSdmaXJzdEJhc2VsaW5lT2Zmc2V0NCcgLz48L3A+CgkJICogPHA+TGVnYWwgdmFsdWVzIGFzIGEgc3RyaW5nIGFyZSBCYXNlbGluZU9mZnNldC5BVVRPLCBCYXNlbGluZU9mZnNldC5BU0NFTlQsIEJhc2VsaW5lT2Zmc2V0LkxJTkVfSEVJR0hULCBGb3JtYXRWYWx1ZS5JTkhFUklUIGFuZCBudW1iZXJzIGZyb20gMCB0byAxMDAwLjwvcD4KCQkgKiA8cD5EZWZhdWx0IHZhbHVlIGlzIHVuZGVmaW5lZCBpbmRpY2F0aW5nIG5vdCBzZXQuPC9wPgoJCSAqIDxwPklmIHVuZGVmaW5lZCBkdXJpbmcgdGhlIGNhc2NhZGUgdGhpcyBwcm9wZXJ0eSB3aWxsIGluaGVyaXQgaXRzIHZhbHVlIGZyb20gYW4gYW5jZXN0b3IuIElmIG5vIGFuY2VzdG9yIGhhcyBzZXQgdGhpcyBwcm9wZXJ0eSwgaXQgd2lsbCBoYXZlIGEgdmFsdWUgb2YgQmFzZWxpbmVPZmZzZXQuQVVUTy48L3A+CgkJICogCgkJICogQHRocm93cyBSYW5nZUVycm9yIHdoZW4gc2V0IHZhbHVlIGlzIG5vdCB3aXRoaW4gcmFuZ2UgZm9yIHRoaXMgcHJvcGVydHkKCQkgKiAKCQkgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKCQkgKiBAbGFuZ3ZlcnNpb24gMy4wCgkJICogQHNlZSBmbGFzaHgudGV4dExheW91dC5mb3JtYXRzLkJhc2VsaW5lT2Zmc2V0CgkJICovCgkJcHVibGljIGZ1bmN0aW9uIGdldCBmaXJzdEJhc2VsaW5lT2Zmc2V0KCk6KgoJCXsgcmV0dXJuIF9zdHlsZXMuZmlyc3RCYXNlbGluZU9mZnNldDsgfQoJCXB1YmxpYyBmdW5jdGlvbiBzZXQgZmlyc3RCYXNlbGluZU9mZnNldCh2YWx1ZToqKTp2b2lkCgkJeyBzZXRTdHlsZUJ5UHJvcGVydHkoVGV4dExheW91dEZvcm1hdC5maXJzdEJhc2VsaW5lT2Zmc2V0UHJvcGVydHksdmFsdWUpOyB9CgoJCVtJbnNwZWN0YWJsZShlbnVtZXJhdGlvbj0idG9wLG1pZGRsZSxib3R0b20sanVzdGlmeSxpbmhlcml0IildCgkJLyoqCgkJICogVmVydGljYWwgYWxpZ25tZW50IG9yIGp1c3RpZmljYXRpb24gKGFkb3B0cyBkZWZhdWx0IHZhbHVlIGlmIHVuZGVmaW5lZCBkdXJpbmcgY2FzY2FkZSkuCgkJICogRGV0ZXJtaW5lcyBob3cgVGV4dEZsb3cgZWxlbWVudHMgYWxpZ24gd2l0aGluIHRoZSBjb250YWluZXIuCgkJICogPHA+TGVnYWwgdmFsdWVzIGFyZSBWZXJ0aWNhbEFsaWduLlRPUCwgVmVydGljYWxBbGlnbi5NSURETEUsIFZlcnRpY2FsQWxpZ24uQk9UVE9NLCBWZXJ0aWNhbEFsaWduLkpVU1RJRlksIEZvcm1hdFZhbHVlLklOSEVSSVQuPC9wPgoJCSAqIDxwPkRlZmF1bHQgdmFsdWUgaXMgdW5kZWZpbmVkIGluZGljYXRpbmcgbm90IHNldC48L3A+CgkJICogPHA+SWYgdW5kZWZpbmVkIGR1cmluZyB0aGUgY2FzY2FkZSB0aGlzIHByb3BlcnR5IHdpbGwgaGF2ZSBhIHZhbHVlIG9mIFZlcnRpY2FsQWxpZ24uVE9QLjwvcD4KCQkgKiAKCQkgKiBAdGhyb3dzIFJhbmdlRXJyb3Igd2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eQoJCSAqIAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCgkJICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQoJCSAqIEBsYW5ndmVyc2lvbiAzLjAKCQkgKiBAc2VlIGZsYXNoeC50ZXh0TGF5b3V0LmZvcm1hdHMuVmVydGljYWxBbGlnbgoJCSAqLwoJCXB1YmxpYyBmdW5jdGlvbiBnZXQgdmVydGljYWxBbGlnbigpOioKCQl7IHJldHVybiBfc3R5bGVzLnZlcnRpY2FsQWxpZ247IH0KCQlwdWJsaWMgZnVuY3Rpb24gc2V0IHZlcnRpY2FsQWxpZ24odmFsdWU6Kik6dm9pZAoJCXsgc2V0U3R5bGVCeVByb3BlcnR5KFRleHRMYXlvdXRGb3JtYXQudmVydGljYWxBbGlnblByb3BlcnR5LHZhbHVlKTsgfQoKCQlbSW5zcGVjdGFibGUoZW51bWVyYXRpb249InJsLHRiLGluaGVyaXQiKV0KCQkvKioKCQkgKiBTcGVjaWZpZXMgYSB2ZXJ0aWNhbCBvciBob3Jpem9udGFsIHByb2dyZXNzaW9uIG9mIGxpbmUgcGxhY2VtZW50LgoJCSAqIExpbmVzIGFyZSBlaXRoZXIgcGxhY2VkIHRvcC10by1ib3R0b20gKDxjb2RlPkJsb2NrUHJvZ3Jlc3Npb24uVEI8L2NvZGU+LCB1c2VkIGZvciBob3Jpem9udGFsIHRleHQpIG9yIHJpZ2h0LXRvLWxlZnQgKDxjb2RlPkJsb2NrUHJvZ3Jlc3Npb24uUkw8L2NvZGU+LCB1c2VkIGZvciB2ZXJ0aWNhbCB0ZXh0KS4KCQkgKiA8cD5MZWdhbCB2YWx1ZXMgYXJlIEJsb2NrUHJvZ3Jlc3Npb24uUkwsIEJsb2NrUHJvZ3Jlc3Npb24uVEIsIEZvcm1hdFZhbHVlLklOSEVSSVQuPC9wPgoJCSAqIDxwPkRlZmF1bHQgdmFsdWUgaXMgdW5kZWZpbmVkIGluZGljYXRpbmcgbm90IHNldC48L3A+CgkJICogPHA+SWYgdW5kZWZpbmVkIGR1cmluZyB0aGUgY2FzY2FkZSB0aGlzIHByb3BlcnR5IHdpbGwgaW5oZXJpdCBpdHMgdmFsdWUgZnJvbSBhbiBhbmNlc3Rvci4gSWYgbm8gYW5jZXN0b3IgaGFzIHNldCB0aGlzIHByb3BlcnR5LCBpdCB3aWxsIGhhdmUgYSB2YWx1ZSBvZiBCbG9ja1Byb2dyZXNzaW9uLlRCLjwvcD4KCQkgKiAKCQkgKiBAdGhyb3dzIFJhbmdlRXJyb3Igd2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eQoJCSAqIAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCgkJICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQoJCSAqIEBsYW5ndmVyc2lvbiAzLjAKCQkgKiBAc2VlIGZsYXNoeC50ZXh0TGF5b3V0LmZvcm1hdHMuQmxvY2tQcm9ncmVzc2lvbgoJCSAqLwoJCXB1YmxpYyBmdW5jdGlvbiBnZXQgYmxvY2tQcm9ncmVzc2lvbigpOioKCQl7IHJldHVybiBfc3R5bGVzLmJsb2NrUHJvZ3Jlc3Npb247IH0KCQlwdWJsaWMgZnVuY3Rpb24gc2V0IGJsb2NrUHJvZ3Jlc3Npb24odmFsdWU6Kik6dm9pZAoJCXsgc2V0U3R5bGVCeVByb3BlcnR5KFRleHRMYXlvdXRGb3JtYXQuYmxvY2tQcm9ncmVzc2lvblByb3BlcnR5LHZhbHVlKTsgfQoKCQlbSW5zcGVjdGFibGUoZW51bWVyYXRpb249ImV4cGxpY2l0LHRvRml0LGluaGVyaXQiKV0KCQkvKioKCQkgKiBDb250cm9scyB3b3JkIHdyYXBwaW5nIHdpdGhpbiB0aGUgY29udGFpbmVyIChhZG9wdHMgZGVmYXVsdCB2YWx1ZSBpZiB1bmRlZmluZWQgZHVyaW5nIGNhc2NhZGUpLgoJCSAqIFRleHQgaW4gdGhlIGNvbnRhaW5lciBtYXkgYmUgc2V0IHRvIGZpdCB0aGUgd2lkdGggb2YgdGhlIGNvbnRhaW5lciAoPGNvZGU+TGluZUJyZWFrLlRPX0ZJVDwvY29kZT4pLCBvciBjYW4gYmUgc2V0IHRvIGJyZWFrIG9ubHkgYXQgZXhwbGljaXQgcmV0dXJuIG9yIGxpbmUgZmVlZCBjaGFyYWN0ZXJzICg8Y29kZT5MaW5lQnJlYWsuRVhQTElDSVQ8L2NvZGU+KS4KCQkgKiA8cD5MZWdhbCB2YWx1ZXMgYXJlIExpbmVCcmVhay5FWFBMSUNJVCwgTGluZUJyZWFrLlRPX0ZJVCwgRm9ybWF0VmFsdWUuSU5IRVJJVC48L3A+CgkJICogPHA+RGVmYXVsdCB2YWx1ZSBpcyB1bmRlZmluZWQgaW5kaWNhdGluZyBub3Qgc2V0LjwvcD4KCQkgKiA8cD5JZiB1bmRlZmluZWQgZHVyaW5nIHRoZSBjYXNjYWRlIHRoaXMgcHJvcGVydHkgd2lsbCBoYXZlIGEgdmFsdWUgb2YgTGluZUJyZWFrLlRPX0ZJVC48L3A+CgkJICogCgkJICogQHRocm93cyBSYW5nZUVycm9yIHdoZW4gc2V0IHZhbHVlIGlzIG5vdCB3aXRoaW4gcmFuZ2UgZm9yIHRoaXMgcHJvcGVydHkKCQkgKiAKCQkgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKCQkgKiBAbGFuZ3ZlcnNpb24gMy4wCgkJICogQHNlZSBmbGFzaHgudGV4dExheW91dC5mb3JtYXRzLkxpbmVCcmVhawoJCSAqLwoJCXB1YmxpYyBmdW5jdGlvbiBnZXQgbGluZUJyZWFrKCk6KgoJCXsgcmV0dXJuIF9zdHlsZXMubGluZUJyZWFrOyB9CgkJcHVibGljIGZ1bmN0aW9uIHNldCBsaW5lQnJlYWsodmFsdWU6Kik6dm9pZAoJCXsgc2V0U3R5bGVCeVByb3BlcnR5KFRleHRMYXlvdXRGb3JtYXQubGluZUJyZWFrUHJvcGVydHksdmFsdWUpOyB9CgoJCVtJbnNwZWN0YWJsZShlbnVtZXJhdGlvbj0idXBwZXJBbHBoYSxsb3dlckFscGhhLHVwcGVyUm9tYW4sbG93ZXJSb21hbixub25lLGRpc2MsY2lyY2xlLHNxdWFyZSxib3gsY2hlY2ssZGlhbW9uZCxoeXBoZW4sYXJhYmljSW5kaWMsYmVuZ2FsaSxkZWNpbWFsLGRlY2ltYWxMZWFkaW5nWmVybyxkZXZhbmFnYXJpLGd1amFyYXRpLGd1cm11a2hpLGthbm5hZGEscGVyc2lhbix0aGFpLHVyZHUsY2prRWFydGhseUJyYW5jaCxjamtIZWF2ZW5seVN0ZW0saGFuZ3VsLGhhbmd1bENvbnN0YW50LGhpcmFnYW5hLGhpcmFnYW5hSXJvaGEsa2F0YWthbmEsa2F0YWthbmFJcm9oYSxsb3dlckFscGhhLGxvd2VyR3JlZWssbG93ZXJMYXRpbix1cHBlckFscGhhLHVwcGVyR3JlZWssdXBwZXJMYXRpbixpbmhlcml0IildCgkJLyoqCgkJICogPHA+TGVnYWwgdmFsdWVzIGFyZSBMaXN0U3R5bGVUeXBlLlVQUEVSX0FMUEhBLCBMaXN0U3R5bGVUeXBlLkxPV0VSX0FMUEhBLCBMaXN0U3R5bGVUeXBlLlVQUEVSX1JPTUFOLCBMaXN0U3R5bGVUeXBlLkxPV0VSX1JPTUFOLCBMaXN0U3R5bGVUeXBlLk5PTkUsIExpc3RTdHlsZVR5cGUuRElTQywgTGlzdFN0eWxlVHlwZS5DSVJDTEUsIExpc3RTdHlsZVR5cGUuU1FVQVJFLCBMaXN0U3R5bGVUeXBlLkJPWCwgTGlzdFN0eWxlVHlwZS5DSEVDSywgTGlzdFN0eWxlVHlwZS5ESUFNT05ELCBMaXN0U3R5bGVUeXBlLkhZUEhFTiwgTGlzdFN0eWxlVHlwZS5BUkFCSUNfSU5ESUMsIExpc3RTdHlsZVR5cGUuQkVOR0FMSSwgTGlzdFN0eWxlVHlwZS5ERUNJTUFMLCBMaXN0U3R5bGVUeXBlLkRFQ0lNQUxfTEVBRElOR19aRVJPLCBMaXN0U3R5bGVUeXBlLkRFVkFOQUdBUkksIExpc3RTdHlsZVR5cGUuR1VKQVJBVEksIExpc3RTdHlsZVR5cGUuR1VSTVVLSEksIExpc3RTdHlsZVR5cGUuS0FOTkFEQSwgTGlzdFN0eWxlVHlwZS5QRVJTSUFOLCBMaXN0U3R5bGVUeXBlLlRIQUksIExpc3RTdHlsZVR5cGUuVVJEVSwgTGlzdFN0eWxlVHlwZS5DSktfRUFSVEhMWV9CUkFOQ0gsIExpc3RTdHlsZVR5cGUuQ0pLX0hFQVZFTkxZX1NURU0sIExpc3RTdHlsZVR5cGUuSEFOR1VMLCBMaXN0U3R5bGVUeXBlLkhBTkdVTF9DT05TVEFOVCwgTGlzdFN0eWxlVHlwZS5ISVJBR0FOQSwgTGlzdFN0eWxlVHlwZS5ISVJBR0FOQV9JUk9IQSwgTGlzdFN0eWxlVHlwZS5LQVRBS0FOQSwgTGlzdFN0eWxlVHlwZS5LQVRBS0FOQV9JUk9IQSwgTGlzdFN0eWxlVHlwZS5MT1dFUl9BTFBIQSwgTGlzdFN0eWxlVHlwZS5MT1dFUl9HUkVFSywgTGlzdFN0eWxlVHlwZS5MT1dFUl9MQVRJTiwgTGlzdFN0eWxlVHlwZS5VUFBFUl9BTFBIQSwgTGlzdFN0eWxlVHlwZS5VUFBFUl9HUkVFSywgTGlzdFN0eWxlVHlwZS5VUFBFUl9MQVRJTiwgRm9ybWF0VmFsdWUuSU5IRVJJVC48L3A+CgkJICogPHA+RGVmYXVsdCB2YWx1ZSBpcyB1bmRlZmluZWQgaW5kaWNhdGluZyBub3Qgc2V0LjwvcD4KCQkgKiA8cD5JZiB1bmRlZmluZWQgZHVyaW5nIHRoZSBjYXNjYWRlIHRoaXMgcHJvcGVydHkgd2lsbCBpbmhlcml0IGl0cyB2YWx1ZSBmcm9tIGFuIGFuY2VzdG9yLiBJZiBubyBhbmNlc3RvciBoYXMgc2V0IHRoaXMgcHJvcGVydHksIGl0IHdpbGwgaGF2ZSBhIHZhbHVlIG9mIExpc3RTdHlsZVR5cGUuRElTQy48L3A+CgkJICogCgkJICogQHRocm93cyBSYW5nZUVycm9yIHdoZW4gc2V0IHZhbHVlIGlzIG5vdCB3aXRoaW4gcmFuZ2UgZm9yIHRoaXMgcHJvcGVydHkKCQkgKiAKCQkgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKCQkgKiBAbGFuZ3ZlcnNpb24gMy4wCgkJICogQHNlZSBmbGFzaHgudGV4dExheW91dC5mb3JtYXRzLkxpc3RTdHlsZVR5cGUKCQkgKi8KCQlwdWJsaWMgZnVuY3Rpb24gZ2V0IGxpc3RTdHlsZVR5cGUoKToqCgkJeyByZXR1cm4gX3N0eWxlcy5saXN0U3R5bGVUeXBlOyB9CgkJcHVibGljIGZ1bmN0aW9uIHNldCBsaXN0U3R5bGVUeXBlKHZhbHVlOiopOnZvaWQKCQl7IHNldFN0eWxlQnlQcm9wZXJ0eShUZXh0TGF5b3V0Rm9ybWF0Lmxpc3RTdHlsZVR5cGVQcm9wZXJ0eSx2YWx1ZSk7IH0KCgkJW0luc3BlY3RhYmxlKGVudW1lcmF0aW9uPSJpbnNpZGUsb3V0c2lkZSxpbmhlcml0IildCgkJLyoqCgkJICogPHA+TGVnYWwgdmFsdWVzIGFyZSBMaXN0U3R5bGVQb3NpdGlvbi5JTlNJREUsIExpc3RTdHlsZVBvc2l0aW9uLk9VVFNJREUsIEZvcm1hdFZhbHVlLklOSEVSSVQuPC9wPgoJCSAqIDxwPkRlZmF1bHQgdmFsdWUgaXMgdW5kZWZpbmVkIGluZGljYXRpbmcgbm90IHNldC48L3A+CgkJICogPHA+SWYgdW5kZWZpbmVkIGR1cmluZyB0aGUgY2FzY2FkZSB0aGlzIHByb3BlcnR5IHdpbGwgaW5oZXJpdCBpdHMgdmFsdWUgZnJvbSBhbiBhbmNlc3Rvci4gSWYgbm8gYW5jZXN0b3IgaGFzIHNldCB0aGlzIHByb3BlcnR5LCBpdCB3aWxsIGhhdmUgYSB2YWx1ZSBvZiBMaXN0U3R5bGVQb3NpdGlvbi5PVVRTSURFLjwvcD4KCQkgKiAKCQkgKiBAdGhyb3dzIFJhbmdlRXJyb3Igd2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eQoJCSAqIAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCgkJICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQoJCSAqIEBsYW5ndmVyc2lvbiAzLjAKCQkgKiBAc2VlIGZsYXNoeC50ZXh0TGF5b3V0LmZvcm1hdHMuTGlzdFN0eWxlUG9zaXRpb24KCQkgKi8KCQlwdWJsaWMgZnVuY3Rpb24gZ2V0IGxpc3RTdHlsZVBvc2l0aW9uKCk6KgoJCXsgcmV0dXJuIF9zdHlsZXMubGlzdFN0eWxlUG9zaXRpb247IH0KCQlwdWJsaWMgZnVuY3Rpb24gc2V0IGxpc3RTdHlsZVBvc2l0aW9uKHZhbHVlOiopOnZvaWQKCQl7IHNldFN0eWxlQnlQcm9wZXJ0eShUZXh0TGF5b3V0Rm9ybWF0Lmxpc3RTdHlsZVBvc2l0aW9uUHJvcGVydHksdmFsdWUpOyB9CgoJCS8qKgoJCSAqIFRoaXMgc3BlY2lmaWVzIGFuIGF1dG8gaW5kZW50IGZvciB0aGUgc3RhcnQgZWRnZSBvZiBsaXN0cyB3aGVuIHRoZSBwYWRkaW5nIHZhbHVlIG9mIHRoZSBsaXN0IG9uIHRoYXQgc2lkZSBpcyA8Y29kZT5hdXRvPC9jb2RlPi4KCQkgKiA8cD5MZWdhbCB2YWx1ZXMgYXJlIG51bWJlcnMgZnJvbSAtMTAwMCB0byAxMDAwIGFuZCBGb3JtYXRWYWx1ZS5JTkhFUklULjwvcD4KCQkgKiA8cD5EZWZhdWx0IHZhbHVlIGlzIHVuZGVmaW5lZCBpbmRpY2F0aW5nIG5vdCBzZXQuPC9wPgoJCSAqIDxwPklmIHVuZGVmaW5lZCBkdXJpbmcgdGhlIGNhc2NhZGUgdGhpcyBwcm9wZXJ0eSB3aWxsIGluaGVyaXQgaXRzIHZhbHVlIGZyb20gYW4gYW5jZXN0b3IuIElmIG5vIGFuY2VzdG9yIGhhcyBzZXQgdGhpcyBwcm9wZXJ0eSwgaXQgd2lsbCBoYXZlIGEgdmFsdWUgb2YgNDAuPC9wPgoJCSAqIAoJCSAqIEB0aHJvd3MgUmFuZ2VFcnJvciB3aGVuIHNldCB2YWx1ZSBpcyBub3Qgd2l0aGluIHJhbmdlIGZvciB0aGlzIHByb3BlcnR5CgkJICogCgkJICogQHBsYXllcnZlcnNpb24gRmxhc2ggMTAKCQkgKiBAcGxheWVydmVyc2lvbiBBSVIgMS41CgkJICogQGxhbmd2ZXJzaW9uIDMuMAoJCSAqLwoJCXB1YmxpYyBmdW5jdGlvbiBnZXQgbGlzdEF1dG9QYWRkaW5nKCk6KgoJCXsgcmV0dXJuIF9zdHlsZXMubGlzdEF1dG9QYWRkaW5nOyB9CgkJcHVibGljIGZ1bmN0aW9uIHNldCBsaXN0QXV0b1BhZGRpbmcodmFsdWU6Kik6dm9pZAoJCXsgc2V0U3R5bGVCeVByb3BlcnR5KFRleHRMYXlvdXRGb3JtYXQubGlzdEF1dG9QYWRkaW5nUHJvcGVydHksdmFsdWUpOyB9CgoJCVtJbnNwZWN0YWJsZShlbnVtZXJhdGlvbj0ic3RhcnQsZW5kLGxlZnQscmlnaHQsYm90aCxub25lLGluaGVyaXQiKV0KCQkvKioKCQkgKiBDb250cm9scyBob3cgdGV4dCB3cmFwcyBhcm91bmQgYSBmbG9hdC4gQSB2YWx1ZSBvZiBub25lIGFsbG93cyB0aGUgdGV4dCB0byB3cmFwIG1vc3QgY2xvc2VseSBhcm91bmQgYSBmbG9hdC4gQSB2YWx1ZSBvZiBsZWZ0IGNhdXNlcyB0aGUgdGV4dCB0byBza2lwIG92ZXIgYW55IHBvcnRpb24gb2YgdGhlIGNvbnRhaW5lciB0aGF0IGhhcyBhIGxlZnQgZmxvYXQsIGFuZCBhIHZhbHVlIG9mIHJpZ2h0IGNhdXNlcyB0aGUgdGV4dCB0byBza2lwIG92ZXIgYW55IHBvcnRpb24gb2YgdGhlIGNvbnRhaW5lciB0aGF0IGhhcyBhIHJpZ2h0IGZsb2F0LiBBIHZhbHVlIG9mIGJvdGggY2F1c2VzIHRoZSB0ZXh0IHRvIHNraXAgb3ZlciBhbnkgZmxvYXRzLgoJCSAqIDxwPkxlZ2FsIHZhbHVlcyBhcmUgQ2xlYXJGbG9hdHMuU1RBUlQsIENsZWFyRmxvYXRzLkVORCwgQ2xlYXJGbG9hdHMuTEVGVCwgQ2xlYXJGbG9hdHMuUklHSFQsIENsZWFyRmxvYXRzLkJPVEgsIENsZWFyRmxvYXRzLk5PTkUsIEZvcm1hdFZhbHVlLklOSEVSSVQuPC9wPgoJCSAqIDxwPkRlZmF1bHQgdmFsdWUgaXMgdW5kZWZpbmVkIGluZGljYXRpbmcgbm90IHNldC48L3A+CgkJICogPHA+SWYgdW5kZWZpbmVkIGR1cmluZyB0aGUgY2FzY2FkZSB0aGlzIHByb3BlcnR5IHdpbGwgaGF2ZSBhIHZhbHVlIG9mIENsZWFyRmxvYXRzLk5PTkUuPC9wPgoJCSAqIEBzZWUgZmxhc2h4LnRleHRMYXlvdXQuZm9ybWF0cy5DbGVhckZsb2F0cwoJCSAqIAoJCSAqIEB0aHJvd3MgUmFuZ2VFcnJvciB3aGVuIHNldCB2YWx1ZSBpcyBub3Qgd2l0aGluIHJhbmdlIGZvciB0aGlzIHByb3BlcnR5CgkJICogCgkJICogQHBsYXllcnZlcnNpb24gRmxhc2ggMTAKCQkgKiBAcGxheWVydmVyc2lvbiBBSVIgMS41CgkJICogQGxhbmd2ZXJzaW9uIDMuMAoJCSAqIEBzZWUgZmxhc2h4LnRleHRMYXlvdXQuZm9ybWF0cy5DbGVhckZsb2F0cwoJCSAqLwoJCXB1YmxpYyBmdW5jdGlvbiBnZXQgY2xlYXJGbG9hdHMoKToqCgkJeyByZXR1cm4gX3N0eWxlcy5jbGVhckZsb2F0czsgfQoJCXB1YmxpYyBmdW5jdGlvbiBzZXQgY2xlYXJGbG9hdHModmFsdWU6Kik6dm9pZAoJCXsgc2V0U3R5bGVCeVByb3BlcnR5KFRleHRMYXlvdXRGb3JtYXQuY2xlYXJGbG9hdHNQcm9wZXJ0eSx2YWx1ZSk7IH0KCgkJLyoqCgkJICogQXNzaWducyBhbiBpZGVudGlmeWluZyBjbGFzcyB0byB0aGUgZWxlbWVudCwgbWFraW5nIGl0IHBvc3NpYmxlIHRvIHNldCBhIHN0eWxlIGZvciB0aGUgZWxlbWVudCBieSByZWZlcmVuY2luZyB0aGUgPGNvZGU+c3R5bGVOYW1lPC9jb2RlPi4KCQkgKiA8cD5EZWZhdWx0IHZhbHVlIGlzIHVuZGVmaW5lZCBpbmRpY2F0aW5nIG5vdCBzZXQuPC9wPgoJCSAqIDxwPklmIHVuZGVmaW5lZCBkdXJpbmcgdGhlIGNhc2NhZGUgdGhpcyBwcm9wZXJ0eSB3aWxsIGhhdmUgYSB2YWx1ZSBvZiBudWxsLjwvcD4KCQkgKiAKCQkgKiBAdGhyb3dzIFJhbmdlRXJyb3Igd2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eQoJCSAqIAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCgkJICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQoJCSAqIEBsYW5ndmVyc2lvbiAzLjAKCQkgKi8KCQlwdWJsaWMgZnVuY3Rpb24gZ2V0IHN0eWxlTmFtZSgpOioKCQl7IHJldHVybiBfc3R5bGVzLnN0eWxlTmFtZTsgfQoJCXB1YmxpYyBmdW5jdGlvbiBzZXQgc3R5bGVOYW1lKHZhbHVlOiopOnZvaWQKCQl7IHNldFN0eWxlQnlQcm9wZXJ0eShUZXh0TGF5b3V0Rm9ybWF0LnN0eWxlTmFtZVByb3BlcnR5LHZhbHVlKTsgfQoKCQkvKioKCQkgKiBEZWZpbmVzIHRoZSBmb3JtYXR0aW5nIGF0dHJpYnV0ZXMgdXNlZCBmb3IgbGlua3MgaW4gbm9ybWFsIHN0YXRlLiBUaGlzIHZhbHVlIHdpbGwgY2FzY2FkZSBkb3duIHRoZSBoaWVyYXJjaHkgYW5kIGFwcGx5IHRvIGFueSBsaW5rcyB0aGF0IGFyZSBkZXNjZW5kYW50cy4KCQkgKiBBY2NlcHRzIDxjb2RlPmluaGVyaXQ8L2NvZGU+LCBhbiA8Y29kZT5JVGV4dExheW91dEZvcm1hdDwvY29kZT4gb3IgY29udmVydHMgYW4gYXJyYXkgb2Ygb2JqZWN0cyB3aXRoIGtleSBhbmQgdmFsdWUgYXMgbWVtYmVycyB0byBhIFRleHRMYXlvdXRGb3JtYXQuCgkJICogPHA+TGVnYWwgdmFsdWVzIGluY2x1ZGUgRm9ybWF0VmFsdWUuSU5IRVJJVC48L3A+CgkJICogPHA+RGVmYXVsdCB2YWx1ZSBpcyB1bmRlZmluZWQgaW5kaWNhdGluZyBub3Qgc2V0LjwvcD4KCQkgKiA8cD5JZiB1bmRlZmluZWQgZHVyaW5nIHRoZSBjYXNjYWRlIHRoaXMgcHJvcGVydHkgd2lsbCBpbmhlcml0IGl0cyB2YWx1ZSBmcm9tIGFuIGFuY2VzdG9yLiBJZiBubyBhbmNlc3RvciBoYXMgc2V0IHRoaXMgcHJvcGVydHksIGl0IHdpbGwgaGF2ZSBhIHZhbHVlIG9mIG51bGwuPC9wPgoJCSAqIAoJCSAqIEB0aHJvd3MgUmFuZ2VFcnJvciB3aGVuIHNldCB2YWx1ZSBpcyBub3Qgd2l0aGluIHJhbmdlIGZvciB0aGlzIHByb3BlcnR5CgkJICogCgkJICogQHBsYXllcnZlcnNpb24gRmxhc2ggMTAKCQkgKiBAcGxheWVydmVyc2lvbiBBSVIgMS41CgkJICogQGxhbmd2ZXJzaW9uIDMuMAoJCSAqLwoJCXB1YmxpYyBmdW5jdGlvbiBnZXQgbGlua05vcm1hbEZvcm1hdCgpOioKCQl7IHJldHVybiBfc3R5bGVzLmxpbmtOb3JtYWxGb3JtYXQ7IH0KCQlwdWJsaWMgZnVuY3Rpb24gc2V0IGxpbmtOb3JtYWxGb3JtYXQodmFsdWU6Kik6dm9pZAoJCXsgc2V0U3R5bGVCeVByb3BlcnR5KFRleHRMYXlvdXRGb3JtYXQubGlua05vcm1hbEZvcm1hdFByb3BlcnR5LHZhbHVlKTsgfQoKCQkvKioKCQkgKiBEZWZpbmVzIHRoZSBmb3JtYXR0aW5nIGF0dHJpYnV0ZXMgdXNlZCBmb3IgbGlua3MgaW4gbm9ybWFsIHN0YXRlLiBUaGlzIHZhbHVlIHdpbGwgY2FzY2FkZSBkb3duIHRoZSBoaWVyYXJjaHkgYW5kIGFwcGx5IHRvIGFueSBsaW5rcyB0aGF0IGFyZSBkZXNjZW5kYW50cy4KCQkgKiBBY2NlcHRzIDxjb2RlPmluaGVyaXQ8L2NvZGU+LCBhbiA8Y29kZT5JVGV4dExheW91dEZvcm1hdDwvY29kZT4gb3IgY29udmVydHMgYW4gYXJyYXkgb2Ygb2JqZWN0cyB3aXRoIGtleSBhbmQgdmFsdWUgYXMgbWVtYmVycyB0byBhIFRleHRMYXlvdXRGb3JtYXQuCgkJICogPHA+TGVnYWwgdmFsdWVzIGluY2x1ZGUgRm9ybWF0VmFsdWUuSU5IRVJJVC48L3A+CgkJICogPHA+RGVmYXVsdCB2YWx1ZSBpcyB1bmRlZmluZWQgaW5kaWNhdGluZyBub3Qgc2V0LjwvcD4KCQkgKiA8cD5JZiB1bmRlZmluZWQgZHVyaW5nIHRoZSBjYXNjYWRlIHRoaXMgcHJvcGVydHkgd2lsbCBpbmhlcml0IGl0cyB2YWx1ZSBmcm9tIGFuIGFuY2VzdG9yLiBJZiBubyBhbmNlc3RvciBoYXMgc2V0IHRoaXMgcHJvcGVydHksIGl0IHdpbGwgaGF2ZSBhIHZhbHVlIG9mIG51bGwuPC9wPgoJCSAqIAoJCSAqIEB0aHJvd3MgUmFuZ2VFcnJvciB3aGVuIHNldCB2YWx1ZSBpcyBub3Qgd2l0aGluIHJhbmdlIGZvciB0aGlzIHByb3BlcnR5CgkJICogCgkJICogQHBsYXllcnZlcnNpb24gRmxhc2ggMTAKCQkgKiBAcGxheWVydmVyc2lvbiBBSVIgMS41CgkJICogQGxhbmd2ZXJzaW9uIDMuMAoJCSAqLwoJCXB1YmxpYyBmdW5jdGlvbiBnZXQgbGlua0FjdGl2ZUZvcm1hdCgpOioKCQl7IHJldHVybiBfc3R5bGVzLmxpbmtBY3RpdmVGb3JtYXQ7IH0KCQlwdWJsaWMgZnVuY3Rpb24gc2V0IGxpbmtBY3RpdmVGb3JtYXQodmFsdWU6Kik6dm9pZAoJCXsgc2V0U3R5bGVCeVByb3BlcnR5KFRleHRMYXlvdXRGb3JtYXQubGlua0FjdGl2ZUZvcm1hdFByb3BlcnR5LHZhbHVlKTsgfQoKCQkvKioKCQkgKiBEZWZpbmVzIHRoZSBmb3JtYXR0aW5nIGF0dHJpYnV0ZXMgdXNlZCBmb3IgbGlua3MgaW4gaG92ZXIgc3RhdGUsIHdoZW4gdGhlIG1vdXNlIGlzIHdpdGhpbiB0aGUgYm91bmRzIChyb2xsaW5nIG92ZXIpIGEgbGluay4gVGhpcyB2YWx1ZSB3aWxsIGNhc2NhZGUgZG93biB0aGUgaGllcmFyY2h5IGFuZCBhcHBseSB0byBhbnkgbGlua3MgdGhhdCBhcmUgZGVzY2VuZGFudHMuCgkJICogQWNjZXB0cyA8Y29kZT5pbmhlcml0PC9jb2RlPiwgYW4gPGNvZGU+SVRleHRMYXlvdXRGb3JtYXQ8L2NvZGU+IG9yIGNvbnZlcnRzIGFuIGFycmF5IG9mIG9iamVjdHMgd2l0aCBrZXkgYW5kIHZhbHVlIGFzIG1lbWJlcnMgdG8gYSBUZXh0TGF5b3V0Rm9ybWF0LgoJCSAqIDxwPkxlZ2FsIHZhbHVlcyBpbmNsdWRlIEZvcm1hdFZhbHVlLklOSEVSSVQuPC9wPgoJCSAqIDxwPkRlZmF1bHQgdmFsdWUgaXMgdW5kZWZpbmVkIGluZGljYXRpbmcgbm90IHNldC48L3A+CgkJICogPHA+SWYgdW5kZWZpbmVkIGR1cmluZyB0aGUgY2FzY2FkZSB0aGlzIHByb3BlcnR5IHdpbGwgaW5oZXJpdCBpdHMgdmFsdWUgZnJvbSBhbiBhbmNlc3Rvci4gSWYgbm8gYW5jZXN0b3IgaGFzIHNldCB0aGlzIHByb3BlcnR5LCBpdCB3aWxsIGhhdmUgYSB2YWx1ZSBvZiBudWxsLjwvcD4KCQkgKiAKCQkgKiBAdGhyb3dzIFJhbmdlRXJyb3Igd2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eQoJCSAqIAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCgkJICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQoJCSAqIEBsYW5ndmVyc2lvbiAzLjAKCQkgKi8KCQlwdWJsaWMgZnVuY3Rpb24gZ2V0IGxpbmtIb3ZlckZvcm1hdCgpOioKCQl7IHJldHVybiBfc3R5bGVzLmxpbmtIb3ZlckZvcm1hdDsgfQoJCXB1YmxpYyBmdW5jdGlvbiBzZXQgbGlua0hvdmVyRm9ybWF0KHZhbHVlOiopOnZvaWQKCQl7IHNldFN0eWxlQnlQcm9wZXJ0eShUZXh0TGF5b3V0Rm9ybWF0LmxpbmtIb3ZlckZvcm1hdFByb3BlcnR5LHZhbHVlKTsgfQoKCQkvKioKCQkgKiBEZWZpbmVzIHRoZSBmb3JtYXR0aW5nIGF0dHJpYnV0ZXMgbGlzdCBtYXJrZXJzLiBUaGlzIHZhbHVlIHdpbGwgY2FzY2FkZSBkb3duIHRoZSBoaWVyYXJjaHkgYW5kIGFwcGx5IHRvIGFueSBsaW5rcyB0aGF0IGFyZSBkZXNjZW5kYW50cy4KCQkgKiBBY2NlcHRzIDxjb2RlPmluaGVyaXQ8L2NvZGU+LCBhbiA8Y29kZT5JTGlzdE1hcmtlckZvcm1hdDwvY29kZT4gb3IgY29udmVydHMgYW4gYXJyYXkgb2Ygb2JqZWN0cyB3aXRoIGtleSBhbmQgdmFsdWUgYXMgbWVtYmVycyB0byBhIExpc3RNYXJrZXJGb3JtYXQuCgkJICogPHA+TGVnYWwgdmFsdWVzIGluY2x1ZGUgRm9ybWF0VmFsdWUuSU5IRVJJVC48L3A+CgkJICogPHA+RGVmYXVsdCB2YWx1ZSBpcyB1bmRlZmluZWQgaW5kaWNhdGluZyBub3Qgc2V0LjwvcD4KCQkgKiA8cD5JZiB1bmRlZmluZWQgZHVyaW5nIHRoZSBjYXNjYWRlIHRoaXMgcHJvcGVydHkgd2lsbCBpbmhlcml0IGl0cyB2YWx1ZSBmcm9tIGFuIGFuY2VzdG9yLiBJZiBubyBhbmNlc3RvciBoYXMgc2V0IHRoaXMgcHJvcGVydHksIGl0IHdpbGwgaGF2ZSBhIHZhbHVlIG9mIG51bGwuPC9wPgoJCSAqIAoJCSAqIEB0aHJvd3MgUmFuZ2VFcnJvciB3aGVuIHNldCB2YWx1ZSBpcyBub3Qgd2l0aGluIHJhbmdlIGZvciB0aGlzIHByb3BlcnR5CgkJICogCgkJICogQHBsYXllcnZlcnNpb24gRmxhc2ggMTAKCQkgKiBAcGxheWVydmVyc2lvbiBBSVIgMS41CgkJICogQGxhbmd2ZXJzaW9uIDMuMAoJCSAqLwoJCXB1YmxpYyBmdW5jdGlvbiBnZXQgbGlzdE1hcmtlckZvcm1hdCgpOioKCQl7IHJldHVybiBfc3R5bGVzLmxpc3RNYXJrZXJGb3JtYXQ7IH0KCQlwdWJsaWMgZnVuY3Rpb24gc2V0IGxpc3RNYXJrZXJGb3JtYXQodmFsdWU6Kik6dm9pZAoJCXsgc2V0U3R5bGVCeVByb3BlcnR5KFRleHRMYXlvdXRGb3JtYXQubGlzdE1hcmtlckZvcm1hdFByb3BlcnR5LHZhbHVlKTsgfQoKCQkvKioKCQkgKiBMZWZ0IGJvcmRlciB3aWR0aCBpbiBwaXhlbHMgKGFkb3B0cyBkZWZhdWx0IHZhbHVlIGlmIHVuZGVmaW5lZCBkdXJpbmcgY2FzY2FkZSkKCQkgKiA8cD5MZWdhbCB2YWx1ZXMgYXJlIG51bWJlcnMgZnJvbSAwIHRvIDEyOCBhbmQgRm9ybWF0VmFsdWUuSU5IRVJJVC48L3A+CgkJICogPHA+RGVmYXVsdCB2YWx1ZSBpcyB1bmRlZmluZWQgaW5kaWNhdGluZyBub3Qgc2V0LjwvcD4KCQkgKiA8cD5JZiB1bmRlZmluZWQgZHVyaW5nIHRoZSBjYXNjYWRlIHRoaXMgcHJvcGVydHkgd2lsbCBoYXZlIGEgdmFsdWUgb2YgMC48L3A+CgkJICogCgkJICogQHRocm93cyBSYW5nZUVycm9yIHdoZW4gc2V0IHZhbHVlIGlzIG5vdCB3aXRoaW4gcmFuZ2UgZm9yIHRoaXMgcHJvcGVydHkKCQkgKiAKCQkgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKCQkgKiBAbGFuZ3ZlcnNpb24gMy4wCgkJICovCgkJcHVibGljIGZ1bmN0aW9uIGdldCBib3JkZXJMZWZ0V2lkdGgoKToqCgkJeyByZXR1cm4gX3N0eWxlcy5ib3JkZXJMZWZ0V2lkdGg7IH0KCQlwdWJsaWMgZnVuY3Rpb24gc2V0IGJvcmRlckxlZnRXaWR0aCh2YWx1ZToqKTp2b2lkCgkJeyBzZXRTdHlsZUJ5UHJvcGVydHkoVGV4dExheW91dEZvcm1hdC5ib3JkZXJMZWZ0V2lkdGhQcm9wZXJ0eSx2YWx1ZSk7IH0KCgkJLyoqCgkJICogUmlnaHQgYm9yZGVyIHdpZHRoIGluIHBpeGVscyAoYWRvcHRzIGRlZmF1bHQgdmFsdWUgaWYgdW5kZWZpbmVkIGR1cmluZyBjYXNjYWRlKQoJCSAqIDxwPkxlZ2FsIHZhbHVlcyBhcmUgbnVtYmVycyBmcm9tIDAgdG8gMTI4IGFuZCBGb3JtYXRWYWx1ZS5JTkhFUklULjwvcD4KCQkgKiA8cD5EZWZhdWx0IHZhbHVlIGlzIHVuZGVmaW5lZCBpbmRpY2F0aW5nIG5vdCBzZXQuPC9wPgoJCSAqIDxwPklmIHVuZGVmaW5lZCBkdXJpbmcgdGhlIGNhc2NhZGUgdGhpcyBwcm9wZXJ0eSB3aWxsIGhhdmUgYSB2YWx1ZSBvZiAwLjwvcD4KCQkgKiAKCQkgKiBAdGhyb3dzIFJhbmdlRXJyb3Igd2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eQoJCSAqIAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCgkJICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQoJCSAqIEBsYW5ndmVyc2lvbiAzLjAKCQkgKi8KCQlwdWJsaWMgZnVuY3Rpb24gZ2V0IGJvcmRlclJpZ2h0V2lkdGgoKToqCgkJeyByZXR1cm4gX3N0eWxlcy5ib3JkZXJSaWdodFdpZHRoOyB9CgkJcHVibGljIGZ1bmN0aW9uIHNldCBib3JkZXJSaWdodFdpZHRoKHZhbHVlOiopOnZvaWQKCQl7IHNldFN0eWxlQnlQcm9wZXJ0eShUZXh0TGF5b3V0Rm9ybWF0LmJvcmRlclJpZ2h0V2lkdGhQcm9wZXJ0eSx2YWx1ZSk7IH0KCgkJLyoqCgkJICogVG9wIGJvcmRlciB3aWR0aCBpbiBwaXhlbHMgKGFkb3B0cyBkZWZhdWx0IHZhbHVlIGlmIHVuZGVmaW5lZCBkdXJpbmcgY2FzY2FkZSkKCQkgKiA8cD5MZWdhbCB2YWx1ZXMgYXJlIG51bWJlcnMgZnJvbSAwIHRvIDEyOCBhbmQgRm9ybWF0VmFsdWUuSU5IRVJJVC48L3A+CgkJICogPHA+RGVmYXVsdCB2YWx1ZSBpcyB1bmRlZmluZWQgaW5kaWNhdGluZyBub3Qgc2V0LjwvcD4KCQkgKiA8cD5JZiB1bmRlZmluZWQgZHVyaW5nIHRoZSBjYXNjYWRlIHRoaXMgcHJvcGVydHkgd2lsbCBoYXZlIGEgdmFsdWUgb2YgMC48L3A+CgkJICogCgkJICogQHRocm93cyBSYW5nZUVycm9yIHdoZW4gc2V0IHZhbHVlIGlzIG5vdCB3aXRoaW4gcmFuZ2UgZm9yIHRoaXMgcHJvcGVydHkKCQkgKiAKCQkgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKCQkgKiBAbGFuZ3ZlcnNpb24gMy4wCgkJICovCgkJcHVibGljIGZ1bmN0aW9uIGdldCBib3JkZXJUb3BXaWR0aCgpOioKCQl7IHJldHVybiBfc3R5bGVzLmJvcmRlclRvcFdpZHRoOyB9CgkJcHVibGljIGZ1bmN0aW9uIHNldCBib3JkZXJUb3BXaWR0aCh2YWx1ZToqKTp2b2lkCgkJeyBzZXRTdHlsZUJ5UHJvcGVydHkoVGV4dExheW91dEZvcm1hdC5ib3JkZXJUb3BXaWR0aFByb3BlcnR5LHZhbHVlKTsgfQoKCQkvKioKCQkgKiBCb3R0b20gYm9yZGVyIHdpZHRoIGluIHBpeGVscyAoYWRvcHRzIGRlZmF1bHQgdmFsdWUgaWYgdW5kZWZpbmVkIGR1cmluZyBjYXNjYWRlKQoJCSAqIDxwPkxlZ2FsIHZhbHVlcyBhcmUgbnVtYmVycyBmcm9tIDAgdG8gMTI4IGFuZCBGb3JtYXRWYWx1ZS5JTkhFUklULjwvcD4KCQkgKiA8cD5EZWZhdWx0IHZhbHVlIGlzIHVuZGVmaW5lZCBpbmRpY2F0aW5nIG5vdCBzZXQuPC9wPgoJCSAqIDxwPklmIHVuZGVmaW5lZCBkdXJpbmcgdGhlIGNhc2NhZGUgdGhpcyBwcm9wZXJ0eSB3aWxsIGhhdmUgYSB2YWx1ZSBvZiAwLjwvcD4KCQkgKiAKCQkgKiBAdGhyb3dzIFJhbmdlRXJyb3Igd2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eQoJCSAqIAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCgkJICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQoJCSAqIEBsYW5ndmVyc2lvbiAzLjAKCQkgKi8KCQlwdWJsaWMgZnVuY3Rpb24gZ2V0IGJvcmRlckJvdHRvbVdpZHRoKCk6KgoJCXsgcmV0dXJuIF9zdHlsZXMuYm9yZGVyQm90dG9tV2lkdGg7IH0KCQlwdWJsaWMgZnVuY3Rpb24gc2V0IGJvcmRlckJvdHRvbVdpZHRoKHZhbHVlOiopOnZvaWQKCQl7IHNldFN0eWxlQnlQcm9wZXJ0eShUZXh0TGF5b3V0Rm9ybWF0LmJvcmRlckJvdHRvbVdpZHRoUHJvcGVydHksdmFsdWUpOyB9CgoJCS8qKgoJCSAqIENvbG9yIG9mIHRoZSBsZWZ0IGJvcmRlciAoYWRvcHRzIGRlZmF1bHQgdmFsdWUgaWYgdW5kZWZpbmVkIGR1cmluZyBjYXNjYWRlKS4gQ2FuIGJlIGVpdGhlciB0aGUgY29uc3RhbnQgdmFsdWUgPGNvZGU+Qm9yZGVyQ29sb3IuVFJBTlNQQVJFTlQ8L2NvZGU+LCBvciBhIGhleGFkZWNpbWFsIHZhbHVlIHRoYXQgc3BlY2lmaWVzIHRoZSB0aHJlZSA4LWJpdCBSR0IgKHJlZCwgZ3JlZW4sIGJsdWUpIHZhbHVlczsgZm9yIGV4YW1wbGUsIDB4RkYwMDAwIGlzIHJlZCBhbmQgMHgwMEZGMDAgaXMgZ3JlZW4uCgkJICogPHA+TGVnYWwgdmFsdWVzIGFzIGEgc3RyaW5nIGFyZSBCb3JkZXJDb2xvci5UUkFOU1BBUkVOVCwgRm9ybWF0VmFsdWUuSU5IRVJJVCBhbmQgdWludHMgZnJvbSAweDAgdG8gMHhmZmZmZmZmZi48L3A+CgkJICogPHA+RGVmYXVsdCB2YWx1ZSBpcyB1bmRlZmluZWQgaW5kaWNhdGluZyBub3Qgc2V0LjwvcD4KCQkgKiA8cD5JZiB1bmRlZmluZWQgZHVyaW5nIHRoZSBjYXNjYWRlIHRoaXMgcHJvcGVydHkgd2lsbCBoYXZlIGEgdmFsdWUgb2YgQm9yZGVyQ29sb3IuVFJBTlNQQVJFTlQuPC9wPgoJCSAqIAoJCSAqIEB0aHJvd3MgUmFuZ2VFcnJvciB3aGVuIHNldCB2YWx1ZSBpcyBub3Qgd2l0aGluIHJhbmdlIGZvciB0aGlzIHByb3BlcnR5CgkJICogCgkJICogQHBsYXllcnZlcnNpb24gRmxhc2ggMTAKCQkgKiBAcGxheWVydmVyc2lvbiBBSVIgMS41CgkJICogQGxhbmd2ZXJzaW9uIDMuMAoJCSAqIEBzZWUgZmxhc2h4LnRleHRMYXlvdXQuZm9ybWF0cy5Cb3JkZXJDb2xvcgoJCSAqLwoJCXB1YmxpYyBmdW5jdGlvbiBnZXQgYm9yZGVyTGVmdENvbG9yKCk6KgoJCXsgcmV0dXJuIF9zdHlsZXMuYm9yZGVyTGVmdENvbG9yOyB9CgkJcHVibGljIGZ1bmN0aW9uIHNldCBib3JkZXJMZWZ0Q29sb3IodmFsdWU6Kik6dm9pZAoJCXsgc2V0U3R5bGVCeVByb3BlcnR5KFRleHRMYXlvdXRGb3JtYXQuYm9yZGVyTGVmdENvbG9yUHJvcGVydHksdmFsdWUpOyB9CgoJCS8qKgoJCSAqIENvbG9yIG9mIHRoZSByaWdodCBib3JkZXIgKGFkb3B0cyBkZWZhdWx0IHZhbHVlIGlmIHVuZGVmaW5lZCBkdXJpbmcgY2FzY2FkZSkuIENhbiBiZSBlaXRoZXIgdGhlIGNvbnN0YW50IHZhbHVlIDxjb2RlPkJvcmRlckNvbG9yLlRSQU5TUEFSRU5UPC9jb2RlPiwgb3IgYSBoZXhhZGVjaW1hbCB2YWx1ZSB0aGF0IHNwZWNpZmllcyB0aGUgdGhyZWUgOC1iaXQgUkdCIChyZWQsIGdyZWVuLCBibHVlKSB2YWx1ZXM7IGZvciBleGFtcGxlLCAweEZGMDAwMCBpcyByZWQgYW5kIDB4MDBGRjAwIGlzIGdyZWVuLgoJCSAqIDxwPkxlZ2FsIHZhbHVlcyBhcyBhIHN0cmluZyBhcmUgQm9yZGVyQ29sb3IuVFJBTlNQQVJFTlQsIEZvcm1hdFZhbHVlLklOSEVSSVQgYW5kIHVpbnRzIGZyb20gMHgwIHRvIDB4ZmZmZmZmZmYuPC9wPgoJCSAqIDxwPkRlZmF1bHQgdmFsdWUgaXMgdW5kZWZpbmVkIGluZGljYXRpbmcgbm90IHNldC48L3A+CgkJICogPHA+SWYgdW5kZWZpbmVkIGR1cmluZyB0aGUgY2FzY2FkZSB0aGlzIHByb3BlcnR5IHdpbGwgaGF2ZSBhIHZhbHVlIG9mIEJvcmRlckNvbG9yLlRSQU5TUEFSRU5ULjwvcD4KCQkgKiAKCQkgKiBAdGhyb3dzIFJhbmdlRXJyb3Igd2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eQoJCSAqIAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCgkJICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQoJCSAqIEBsYW5ndmVyc2lvbiAzLjAKCQkgKiBAc2VlIGZsYXNoeC50ZXh0TGF5b3V0LmZvcm1hdHMuQm9yZGVyQ29sb3IKCQkgKi8KCQlwdWJsaWMgZnVuY3Rpb24gZ2V0IGJvcmRlclJpZ2h0Q29sb3IoKToqCgkJeyByZXR1cm4gX3N0eWxlcy5ib3JkZXJSaWdodENvbG9yOyB9CgkJcHVibGljIGZ1bmN0aW9uIHNldCBib3JkZXJSaWdodENvbG9yKHZhbHVlOiopOnZvaWQKCQl7IHNldFN0eWxlQnlQcm9wZXJ0eShUZXh0TGF5b3V0Rm9ybWF0LmJvcmRlclJpZ2h0Q29sb3JQcm9wZXJ0eSx2YWx1ZSk7IH0KCgkJLyoqCgkJICogQ29sb3Igb2YgdGhlIHRvcCBib3JkZXIgKGFkb3B0cyBkZWZhdWx0IHZhbHVlIGlmIHVuZGVmaW5lZCBkdXJpbmcgY2FzY2FkZSkuIENhbiBiZSBlaXRoZXIgdGhlIGNvbnN0YW50IHZhbHVlIDxjb2RlPkJvcmRlckNvbG9yLlRSQU5TUEFSRU5UPC9jb2RlPiwgb3IgYSBoZXhhZGVjaW1hbCB2YWx1ZSB0aGF0IHNwZWNpZmllcyB0aGUgdGhyZWUgOC1iaXQgUkdCIChyZWQsIGdyZWVuLCBibHVlKSB2YWx1ZXM7IGZvciBleGFtcGxlLCAweEZGMDAwMCBpcyByZWQgYW5kIDB4MDBGRjAwIGlzIGdyZWVuLgoJCSAqIDxwPkxlZ2FsIHZhbHVlcyBhcyBhIHN0cmluZyBhcmUgQm9yZGVyQ29sb3IuVFJBTlNQQVJFTlQsIEZvcm1hdFZhbHVlLklOSEVSSVQgYW5kIHVpbnRzIGZyb20gMHgwIHRvIDB4ZmZmZmZmZmYuPC9wPgoJCSAqIDxwPkRlZmF1bHQgdmFsdWUgaXMgdW5kZWZpbmVkIGluZGljYXRpbmcgbm90IHNldC48L3A+CgkJICogPHA+SWYgdW5kZWZpbmVkIGR1cmluZyB0aGUgY2FzY2FkZSB0aGlzIHByb3BlcnR5IHdpbGwgaGF2ZSBhIHZhbHVlIG9mIEJvcmRlckNvbG9yLlRSQU5TUEFSRU5ULjwvcD4KCQkgKiAKCQkgKiBAdGhyb3dzIFJhbmdlRXJyb3Igd2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eQoJCSAqIAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCgkJICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQoJCSAqIEBsYW5ndmVyc2lvbiAzLjAKCQkgKiBAc2VlIGZsYXNoeC50ZXh0TGF5b3V0LmZvcm1hdHMuQm9yZGVyQ29sb3IKCQkgKi8KCQlwdWJsaWMgZnVuY3Rpb24gZ2V0IGJvcmRlclRvcENvbG9yKCk6KgoJCXsgcmV0dXJuIF9zdHlsZXMuYm9yZGVyVG9wQ29sb3I7IH0KCQlwdWJsaWMgZnVuY3Rpb24gc2V0IGJvcmRlclRvcENvbG9yKHZhbHVlOiopOnZvaWQKCQl7IHNldFN0eWxlQnlQcm9wZXJ0eShUZXh0TGF5b3V0Rm9ybWF0LmJvcmRlclRvcENvbG9yUHJvcGVydHksdmFsdWUpOyB9CgoJCS8qKgoJCSAqIENvbG9yIG9mIHRoZSBib3R0b20gYm9yZGVyIChhZG9wdHMgZGVmYXVsdCB2YWx1ZSBpZiB1bmRlZmluZWQgZHVyaW5nIGNhc2NhZGUpLiBDYW4gYmUgZWl0aGVyIHRoZSBjb25zdGFudCB2YWx1ZSA8Y29kZT5Cb3JkZXJDb2xvci5UUkFOU1BBUkVOVDwvY29kZT4sIG9yIGEgaGV4YWRlY2ltYWwgdmFsdWUgdGhhdCBzcGVjaWZpZXMgdGhlIHRocmVlIDgtYml0IFJHQiAocmVkLCBncmVlbiwgYmx1ZSkgdmFsdWVzOyBmb3IgZXhhbXBsZSwgMHhGRjAwMDAgaXMgcmVkIGFuZCAweDAwRkYwMCBpcyBncmVlbi4KCQkgKiA8cD5MZWdhbCB2YWx1ZXMgYXMgYSBzdHJpbmcgYXJlIEJvcmRlckNvbG9yLlRSQU5TUEFSRU5ULCBGb3JtYXRWYWx1ZS5JTkhFUklUIGFuZCB1aW50cyBmcm9tIDB4MCB0byAweGZmZmZmZmZmLjwvcD4KCQkgKiA8cD5EZWZhdWx0IHZhbHVlIGlzIHVuZGVmaW5lZCBpbmRpY2F0aW5nIG5vdCBzZXQuPC9wPgoJCSAqIDxwPklmIHVuZGVmaW5lZCBkdXJpbmcgdGhlIGNhc2NhZGUgdGhpcyBwcm9wZXJ0eSB3aWxsIGhhdmUgYSB2YWx1ZSBvZiBCb3JkZXJDb2xvci5UUkFOU1BBUkVOVC48L3A+CgkJICogCgkJICogQHRocm93cyBSYW5nZUVycm9yIHdoZW4gc2V0IHZhbHVlIGlzIG5vdCB3aXRoaW4gcmFuZ2UgZm9yIHRoaXMgcHJvcGVydHkKCQkgKiAKCQkgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKCQkgKiBAbGFuZ3ZlcnNpb24gMy4wCgkJICogQHNlZSBmbGFzaHgudGV4dExheW91dC5mb3JtYXRzLkJvcmRlckNvbG9yCgkJICovCgkJcHVibGljIGZ1bmN0aW9uIGdldCBib3JkZXJCb3R0b21Db2xvcigpOioKCQl7IHJldHVybiBfc3R5bGVzLmJvcmRlckJvdHRvbUNvbG9yOyB9CgkJcHVibGljIGZ1bmN0aW9uIHNldCBib3JkZXJCb3R0b21Db2xvcih2YWx1ZToqKTp2b2lkCgkJeyBzZXRTdHlsZUJ5UHJvcGVydHkoVGV4dExheW91dEZvcm1hdC5ib3JkZXJCb3R0b21Db2xvclByb3BlcnR5LHZhbHVlKTsgfQoKCQkvKioKCQkgKiBsZWZ0IG1hcmdpbiBpbiBwaXhlbHMoYWRvcHRzIGRlZmF1bHQgdmFsdWUgaWYgdW5kZWZpbmVkIGR1cmluZyBjYXNjYWRlKS4KCQkgKiA8cD5MZWdhbCB2YWx1ZXMgYXJlIG51bWJlcnMgZnJvbSAtODAwMCB0byA4MDAwIGFuZCBGb3JtYXRWYWx1ZS5JTkhFUklULjwvcD4KCQkgKiA8cD5EZWZhdWx0IHZhbHVlIGlzIHVuZGVmaW5lZCBpbmRpY2F0aW5nIG5vdCBzZXQuPC9wPgoJCSAqIDxwPklmIHVuZGVmaW5lZCBkdXJpbmcgdGhlIGNhc2NhZGUgdGhpcyBwcm9wZXJ0eSB3aWxsIGhhdmUgYSB2YWx1ZSBvZiAwLjwvcD4KCQkgKiAKCQkgKiBAdGhyb3dzIFJhbmdlRXJyb3Igd2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eQoJCSAqIAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCgkJICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQoJCSAqIEBsYW5ndmVyc2lvbiAzLjAKCQkgKi8KCQlwdWJsaWMgZnVuY3Rpb24gZ2V0IG1hcmdpbkxlZnQoKToqCgkJeyByZXR1cm4gX3N0eWxlcy5tYXJnaW5MZWZ0OyB9CgkJcHVibGljIGZ1bmN0aW9uIHNldCBtYXJnaW5MZWZ0KHZhbHVlOiopOnZvaWQKCQl7IHNldFN0eWxlQnlQcm9wZXJ0eShUZXh0TGF5b3V0Rm9ybWF0Lm1hcmdpbkxlZnRQcm9wZXJ0eSx2YWx1ZSk7IH0KCgkJLyoqCgkJICogcmlnaHQgbWFyZ2luIGluIHBpeGVscyAoYWRvcHRzIGRlZmF1bHQgdmFsdWUgaWYgdW5kZWZpbmVkIGR1cmluZyBjYXNjYWRlKS4KCQkgKiA8cD5MZWdhbCB2YWx1ZXMgYXJlIG51bWJlcnMgZnJvbSAtODAwMCB0byA4MDAwIGFuZCBGb3JtYXRWYWx1ZS5JTkhFUklULjwvcD4KCQkgKiA8cD5EZWZhdWx0IHZhbHVlIGlzIHVuZGVmaW5lZCBpbmRpY2F0aW5nIG5vdCBzZXQuPC9wPgoJCSAqIDxwPklmIHVuZGVmaW5lZCBkdXJpbmcgdGhlIGNhc2NhZGUgdGhpcyBwcm9wZXJ0eSB3aWxsIGhhdmUgYSB2YWx1ZSBvZiAwLjwvcD4KCQkgKiAKCQkgKiBAdGhyb3dzIFJhbmdlRXJyb3Igd2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eQoJCSAqIAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCgkJICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQoJCSAqIEBsYW5ndmVyc2lvbiAzLjAKCQkgKi8KCQlwdWJsaWMgZnVuY3Rpb24gZ2V0IG1hcmdpblJpZ2h0KCk6KgoJCXsgcmV0dXJuIF9zdHlsZXMubWFyZ2luUmlnaHQ7IH0KCQlwdWJsaWMgZnVuY3Rpb24gc2V0IG1hcmdpblJpZ2h0KHZhbHVlOiopOnZvaWQKCQl7IHNldFN0eWxlQnlQcm9wZXJ0eShUZXh0TGF5b3V0Rm9ybWF0Lm1hcmdpblJpZ2h0UHJvcGVydHksdmFsdWUpOyB9CgoJCS8qKgoJCSAqIHRvcCBtYXJnaW4gaW4gcGl4ZWxzIChhZG9wdHMgZGVmYXVsdCB2YWx1ZSBpZiB1bmRlZmluZWQgZHVyaW5nIGNhc2NhZGUpLgoJCSAqIDxwPkxlZ2FsIHZhbHVlcyBhcmUgbnVtYmVycyBmcm9tIC04MDAwIHRvIDgwMDAgYW5kIEZvcm1hdFZhbHVlLklOSEVSSVQuPC9wPgoJCSAqIDxwPkRlZmF1bHQgdmFsdWUgaXMgdW5kZWZpbmVkIGluZGljYXRpbmcgbm90IHNldC48L3A+CgkJICogPHA+SWYgdW5kZWZpbmVkIGR1cmluZyB0aGUgY2FzY2FkZSB0aGlzIHByb3BlcnR5IHdpbGwgaGF2ZSBhIHZhbHVlIG9mIDAuPC9wPgoJCSAqIAoJCSAqIEB0aHJvd3MgUmFuZ2VFcnJvciB3aGVuIHNldCB2YWx1ZSBpcyBub3Qgd2l0aGluIHJhbmdlIGZvciB0aGlzIHByb3BlcnR5CgkJICogCgkJICogQHBsYXllcnZlcnNpb24gRmxhc2ggMTAKCQkgKiBAcGxheWVydmVyc2lvbiBBSVIgMS41CgkJICogQGxhbmd2ZXJzaW9uIDMuMAoJCSAqLwoJCXB1YmxpYyBmdW5jdGlvbiBnZXQgbWFyZ2luVG9wKCk6KgoJCXsgcmV0dXJuIF9zdHlsZXMubWFyZ2luVG9wOyB9CgkJcHVibGljIGZ1bmN0aW9uIHNldCBtYXJnaW5Ub3AodmFsdWU6Kik6dm9pZAoJCXsgc2V0U3R5bGVCeVByb3BlcnR5KFRleHRMYXlvdXRGb3JtYXQubWFyZ2luVG9wUHJvcGVydHksdmFsdWUpOyB9CgoJCS8qKgoJCSAqIGJvdHRvbSBtYXJnaW4gaW4gcGl4ZWxzIChhZG9wdHMgZGVmYXVsdCB2YWx1ZSBpZiB1bmRlZmluZWQgZHVyaW5nIGNhc2NhZGUpLgoJCSAqIDxwPkxlZ2FsIHZhbHVlcyBhcmUgbnVtYmVycyBmcm9tIC04MDAwIHRvIDgwMDAgYW5kIEZvcm1hdFZhbHVlLklOSEVSSVQuPC9wPgoJCSAqIDxwPkRlZmF1bHQgdmFsdWUgaXMgdW5kZWZpbmVkIGluZGljYXRpbmcgbm90IHNldC48L3A+CgkJICogPHA+SWYgdW5kZWZpbmVkIGR1cmluZyB0aGUgY2FzY2FkZSB0aGlzIHByb3BlcnR5IHdpbGwgaGF2ZSBhIHZhbHVlIG9mIDAuPC9wPgoJCSAqIAoJCSAqIEB0aHJvd3MgUmFuZ2VFcnJvciB3aGVuIHNldCB2YWx1ZSBpcyBub3Qgd2l0aGluIHJhbmdlIGZvciB0aGlzIHByb3BlcnR5CgkJICogCgkJICogQHBsYXllcnZlcnNpb24gRmxhc2ggMTAKCQkgKiBAcGxheWVydmVyc2lvbiBBSVIgMS41CgkJICogQGxhbmd2ZXJzaW9uIDMuMAoJCSAqLwoJCXB1YmxpYyBmdW5jdGlvbiBnZXQgbWFyZ2luQm90dG9tKCk6KgoJCXsgcmV0dXJuIF9zdHlsZXMubWFyZ2luQm90dG9tOyB9CgkJcHVibGljIGZ1bmN0aW9uIHNldCBtYXJnaW5Cb3R0b20odmFsdWU6Kik6dm9pZAoJCXsgc2V0U3R5bGVCeVByb3BlcnR5KFRleHRMYXlvdXRGb3JtYXQubWFyZ2luQm90dG9tUHJvcGVydHksdmFsdWUpOyB9CgoJCS8qKgoJCSAqIGNlbGxTcGFjaW5nIHNwZWNpZmllcyBob3cgbXVjaCBzcGFjZSB0aGUgdXNlciBhZ2VudCBzaG91bGQgbGVhdmUgYmV0d2VlbiB0aGUgbGVmdCBzaWRlIG9mIHRoZSB0YWJsZSBhbmQgdGhlIGxlZnQtaGFuZCBzaWRlIG9mIHRoZSBsZWZ0bW9zdCBjb2x1bW4sIHRoZSB0b3Agb2YgdGhlIHRhYmxlIGFuZCB0aGUgdG9wIHNpZGUgb2YgdGhlIHRvcG1vc3Qgcm93LCBhbmQgc28gb24gZm9yIHRoZSByaWdodCBhbmQgYm90dG9tIG9mIHRoZSB0YWJsZS4gVGhlIGF0dHJpYnV0ZSBhbHNvIHNwZWNpZmllcyB0aGUgYW1vdW50IG9mIHNwYWNlIHRvIGxlYXZlIGJldHdlZW4gY2VsbHMuCgkJICogPHA+TGVnYWwgdmFsdWVzIGFyZSBudW1iZXJzIGZyb20gMCB0byAxMDAwIGFuZCBGb3JtYXRWYWx1ZS5JTkhFUklULjwvcD4KCQkgKiA8cD5EZWZhdWx0IHZhbHVlIGlzIHVuZGVmaW5lZCBpbmRpY2F0aW5nIG5vdCBzZXQuPC9wPgoJCSAqIDxwPklmIHVuZGVmaW5lZCBkdXJpbmcgdGhlIGNhc2NhZGUgdGhpcyBwcm9wZXJ0eSB3aWxsIGhhdmUgYSB2YWx1ZSBvZiAwLjwvcD4KCQkgKiAKCQkgKiBAdGhyb3dzIFJhbmdlRXJyb3Igd2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eQoJCSAqIAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCgkJICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQoJCSAqIEBsYW5ndmVyc2lvbiAzLjAKCQkgKi8KCQlwdWJsaWMgZnVuY3Rpb24gZ2V0IGNlbGxTcGFjaW5nKCk6KgoJCXsgcmV0dXJuIF9zdHlsZXMuY2VsbFNwYWNpbmc7IH0KCQlwdWJsaWMgZnVuY3Rpb24gc2V0IGNlbGxTcGFjaW5nKHZhbHVlOiopOnZvaWQKCQl7IHNldFN0eWxlQnlQcm9wZXJ0eShUZXh0TGF5b3V0Rm9ybWF0LmNlbGxTcGFjaW5nUHJvcGVydHksdmFsdWUpOyB9CgoJCS8qKgoJCSAqIGNlbGxQYWRkaW5nIHNwZWNpZmllcyB0aGUgYW1vdW50IG9mIHNwYWNlIGJldHdlZW4gdGhlIGJvcmRlciBvZiB0aGUgY2VsbCBhbmQgaXRzIGNvbnRlbnRzLiBJZiB0aGUgdmFsdWUgb2YgdGhpcyBhdHRyaWJ1dGUgaXMgYSBwaXhlbCBsZW5ndGgsIGFsbCBmb3VyIG1hcmdpbnMgc2hvdWxkIGJlIHRoaXMgZGlzdGFuY2UgZnJvbSB0aGUgY29udGVudHMuIElmIHRoZSB2YWx1ZSBvZiB0aGUgYXR0cmlidXRlIGlzIGEgcGVyY2VudGFnZSBsZW5ndGgsIHRoZSB0b3AgYW5kIGJvdHRvbSBtYXJnaW5zIHNob3VsZCBiZSBlcXVhbGx5IHNlcGFyYXRlZCBmcm9tIHRoZSBjb250ZW50IGJhc2VkIG9uIGEgcGVyY2VudGFnZSBvZiB0aGUgYXZhaWxhYmxlIHZlcnRpY2FsIHNwYWNlLCBhbmQgdGhlIGxlZnQgYW5kIHJpZ2h0IG1hcmdpbnMgc2hvdWxkIGJlIGVxdWFsbHkgc2VwYXJhdGVkIGZyb20gdGhlIGNvbnRlbnQgYmFzZWQgb24gYSBwZXJjZW50YWdlIG9mIHRoZSBhdmFpbGFibGUgaG9yaXpvbnRhbCBzcGFjZS4KCQkgKiA8cD5MZWdhbCB2YWx1ZXMgYXMgYSBudW1iZXIgYXJlIGZyb20gMCB0byAxMDAwLjwvcD4KCQkgKiA8cD5MZWdhbCB2YWx1ZXMgYXMgYSBwZXJjZW50IGFyZSBudW1iZXJzIGZyb20gMCUgdG8gMTAwJS48L3A+CgkJICogPHA+TGVnYWwgdmFsdWVzIGluY2x1ZGUgRm9ybWF0VmFsdWUuSU5IRVJJVC48L3A+CgkJICogPHA+RGVmYXVsdCB2YWx1ZSBpcyB1bmRlZmluZWQgaW5kaWNhdGluZyBub3Qgc2V0LjwvcD4KCQkgKiA8cD5JZiB1bmRlZmluZWQgZHVyaW5nIHRoZSBjYXNjYWRlIHRoaXMgcHJvcGVydHkgd2lsbCBpbmhlcml0IGl0cyB2YWx1ZSBmcm9tIGFuIGFuY2VzdG9yLiBJZiBubyBhbmNlc3RvciBoYXMgc2V0IHRoaXMgcHJvcGVydHksIGl0IHdpbGwgaGF2ZSBhIHZhbHVlIG9mIDAuPC9wPgoJCSAqIAoJCSAqIEB0aHJvd3MgUmFuZ2VFcnJvciB3aGVuIHNldCB2YWx1ZSBpcyBub3Qgd2l0aGluIHJhbmdlIGZvciB0aGlzIHByb3BlcnR5CgkJICogCgkJICogQHBsYXllcnZlcnNpb24gRmxhc2ggMTAKCQkgKiBAcGxheWVydmVyc2lvbiBBSVIgMS41CgkJICogQGxhbmd2ZXJzaW9uIDMuMAoJCSAqLwoJCXB1YmxpYyBmdW5jdGlvbiBnZXQgY2VsbFBhZGRpbmcoKToqCgkJeyByZXR1cm4gX3N0eWxlcy5jZWxsUGFkZGluZzsgfQoJCXB1YmxpYyBmdW5jdGlvbiBzZXQgY2VsbFBhZGRpbmcodmFsdWU6Kik6dm9pZAoJCXsgc2V0U3R5bGVCeVByb3BlcnR5KFRleHRMYXlvdXRGb3JtYXQuY2VsbFBhZGRpbmdQcm9wZXJ0eSx2YWx1ZSk7IH0KCgkJLyoqCgkJICogV2lkdGggb2YgdGFibGUgZWxlbWVudCBzcGVjaWZpZXMgdGhlIGRlc2lyZWQgd2lkdGggb2YgdGhlIGVudGlyZSB0YWJsZSBhbmQgaXMgaW50ZW5kZWQgZm9yIHZpc3VhbCB1c2VyIGFnZW50cy4gV2hlbiB0aGUgdmFsdWUgaXMgYSBwZXJjZW50YWdlIHZhbHVlLCB0aGUgdmFsdWUgaXMgcmVsYXRpdmUgdG8gdGhlIHVzZXIgYWdlbnQncyBhdmFpbGFibGUgaG9yaXpvbnRhbCBzcGFjZS4KCQkgKiA8cD5MZWdhbCB2YWx1ZXMgYXMgYSBudW1iZXIgYXJlIGZyb20gMCB0byA4MDAwLjwvcD4KCQkgKiA8cD5MZWdhbCB2YWx1ZXMgYXMgYSBwZXJjZW50IGFyZSBudW1iZXJzIGZyb20gMCUgdG8gMTAwJS48L3A+CgkJICogPHA+TGVnYWwgdmFsdWVzIGluY2x1ZGUgRm9ybWF0VmFsdWUuSU5IRVJJVC48L3A+CgkJICogPHA+RGVmYXVsdCB2YWx1ZSBpcyB1bmRlZmluZWQgaW5kaWNhdGluZyBub3Qgc2V0LjwvcD4KCQkgKiA8cD5JZiB1bmRlZmluZWQgZHVyaW5nIHRoZSBjYXNjYWRlIHRoaXMgcHJvcGVydHkgd2lsbCBoYXZlIGEgdmFsdWUgb2YgMTAwJS48L3A+CgkJICogCgkJICogQHRocm93cyBSYW5nZUVycm9yIHdoZW4gc2V0IHZhbHVlIGlzIG5vdCB3aXRoaW4gcmFuZ2UgZm9yIHRoaXMgcHJvcGVydHkKCQkgKiAKCQkgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKCQkgKiBAbGFuZ3ZlcnNpb24gMy4wCgkJICovCgkJcHVibGljIGZ1bmN0aW9uIGdldCB0YWJsZVdpZHRoKCk6KgoJCXsgcmV0dXJuIF9zdHlsZXMudGFibGVXaWR0aDsgfQoJCXB1YmxpYyBmdW5jdGlvbiBzZXQgdGFibGVXaWR0aCh2YWx1ZToqKTp2b2lkCgkJeyBzZXRTdHlsZUJ5UHJvcGVydHkoVGV4dExheW91dEZvcm1hdC50YWJsZVdpZHRoUHJvcGVydHksdmFsdWUpOyB9CgoJCS8qKgoJCSAqIFdpZHRoIG9mIHRhYmxlIGNvbHVtbiBzcGVjaWZpZXMgYSBkZWZhdWx0IHdpZHRoIGZvciBlYWNoIGNvbHVtbiBzcGFubmVkIGJ5IHRoZSBjdXJyZW50IENPTCBlbGVtZW50LgoJCSAqIDxwPkxlZ2FsIHZhbHVlcyBhcyBhIG51bWJlciBhcmUgZnJvbSAwIHRvIDgwMDAuPC9wPgoJCSAqIDxwPkxlZ2FsIHZhbHVlcyBhcyBhIHBlcmNlbnQgYXJlIG51bWJlcnMgZnJvbSAwJSB0byAxMDAlLjwvcD4KCQkgKiA8cD5MZWdhbCB2YWx1ZXMgaW5jbHVkZSBGb3JtYXRWYWx1ZS5JTkhFUklULjwvcD4KCQkgKiA8cD5EZWZhdWx0IHZhbHVlIGlzIHVuZGVmaW5lZCBpbmRpY2F0aW5nIG5vdCBzZXQuPC9wPgoJCSAqIDxwPklmIHVuZGVmaW5lZCBkdXJpbmcgdGhlIGNhc2NhZGUgdGhpcyBwcm9wZXJ0eSB3aWxsIGhhdmUgYSB2YWx1ZSBvZiAwLjwvcD4KCQkgKiAKCQkgKiBAdGhyb3dzIFJhbmdlRXJyb3Igd2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eQoJCSAqIAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCgkJICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQoJCSAqIEBsYW5ndmVyc2lvbiAzLjAKCQkgKi8KCQlwdWJsaWMgZnVuY3Rpb24gZ2V0IHRhYmxlQ29sdW1uV2lkdGgoKToqCgkJeyByZXR1cm4gX3N0eWxlcy50YWJsZUNvbHVtbldpZHRoOyB9CgkJcHVibGljIGZ1bmN0aW9uIHNldCB0YWJsZUNvbHVtbldpZHRoKHZhbHVlOiopOnZvaWQKCQl7IHNldFN0eWxlQnlQcm9wZXJ0eShUZXh0TGF5b3V0Rm9ybWF0LnRhYmxlQ29sdW1uV2lkdGhQcm9wZXJ0eSx2YWx1ZSk7IH0KCgkJW0luc3BlY3RhYmxlKGVudW1lcmF0aW9uPSJ2b2lkLGFib3ZlLGJlbG93LGhzaWRlcyx2c2lkZXMsbGhzLHJocyxib3gsYm9yZGVyLGluaGVyaXQiKV0KCQkvKioKCQkgKiBmcmFtZSBzcGVjaWZpZXMgd2hpY2ggc2lkZXMgb2YgdGhlIGZyYW1lIHN1cnJvdW5kaW5nIGEgdGFibGUgd2lsbCBiZSB2aXNpYmxlLiBQb3NzaWJsZSB2YWx1ZXM6CgkJICogPHA+TGVnYWwgdmFsdWVzIGFyZSBUYWJsZUZyYW1lLlZPSUQsIFRhYmxlRnJhbWUuQUJPVkUsIFRhYmxlRnJhbWUuQkVMT1csIFRhYmxlRnJhbWUuSFNJREVTLCBUYWJsZUZyYW1lLlZTSURFUywgVGFibGVGcmFtZS5MSFMsIFRhYmxlRnJhbWUuUkhTLCBUYWJsZUZyYW1lLkJPWCwgVGFibGVGcmFtZS5CT1JERVIsIEZvcm1hdFZhbHVlLklOSEVSSVQuPC9wPgoJCSAqIDxwPkRlZmF1bHQgdmFsdWUgaXMgdW5kZWZpbmVkIGluZGljYXRpbmcgbm90IHNldC48L3A+CgkJICogPHA+SWYgdW5kZWZpbmVkIGR1cmluZyB0aGUgY2FzY2FkZSB0aGlzIHByb3BlcnR5IHdpbGwgaGF2ZSBhIHZhbHVlIG9mIFRhYmxlRnJhbWUuVk9JRC48L3A+CgkJICogCgkJICogQHRocm93cyBSYW5nZUVycm9yIHdoZW4gc2V0IHZhbHVlIGlzIG5vdCB3aXRoaW4gcmFuZ2UgZm9yIHRoaXMgcHJvcGVydHkKCQkgKiAKCQkgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKCQkgKiBAbGFuZ3ZlcnNpb24gMy4wCgkJICogQHNlZSBmbGFzaHgudGV4dExheW91dC5mb3JtYXRzLlRhYmxlRnJhbWUKCQkgKi8KCQlwdWJsaWMgZnVuY3Rpb24gZ2V0IGZyYW1lKCk6KgoJCXsgcmV0dXJuIF9zdHlsZXMuZnJhbWU7IH0KCQlwdWJsaWMgZnVuY3Rpb24gc2V0IGZyYW1lKHZhbHVlOiopOnZvaWQKCQl7IHNldFN0eWxlQnlQcm9wZXJ0eShUZXh0TGF5b3V0Rm9ybWF0LmZyYW1lUHJvcGVydHksdmFsdWUpOyB9CgoJCVtJbnNwZWN0YWJsZShlbnVtZXJhdGlvbj0ibm9uZSxncm91cHMscm93cyxjb2xzLGFsbCxpbmhlcml0IildCgkJLyoqCgkJICogcnVsZXMgc3BlY2lmaWVzIHdoaWNoIHJ1bGVzIHdpbGwgYXBwZWFyIGJldHdlZW4gY2VsbHMgd2l0aGluIGEgdGFibGUuIFRoZSByZW5kZXJpbmcgb2YgcnVsZXMgaXMgdXNlciBhZ2VudCBkZXBlbmRlbnQuIFBvc3NpYmxlIHZhbHVlczoKCQkgKiA8cD5MZWdhbCB2YWx1ZXMgYXJlIFRhYmxlUnVsZXMuTk9ORSwgVGFibGVSdWxlcy5HUk9VUFMsIFRhYmxlUnVsZXMuUk9XUywgVGFibGVSdWxlcy5DT0xTLCBUYWJsZVJ1bGVzLkFMTCwgRm9ybWF0VmFsdWUuSU5IRVJJVC48L3A+CgkJICogPHA+RGVmYXVsdCB2YWx1ZSBpcyB1bmRlZmluZWQgaW5kaWNhdGluZyBub3Qgc2V0LjwvcD4KCQkgKiA8cD5JZiB1bmRlZmluZWQgZHVyaW5nIHRoZSBjYXNjYWRlIHRoaXMgcHJvcGVydHkgd2lsbCBoYXZlIGEgdmFsdWUgb2YgVGFibGVSdWxlcy5OT05FLjwvcD4KCQkgKiAKCQkgKiBAdGhyb3dzIFJhbmdlRXJyb3Igd2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eQoJCSAqIAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCgkJICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQoJCSAqIEBsYW5ndmVyc2lvbiAzLjAKCQkgKiBAc2VlIGZsYXNoeC50ZXh0TGF5b3V0LmZvcm1hdHMuVGFibGVSdWxlcwoJCSAqLwoJCXB1YmxpYyBmdW5jdGlvbiBnZXQgcnVsZXMoKToqCgkJeyByZXR1cm4gX3N0eWxlcy5ydWxlczsgfQoJCXB1YmxpYyBmdW5jdGlvbiBzZXQgcnVsZXModmFsdWU6Kik6dm9pZAoJCXsgc2V0U3R5bGVCeVByb3BlcnR5KFRleHRMYXlvdXRGb3JtYXQucnVsZXNQcm9wZXJ0eSx2YWx1ZSk7IH0KCgkJc3RhdGljIHByaXZhdGUgdmFyIF9kZWZhdWx0czpUZXh0TGF5b3V0Rm9ybWF0OwoJCS8qKgoJCSAqIFJldHVybnMgYSBUZXh0TGF5b3V0Rm9ybWF0IG9iamVjdCB3aXRoIGRlZmF1bHQgc2V0dGluZ3MuCgkJICogVGhpcyBmdW5jdGlvbiBhbHdheXMgcmV0dXJucyB0aGUgc2FtZSBvYmplY3QuCgkJICogCgkJICogQHJldHVybiBhIHNpbmdsZXRvbiBpbnN0YW5jZSBvZiBJVGV4dExheW91dEZvcm1hdCB0aGF0IGlzIHBvcHVsYXRlZCB3aXRoIGRlZmF1bHQgdmFsdWVzLgoJCSAqIAoJCSAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCgkJICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQoJCSAqIEBsYW5ndmVyc2lvbiAzLjAKCQkgKi8KCQlzdGF0aWMgcHVibGljIGZ1bmN0aW9uIGdldCBkZWZhdWx0Rm9ybWF0KCk6SVRleHRMYXlvdXRGb3JtYXQKCQl7CgkJCWlmIChfZGVmYXVsdHMgPT0gbnVsbCkKCQkJewoJCQkJX2RlZmF1bHRzID0gbmV3IFRleHRMYXlvdXRGb3JtYXQoKTsKCQkJCVByb3BlcnR5LmRlZmF1bHRzQWxsSGVscGVyKF9kZXNjcmlwdGlvbixfZGVmYXVsdHMpOwoJCQl9CgkJCXJldHVybiBfZGVmYXVsdHM7CgkJfQoKCQkvKiogQHByaXZhdGUgKi8KCQl0bGZfaW50ZXJuYWwgc3RhdGljIGZ1bmN0aW9uIHJlc2V0TW9kaWZpZWROb25pbmhlcml0ZWRTdHlsZXMoc3R5bGVzT2JqZWN0Ok9iamVjdCk6dm9pZAoJCXsKCQkJdmFyIGZvcm1hdDpUZXh0TGF5b3V0Rm9ybWF0ID0gc3R5bGVzT2JqZWN0IGFzIFRleHRMYXlvdXRGb3JtYXQ7CgkJCWlmIChmb3JtYXQpCgkJCXsKCQkJCS8vIERPIFRISVMgcG9zc2libGUgb3B0aW1pemF0aW9uIGlmIChmb3JtYXQuZ2V0U3R5bGVzKCkgPT0gX2VtcHR5U3R5bGVzKSByZXR1cm47CgkJCQlmb3JtYXQud3JpdGFibGVTdHlsZXMoKTsKCQkJCXN0eWxlc09iamVjdCA9IGZvcm1hdC5nZXRTdHlsZXMoKTsKCQkJfQoKCQkJaWYgKHN0eWxlc09iamVjdC5jb2x1bW5CcmVha0JlZm9yZSAhPSB1bmRlZmluZWQgJiYgc3R5bGVzT2JqZWN0LmNvbHVtbkJyZWFrQmVmb3JlICE9IFRleHRMYXlvdXRGb3JtYXQuY29sdW1uQnJlYWtCZWZvcmVQcm9wZXJ0eS5kZWZhdWx0VmFsdWUpCgkJCQlzdHlsZXNPYmplY3QuY29sdW1uQnJlYWtCZWZvcmUgPSBUZXh0TGF5b3V0Rm9ybWF0LmNvbHVtbkJyZWFrQmVmb3JlUHJvcGVydHkuZGVmYXVsdFZhbHVlOwoJCQlpZiAoc3R5bGVzT2JqZWN0LmNvbHVtbkJyZWFrQWZ0ZXIgIT0gdW5kZWZpbmVkICYmIHN0eWxlc09iamVjdC5jb2x1bW5CcmVha0FmdGVyICE9IFRleHRMYXlvdXRGb3JtYXQuY29sdW1uQnJlYWtBZnRlclByb3BlcnR5LmRlZmF1bHRWYWx1ZSkKCQkJCXN0eWxlc09iamVjdC5jb2x1bW5CcmVha0FmdGVyID0gVGV4dExheW91dEZvcm1hdC5jb2x1bW5CcmVha0FmdGVyUHJvcGVydHkuZGVmYXVsdFZhbHVlOwoJCQlpZiAoc3R5bGVzT2JqZWN0LmNvbnRhaW5lckJyZWFrQmVmb3JlICE9IHVuZGVmaW5lZCAmJiBzdHlsZXNPYmplY3QuY29udGFpbmVyQnJlYWtCZWZvcmUgIT0gVGV4dExheW91dEZvcm1hdC5jb250YWluZXJCcmVha0JlZm9yZVByb3BlcnR5LmRlZmF1bHRWYWx1ZSkKCQkJCXN0eWxlc09iamVjdC5jb250YWluZXJCcmVha0JlZm9yZSA9IFRleHRMYXlvdXRGb3JtYXQuY29udGFpbmVyQnJlYWtCZWZvcmVQcm9wZXJ0eS5kZWZhdWx0VmFsdWU7CgkJCWlmIChzdHlsZXNPYmplY3QuY29udGFpbmVyQnJlYWtBZnRlciAhPSB1bmRlZmluZWQgJiYgc3R5bGVzT2JqZWN0LmNvbnRhaW5lckJyZWFrQWZ0ZXIgIT0gVGV4dExheW91dEZvcm1hdC5jb250YWluZXJCcmVha0FmdGVyUHJvcGVydHkuZGVmYXVsdFZhbHVlKQoJCQkJc3R5bGVzT2JqZWN0LmNvbnRhaW5lckJyZWFrQWZ0ZXIgPSBUZXh0TGF5b3V0Rm9ybWF0LmNvbnRhaW5lckJyZWFrQWZ0ZXJQcm9wZXJ0eS5kZWZhdWx0VmFsdWU7CgkJCWlmIChzdHlsZXNPYmplY3QuYmFja2dyb3VuZENvbG9yICE9IHVuZGVmaW5lZCAmJiBzdHlsZXNPYmplY3QuYmFja2dyb3VuZENvbG9yICE9IFRleHRMYXlvdXRGb3JtYXQuYmFja2dyb3VuZENvbG9yUHJvcGVydHkuZGVmYXVsdFZhbHVlKQoJCQkJc3R5bGVzT2JqZWN0LmJhY2tncm91bmRDb2xvciA9IFRleHRMYXlvdXRGb3JtYXQuYmFja2dyb3VuZENvbG9yUHJvcGVydHkuZGVmYXVsdFZhbHVlOwoJCQlpZiAoc3R5bGVzT2JqZWN0LmJhY2tncm91bmRBbHBoYSAhPSB1bmRlZmluZWQgJiYgc3R5bGVzT2JqZWN0LmJhY2tncm91bmRBbHBoYSAhPSBUZXh0TGF5b3V0Rm9ybWF0LmJhY2tncm91bmRBbHBoYVByb3BlcnR5LmRlZmF1bHRWYWx1ZSkKCQkJCXN0eWxlc09iamVjdC5iYWNrZ3JvdW5kQWxwaGEgPSBUZXh0TGF5b3V0Rm9ybWF0LmJhY2tncm91bmRBbHBoYVByb3BlcnR5LmRlZmF1bHRWYWx1ZTsKCQkJaWYgKHN0eWxlc09iamVjdC5jb2x1bW5HYXAgIT0gdW5kZWZpbmVkICYmIHN0eWxlc09iamVjdC5jb2x1bW5HYXAgIT0gVGV4dExheW91dEZvcm1hdC5jb2x1bW5HYXBQcm9wZXJ0eS5kZWZhdWx0VmFsdWUpCgkJCQlzdHlsZXNPYmplY3QuY29sdW1uR2FwID0gVGV4dExheW91dEZvcm1hdC5jb2x1bW5HYXBQcm9wZXJ0eS5kZWZhdWx0VmFsdWU7CgkJCWlmIChzdHlsZXNPYmplY3QucGFkZGluZ0xlZnQgIT0gdW5kZWZpbmVkICYmIHN0eWxlc09iamVjdC5wYWRkaW5nTGVmdCAhPSBUZXh0TGF5b3V0Rm9ybWF0LnBhZGRpbmdMZWZ0UHJvcGVydHkuZGVmYXVsdFZhbHVlKQoJCQkJc3R5bGVzT2JqZWN0LnBhZGRpbmdMZWZ0ID0gVGV4dExheW91dEZvcm1hdC5wYWRkaW5nTGVmdFByb3BlcnR5LmRlZmF1bHRWYWx1ZTsKCQkJaWYgKHN0eWxlc09iamVjdC5wYWRkaW5nVG9wICE9IHVuZGVmaW5lZCAmJiBzdHlsZXNPYmplY3QucGFkZGluZ1RvcCAhPSBUZXh0TGF5b3V0Rm9ybWF0LnBhZGRpbmdUb3BQcm9wZXJ0eS5kZWZhdWx0VmFsdWUpCgkJCQlzdHlsZXNPYmplY3QucGFkZGluZ1RvcCA9IFRleHRMYXlvdXRGb3JtYXQucGFkZGluZ1RvcFByb3BlcnR5LmRlZmF1bHRWYWx1ZTsKCQkJaWYgKHN0eWxlc09iamVjdC5wYWRkaW5nUmlnaHQgIT0gdW5kZWZpbmVkICYmIHN0eWxlc09iamVjdC5wYWRkaW5nUmlnaHQgIT0gVGV4dExheW91dEZvcm1hdC5wYWRkaW5nUmlnaHRQcm9wZXJ0eS5kZWZhdWx0VmFsdWUpCgkJCQlzdHlsZXNPYmplY3QucGFkZGluZ1JpZ2h0ID0gVGV4dExheW91dEZvcm1hdC5wYWRkaW5nUmlnaHRQcm9wZXJ0eS5kZWZhdWx0VmFsdWU7CgkJCWlmIChzdHlsZXNPYmplY3QucGFkZGluZ0JvdHRvbSAhPSB1bmRlZmluZWQgJiYgc3R5bGVzT2JqZWN0LnBhZGRpbmdCb3R0b20gIT0gVGV4dExheW91dEZvcm1hdC5wYWRkaW5nQm90dG9tUHJvcGVydHkuZGVmYXVsdFZhbHVlKQoJCQkJc3R5bGVzT2JqZWN0LnBhZGRpbmdCb3R0b20gPSBUZXh0TGF5b3V0Rm9ybWF0LnBhZGRpbmdCb3R0b21Qcm9wZXJ0eS5kZWZhdWx0VmFsdWU7CgkJCWlmIChzdHlsZXNPYmplY3QuY29sdW1uQ291bnQgIT0gdW5kZWZpbmVkICYmIHN0eWxlc09iamVjdC5jb2x1bW5Db3VudCAhPSBUZXh0TGF5b3V0Rm9ybWF0LmNvbHVtbkNvdW50UHJvcGVydHkuZGVmYXVsdFZhbHVlKQoJCQkJc3R5bGVzT2JqZWN0LmNvbHVtbkNvdW50ID0gVGV4dExheW91dEZvcm1hdC5jb2x1bW5Db3VudFByb3BlcnR5LmRlZmF1bHRWYWx1ZTsKCQkJaWYgKHN0eWxlc09iamVjdC5jb2x1bW5XaWR0aCAhPSB1bmRlZmluZWQgJiYgc3R5bGVzT2JqZWN0LmNvbHVtbldpZHRoICE9IFRleHRMYXlvdXRGb3JtYXQuY29sdW1uV2lkdGhQcm9wZXJ0eS5kZWZhdWx0VmFsdWUpCgkJCQlzdHlsZXNPYmplY3QuY29sdW1uV2lkdGggPSBUZXh0TGF5b3V0Rm9ybWF0LmNvbHVtbldpZHRoUHJvcGVydHkuZGVmYXVsdFZhbHVlOwoJCQlpZiAoc3R5bGVzT2JqZWN0LnZlcnRpY2FsQWxpZ24gIT0gdW5kZWZpbmVkICYmIHN0eWxlc09iamVjdC52ZXJ0aWNhbEFsaWduICE9IFRleHRMYXlvdXRGb3JtYXQudmVydGljYWxBbGlnblByb3BlcnR5LmRlZmF1bHRWYWx1ZSkKCQkJCXN0eWxlc09iamVjdC52ZXJ0aWNhbEFsaWduID0gVGV4dExheW91dEZvcm1hdC52ZXJ0aWNhbEFsaWduUHJvcGVydHkuZGVmYXVsdFZhbHVlOwoJCQlpZiAoc3R5bGVzT2JqZWN0LmxpbmVCcmVhayAhPSB1bmRlZmluZWQgJiYgc3R5bGVzT2JqZWN0LmxpbmVCcmVhayAhPSBUZXh0TGF5b3V0Rm9ybWF0LmxpbmVCcmVha1Byb3BlcnR5LmRlZmF1bHRWYWx1ZSkKCQkJCXN0eWxlc09iamVjdC5saW5lQnJlYWsgPSBUZXh0TGF5b3V0Rm9ybWF0LmxpbmVCcmVha1Byb3BlcnR5LmRlZmF1bHRWYWx1ZTsKCQkJaWYgKHN0eWxlc09iamVjdC5jbGVhckZsb2F0cyAhPSB1bmRlZmluZWQgJiYgc3R5bGVzT2JqZWN0LmNsZWFyRmxvYXRzICE9IFRleHRMYXlvdXRGb3JtYXQuY2xlYXJGbG9hdHNQcm9wZXJ0eS5kZWZhdWx0VmFsdWUpCgkJCQlzdHlsZXNPYmplY3QuY2xlYXJGbG9hdHMgPSBUZXh0TGF5b3V0Rm9ybWF0LmNsZWFyRmxvYXRzUHJvcGVydHkuZGVmYXVsdFZhbHVlOwoJCQlpZiAoc3R5bGVzT2JqZWN0LnN0eWxlTmFtZSAhPSB1bmRlZmluZWQgJiYgc3R5bGVzT2JqZWN0LnN0eWxlTmFtZSAhPSBUZXh0TGF5b3V0Rm9ybWF0LnN0eWxlTmFtZVByb3BlcnR5LmRlZmF1bHRWYWx1ZSkKCQkJCXN0eWxlc09iamVjdC5zdHlsZU5hbWUgPSBUZXh0TGF5b3V0Rm9ybWF0LnN0eWxlTmFtZVByb3BlcnR5LmRlZmF1bHRWYWx1ZTsKCQkJaWYgKHN0eWxlc09iamVjdC5ib3JkZXJMZWZ0V2lkdGggIT0gdW5kZWZpbmVkICYmIHN0eWxlc09iamVjdC5ib3JkZXJMZWZ0V2lkdGggIT0gVGV4dExheW91dEZvcm1hdC5ib3JkZXJMZWZ0V2lkdGhQcm9wZXJ0eS5kZWZhdWx0VmFsdWUpCgkJCQlzdHlsZXNPYmplY3QuYm9yZGVyTGVmdFdpZHRoID0gVGV4dExheW91dEZvcm1hdC5ib3JkZXJMZWZ0V2lkdGhQcm9wZXJ0eS5kZWZhdWx0VmFsdWU7CgkJCWlmIChzdHlsZXNPYmplY3QuYm9yZGVyUmlnaHRXaWR0aCAhPSB1bmRlZmluZWQgJiYgc3R5bGVzT2JqZWN0LmJvcmRlclJpZ2h0V2lkdGggIT0gVGV4dExheW91dEZvcm1hdC5ib3JkZXJSaWdodFdpZHRoUHJvcGVydHkuZGVmYXVsdFZhbHVlKQoJCQkJc3R5bGVzT2JqZWN0LmJvcmRlclJpZ2h0V2lkdGggPSBUZXh0TGF5b3V0Rm9ybWF0LmJvcmRlclJpZ2h0V2lkdGhQcm9wZXJ0eS5kZWZhdWx0VmFsdWU7CgkJCWlmIChzdHlsZXNPYmplY3QuYm9yZGVyVG9wV2lkdGggIT0gdW5kZWZpbmVkICYmIHN0eWxlc09iamVjdC5ib3JkZXJUb3BXaWR0aCAhPSBUZXh0TGF5b3V0Rm9ybWF0LmJvcmRlclRvcFdpZHRoUHJvcGVydHkuZGVmYXVsdFZhbHVlKQoJCQkJc3R5bGVzT2JqZWN0LmJvcmRlclRvcFdpZHRoID0gVGV4dExheW91dEZvcm1hdC5ib3JkZXJUb3BXaWR0aFByb3BlcnR5LmRlZmF1bHRWYWx1ZTsKCQkJaWYgKHN0eWxlc09iamVjdC5ib3JkZXJCb3R0b21XaWR0aCAhPSB1bmRlZmluZWQgJiYgc3R5bGVzT2JqZWN0LmJvcmRlckJvdHRvbVdpZHRoICE9IFRleHRMYXlvdXRGb3JtYXQuYm9yZGVyQm90dG9tV2lkdGhQcm9wZXJ0eS5kZWZhdWx0VmFsdWUpCgkJCQlzdHlsZXNPYmplY3QuYm9yZGVyQm90dG9tV2lkdGggPSBUZXh0TGF5b3V0Rm9ybWF0LmJvcmRlckJvdHRvbVdpZHRoUHJvcGVydHkuZGVmYXVsdFZhbHVlOwoJCQlpZiAoc3R5bGVzT2JqZWN0LmJvcmRlckxlZnRDb2xvciAhPSB1bmRlZmluZWQgJiYgc3R5bGVzT2JqZWN0LmJvcmRlckxlZnRDb2xvciAhPSBUZXh0TGF5b3V0Rm9ybWF0LmJvcmRlckxlZnRDb2xvclByb3BlcnR5LmRlZmF1bHRWYWx1ZSkKCQkJCXN0eWxlc09iamVjdC5ib3JkZXJMZWZ0Q29sb3IgPSBUZXh0TGF5b3V0Rm9ybWF0LmJvcmRlckxlZnRDb2xvclByb3BlcnR5LmRlZmF1bHRWYWx1ZTsKCQkJaWYgKHN0eWxlc09iamVjdC5ib3JkZXJSaWdodENvbG9yICE9IHVuZGVmaW5lZCAmJiBzdHlsZXNPYmplY3QuYm9yZGVyUmlnaHRDb2xvciAhPSBUZXh0TGF5b3V0Rm9ybWF0LmJvcmRlclJpZ2h0Q29sb3JQcm9wZXJ0eS5kZWZhdWx0VmFsdWUpCgkJCQlzdHlsZXNPYmplY3QuYm9yZGVyUmlnaHRDb2xvciA9IFRleHRMYXlvdXRGb3JtYXQuYm9yZGVyUmlnaHRDb2xvclByb3BlcnR5LmRlZmF1bHRWYWx1ZTsKCQkJaWYgKHN0eWxlc09iamVjdC5ib3JkZXJUb3BDb2xvciAhPSB1bmRlZmluZWQgJiYgc3R5bGVzT2JqZWN0LmJvcmRlclRvcENvbG9yICE9IFRleHRMYXlvdXRGb3JtYXQuYm9yZGVyVG9wQ29sb3JQcm9wZXJ0eS5kZWZhdWx0VmFsdWUpCgkJCQlzdHlsZXNPYmplY3QuYm9yZGVyVG9wQ29sb3IgPSBUZXh0TGF5b3V0Rm9ybWF0LmJvcmRlclRvcENvbG9yUHJvcGVydHkuZGVmYXVsdFZhbHVlOwoJCQlpZiAoc3R5bGVzT2JqZWN0LmJvcmRlckJvdHRvbUNvbG9yICE9IHVuZGVmaW5lZCAmJiBzdHlsZXNPYmplY3QuYm9yZGVyQm90dG9tQ29sb3IgIT0gVGV4dExheW91dEZvcm1hdC5ib3JkZXJCb3R0b21Db2xvclByb3BlcnR5LmRlZmF1bHRWYWx1ZSkKCQkJCXN0eWxlc09iamVjdC5ib3JkZXJCb3R0b21Db2xvciA9IFRleHRMYXlvdXRGb3JtYXQuYm9yZGVyQm90dG9tQ29sb3JQcm9wZXJ0eS5kZWZhdWx0VmFsdWU7CgkJCWlmIChzdHlsZXNPYmplY3QubWFyZ2luTGVmdCAhPSB1bmRlZmluZWQgJiYgc3R5bGVzT2JqZWN0Lm1hcmdpbkxlZnQgIT0gVGV4dExheW91dEZvcm1hdC5tYXJnaW5MZWZ0UHJvcGVydHkuZGVmYXVsdFZhbHVlKQoJCQkJc3R5bGVzT2JqZWN0Lm1hcmdpbkxlZnQgPSBUZXh0TGF5b3V0Rm9ybWF0Lm1hcmdpbkxlZnRQcm9wZXJ0eS5kZWZhdWx0VmFsdWU7CgkJCWlmIChzdHlsZXNPYmplY3QubWFyZ2luUmlnaHQgIT0gdW5kZWZpbmVkICYmIHN0eWxlc09iamVjdC5tYXJnaW5SaWdodCAhPSBUZXh0TGF5b3V0Rm9ybWF0Lm1hcmdpblJpZ2h0UHJvcGVydHkuZGVmYXVsdFZhbHVlKQoJCQkJc3R5bGVzT2JqZWN0Lm1hcmdpblJpZ2h0ID0gVGV4dExheW91dEZvcm1hdC5tYXJnaW5SaWdodFByb3BlcnR5LmRlZmF1bHRWYWx1ZTsKCQkJaWYgKHN0eWxlc09iamVjdC5tYXJnaW5Ub3AgIT0gdW5kZWZpbmVkICYmIHN0eWxlc09iamVjdC5tYXJnaW5Ub3AgIT0gVGV4dExheW91dEZvcm1hdC5tYXJnaW5Ub3BQcm9wZXJ0eS5kZWZhdWx0VmFsdWUpCgkJCQlzdHlsZXNPYmplY3QubWFyZ2luVG9wID0gVGV4dExheW91dEZvcm1hdC5tYXJnaW5Ub3BQcm9wZXJ0eS5kZWZhdWx0VmFsdWU7CgkJCWlmIChzdHlsZXNPYmplY3QubWFyZ2luQm90dG9tICE9IHVuZGVmaW5lZCAmJiBzdHlsZXNPYmplY3QubWFyZ2luQm90dG9tICE9IFRleHRMYXlvdXRGb3JtYXQubWFyZ2luQm90dG9tUHJvcGVydHkuZGVmYXVsdFZhbHVlKQoJCQkJc3R5bGVzT2JqZWN0Lm1hcmdpbkJvdHRvbSA9IFRleHRMYXlvdXRGb3JtYXQubWFyZ2luQm90dG9tUHJvcGVydHkuZGVmYXVsdFZhbHVlOwoJCQlpZiAoc3R5bGVzT2JqZWN0LmNlbGxTcGFjaW5nICE9IHVuZGVmaW5lZCAmJiBzdHlsZXNPYmplY3QuY2VsbFNwYWNpbmcgIT0gVGV4dExheW91dEZvcm1hdC5jZWxsU3BhY2luZ1Byb3BlcnR5LmRlZmF1bHRWYWx1ZSkKCQkJCXN0eWxlc09iamVjdC5jZWxsU3BhY2luZyA9IFRleHRMYXlvdXRGb3JtYXQuY2VsbFNwYWNpbmdQcm9wZXJ0eS5kZWZhdWx0VmFsdWU7CgkJCWlmIChzdHlsZXNPYmplY3QudGFibGVXaWR0aCAhPSB1bmRlZmluZWQgJiYgc3R5bGVzT2JqZWN0LnRhYmxlV2lkdGggIT0gVGV4dExheW91dEZvcm1hdC50YWJsZVdpZHRoUHJvcGVydHkuZGVmYXVsdFZhbHVlKQoJCQkJc3R5bGVzT2JqZWN0LnRhYmxlV2lkdGggPSBUZXh0TGF5b3V0Rm9ybWF0LnRhYmxlV2lkdGhQcm9wZXJ0eS5kZWZhdWx0VmFsdWU7CgkJCWlmIChzdHlsZXNPYmplY3QudGFibGVDb2x1bW5XaWR0aCAhPSB1bmRlZmluZWQgJiYgc3R5bGVzT2JqZWN0LnRhYmxlQ29sdW1uV2lkdGggIT0gVGV4dExheW91dEZvcm1hdC50YWJsZUNvbHVtbldpZHRoUHJvcGVydHkuZGVmYXVsdFZhbHVlKQoJCQkJc3R5bGVzT2JqZWN0LnRhYmxlQ29sdW1uV2lkdGggPSBUZXh0TGF5b3V0Rm9ybWF0LnRhYmxlQ29sdW1uV2lkdGhQcm9wZXJ0eS5kZWZhdWx0VmFsdWU7CgkJCWlmIChzdHlsZXNPYmplY3QuZnJhbWUgIT0gdW5kZWZpbmVkICYmIHN0eWxlc09iamVjdC5mcmFtZSAhPSBUZXh0TGF5b3V0Rm9ybWF0LmZyYW1lUHJvcGVydHkuZGVmYXVsdFZhbHVlKQoJCQkJc3R5bGVzT2JqZWN0LmZyYW1lID0gVGV4dExheW91dEZvcm1hdC5mcmFtZVByb3BlcnR5LmRlZmF1bHRWYWx1ZTsKCQkJaWYgKHN0eWxlc09iamVjdC5ydWxlcyAhPSB1bmRlZmluZWQgJiYgc3R5bGVzT2JqZWN0LnJ1bGVzICE9IFRleHRMYXlvdXRGb3JtYXQucnVsZXNQcm9wZXJ0eS5kZWZhdWx0VmFsdWUpCgkJCQlzdHlsZXNPYmplY3QucnVsZXMgPSBUZXh0TGF5b3V0Rm9ybWF0LnJ1bGVzUHJvcGVydHkuZGVmYXVsdFZhbHVlOwoJCX0KCgkJLyoqCgkJICogQ3JlYXRlcyBhIG5ldyBUZXh0TGF5b3V0Rm9ybWF0IG9iamVjdC4gQWxsIHNldHRpbmdzIGFyZSBlbXB0eSBvciwgb3B0aW9uYWxseSwgYXJlIGluaXRpYWxpemVkIGZyb20gdGhlCgkJICogc3VwcGxpZWQgPGNvZGU+aW5pdGlhbFZhbHVlczwvY29kZT4gb2JqZWN0LgoJCSAqIAoJCSAqIEBwYXJhbSBpbml0aWFsVmFsdWVzIG9wdGlvbmFsIGluc3RhbmNlIGZyb20gd2hpY2ggdG8gY29weSBpbml0aWFsIHZhbHVlcy4gSWYgYW4gVGV4dExheW91dEZvcm1hdCBvYmplY3QgdmFsdWVzIGFyZSBjb3BpZWQuCgkJICogT3RoZXJ3aXNlIGluaXRpYWxWYWx1ZXMgaXMgdHJlYXRlZCBsaWtlIGEgRGljdGlvbmFyeSBvciBPYmplY3QgYW5kIGl0ZXJhdGVkIG92ZXIuCgkJICogCgkJICogQHBsYXllcnZlcnNpb24gRmxhc2ggMTAKCQkgKiBAcGxheWVydmVyc2lvbiBBSVIgMS41CgkJICogQGxhbmd2ZXJzaW9uIDMuMAoJCSAqLwoJCXB1YmxpYyBzdGF0aWMgZnVuY3Rpb24gY3JlYXRlVGV4dExheW91dEZvcm1hdChpbml0aWFsVmFsdWVzOk9iamVjdCk6VGV4dExheW91dEZvcm1hdAoJCXsKCQkJdmFyIGZvcm1hdDpJVGV4dExheW91dEZvcm1hdCA9IGluaXRpYWxWYWx1ZXMgYXMgSVRleHRMYXlvdXRGb3JtYXQ7CgkJCXZhciByc2x0OlRleHRMYXlvdXRGb3JtYXQgPSBuZXcgVGV4dExheW91dEZvcm1hdChmb3JtYXQpOwoJCQlpZiAoZm9ybWF0ID09IG51bGwgJiYgaW5pdGlhbFZhbHVlcykKCQkJewoJCQkJZm9yICh2YXIga2V5OlN0cmluZyBpbiBpbml0aWFsVmFsdWVzKQoJCQkJCXJzbHQuc2V0U3R5bGUoa2V5LGluaXRpYWxWYWx1ZXNba2V5XSk7CgkJCX0KCQkJcmV0dXJuIHJzbHQ7CgkJfQoJfQp9Cg==