Ly8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KLy8KLy8gIExpY2Vuc2VkIHRvIHRoZSBBcGFjaGUgU29mdHdhcmUgRm91bmRhdGlvbiAoQVNGKSB1bmRlciBvbmUgb3IgbW9yZQovLyAgY29udHJpYnV0b3IgbGljZW5zZSBhZ3JlZW1lbnRzLiAgU2VlIHRoZSBOT1RJQ0UgZmlsZSBkaXN0cmlidXRlZCB3aXRoCi8vICB0aGlzIHdvcmsgZm9yIGFkZGl0aW9uYWwgaW5mb3JtYXRpb24gcmVnYXJkaW5nIGNvcHlyaWdodCBvd25lcnNoaXAuCi8vICBUaGUgQVNGIGxpY2Vuc2VzIHRoaXMgZmlsZSB0byBZb3UgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMAovLyAgKHRoZSAiTGljZW5zZSIpOyB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGgKLy8gIHRoZSBMaWNlbnNlLiAgWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0Ci8vCi8vICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wCi8vCi8vICBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlCi8vICBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiAiQVMgSVMiIEJBU0lTLAovLyAgV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuCi8vICBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kCi8vICBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS4KLy8KLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KcGFja2FnZSBmbGFzaHgudGV4dExheW91dC5mb3JtYXRzCnsKICAgIGltcG9ydCBmbGFzaHgudGV4dExheW91dC5kZWJ1Zy5hc3NlcnQ7CiAgICBpbXBvcnQgZmxhc2h4LnRleHRMYXlvdXQucHJvcGVydHkuUHJvcGVydHk7CiAgICBpbXBvcnQgZmxhc2h4LnRleHRMYXlvdXQudGxmX2ludGVybmFsOwogICAgdXNlIG5hbWVzcGFjZSB0bGZfaW50ZXJuYWw7CgogICAgaW1wb3J0IGZsYXNoeC50ZXh0TGF5b3V0LmZvcm1hdHMuQmFja2dyb3VuZENvbG9yOwogICAgaW1wb3J0IGZsYXNoLnRleHQuZW5naW5lLkJyZWFrT3Bwb3J0dW5pdHk7CiAgICBpbXBvcnQgZmxhc2gudGV4dC5lbmdpbmUuRGlnaXRDYXNlOwogICAgaW1wb3J0IGZsYXNoLnRleHQuZW5naW5lLkRpZ2l0V2lkdGg7CiAgICBpbXBvcnQgZmxhc2gudGV4dC5lbmdpbmUuVGV4dEJhc2VsaW5lOwogICAgaW1wb3J0IGZsYXNoLnRleHQuZW5naW5lLktlcm5pbmc7CiAgICBpbXBvcnQgZmxhc2gudGV4dC5lbmdpbmUuTGlnYXR1cmVMZXZlbDsKICAgIGltcG9ydCBmbGFzaC50ZXh0LmVuZ2luZS5UZXh0QmFzZWxpbmU7CiAgICBpbXBvcnQgZmxhc2h4LnRleHRMYXlvdXQuZm9ybWF0cy5UTEZUeXBvZ3JhcGhpY0Nhc2U7CiAgICBpbXBvcnQgZmxhc2h4LnRleHRMYXlvdXQuZm9ybWF0cy5UZXh0RGVjb3JhdGlvbjsKICAgIGltcG9ydCBmbGFzaC50ZXh0LmVuZ2luZS5Gb250V2VpZ2h0OwogICAgaW1wb3J0IGZsYXNoLnRleHQuZW5naW5lLkZvbnRQb3N0dXJlOwogICAgaW1wb3J0IGZsYXNoeC50ZXh0TGF5b3V0LmZvcm1hdHMuV2hpdGVTcGFjZUNvbGxhcHNlOwogICAgaW1wb3J0IGZsYXNoLnRleHQuZW5naW5lLlJlbmRlcmluZ01vZGU7CiAgICBpbXBvcnQgZmxhc2gudGV4dC5lbmdpbmUuQ0ZGSGludGluZzsKICAgIGltcG9ydCBmbGFzaC50ZXh0LmVuZ2luZS5Gb250TG9va3VwOwogICAgaW1wb3J0IGZsYXNoLnRleHQuZW5naW5lLlRleHRSb3RhdGlvbjsKICAgIGltcG9ydCBmbGFzaHgudGV4dExheW91dC5mb3JtYXRzLlRleHRBbGlnbjsKICAgIGltcG9ydCBmbGFzaHgudGV4dExheW91dC5mb3JtYXRzLlRleHRBbGlnbjsKICAgIGltcG9ydCBmbGFzaHgudGV4dExheW91dC5mb3JtYXRzLlRleHRKdXN0aWZ5OwogICAgaW1wb3J0IGZsYXNoeC50ZXh0TGF5b3V0LmZvcm1hdHMuSnVzdGlmaWNhdGlvblJ1bGU7CiAgICBpbXBvcnQgZmxhc2gudGV4dC5lbmdpbmUuSnVzdGlmaWNhdGlvblN0eWxlOwogICAgaW1wb3J0IGZsYXNoeC50ZXh0TGF5b3V0LmZvcm1hdHMuRGlyZWN0aW9uOwogICAgaW1wb3J0IGZsYXNoeC50ZXh0TGF5b3V0LmZvcm1hdHMuTGVhZGluZ01vZGVsOwogICAgaW1wb3J0IGZsYXNoeC50ZXh0TGF5b3V0LmZvcm1hdHMuRm9ybWF0VmFsdWU7CiAgICBpbXBvcnQgZmxhc2h4LnRleHRMYXlvdXQuZm9ybWF0cy5Gb3JtYXRWYWx1ZTsKICAgIGltcG9ydCBmbGFzaHgudGV4dExheW91dC5mb3JtYXRzLkZvcm1hdFZhbHVlOwogICAgaW1wb3J0IGZsYXNoeC50ZXh0TGF5b3V0LmZvcm1hdHMuRm9ybWF0VmFsdWU7CiAgICBpbXBvcnQgZmxhc2h4LnRleHRMYXlvdXQuZm9ybWF0cy5Gb3JtYXRWYWx1ZTsKICAgIGltcG9ydCBmbGFzaHgudGV4dExheW91dC5mb3JtYXRzLkZvcm1hdFZhbHVlOwogICAgaW1wb3J0IGZsYXNoeC50ZXh0TGF5b3V0LmZvcm1hdHMuQmFzZWxpbmVPZmZzZXQ7CiAgICBpbXBvcnQgZmxhc2h4LnRleHRMYXlvdXQuZm9ybWF0cy5WZXJ0aWNhbEFsaWduOwogICAgaW1wb3J0IGZsYXNoeC50ZXh0TGF5b3V0LmZvcm1hdHMuQmxvY2tQcm9ncmVzc2lvbjsKICAgIGltcG9ydCBmbGFzaHgudGV4dExheW91dC5mb3JtYXRzLkxpbmVCcmVhazsKICAgIGltcG9ydCBmbGFzaHgudGV4dExheW91dC5mb3JtYXRzLkxpc3RTdHlsZVR5cGU7CiAgICBpbXBvcnQgZmxhc2h4LnRleHRMYXlvdXQuZm9ybWF0cy5MaXN0U3R5bGVQb3NpdGlvbjsKICAgIGltcG9ydCBmbGFzaHgudGV4dExheW91dC5mb3JtYXRzLkNsZWFyRmxvYXRzOwoKICAgIC8qKgogICAgICogVGhlIFRleHRMYXlvdXRGb3JtYXQgY2xhc3MgaG9sZHMgYWxsIG9mIHRoZSB0ZXh0IGxheW91dCBwcm9wZXJ0aWVzLiBUaGVzZSBwcm9wZXJ0aWVzIGFmZmVjdCB0aGUgZm9ybWF0IGFuZCBzdHlsZSBvZiBhIHRleHQgZmxvdyBhdCB0aGUgY29udGFpbmVyIGxldmVsLCBwYXJhZ3JhcGggbGV2ZWwsIGFuZCB0ZXh0IGxldmVsLiAgQm90aCB0aGUgQ29udGFpbmVyQ29udHJvbGxlciBjbGFzcyBhbmQgdGhlIEZsb3dFbGVtZW50IGJhc2UgY2xhc3MgaGF2ZSA8Y29kZT5mb3JtYXQ8L2NvZGU+IHByb3BlcnRpZXMgdGhhdCBlbmFibGUgeW91IHRvIGFzc2lnbiBhIFRleHRMYXlvdXRGb3JtYXQgaW5zdGFuY2UgdG8gdGhlbS4gQXNzaWduIGEgVGV4dExheW91dEZvcm1hdCBvYmplY3QgdG8gYSBjb250YWluZXIgdG8gYWZmZWN0IHRoZSBmb3JtYXQgb2YgYWxsIG9mIHRoZSBjb250YWluZXIncyBjb250ZW50LiBBc3NpZ24gYSBUZXh0TGF5b3V0Rm9ybWF0IG9iamVjdCB0byBhIEZsb3dFbGVtZW50IGRlc2NlbmRhbnQgdG8gc3BlY2lmeSBmb3JtYXR0aW5nIGZvciB0aGF0IHBhcnRpY3VsYXIgZWxlbWVudDogVGV4dEZsb3csIFBhcmFncmFwaEVsZW1lbnQsIERpdkVsZW1lbnQsIFNwYW5FbGVtZW50LCBJbmxpbmVHcmFwaGljRWxlbWVudCwgTGlua0VsZW1lbnQsIGFuZCBUQ1lFbGVtZW50LgogICAgICogSW4gYWRkaXRpb24gdG8gdGhlIDxjb2RlPmZvcm1hdDwvY29kZT4gcHJvcGVydHksIHRoZXNlIGNsYXNzZXMgYWxzbyBkZWZpbmUgZWFjaCBvZiB0aGUgaW5kaXZpZHVhbCBUZXh0TGF5b3V0Rm9ybWF0IHByb3BlcnRpZXMgc28gdGhhdCB5b3UgY2FuIG92ZXJyaWRlIHRoZSBzZXR0aW5nIG9mIGEgcGFydGljdWxhciBzdHlsZSBwcm9wZXJ0eSBmb3IgdGhhdCBlbGVtZW50LCBpZiB5b3Ugd2lzaC4gPHA+QmVjYXVzZSB5b3UgY2FuIHNldCBhIGdpdmVuIHN0eWxlIGF0IG11bHRpcGxlIGxldmVscywgaXQgaXMgcG9zc2libGUgdG8gaGF2ZSBjb25mbGljdHMuIEZvciBleGFtcGxlLCB0aGUgY29sb3Igb2YgdGhlIHRleHQgYXQgdGhlIFRleHRGbG93IGxldmVsIGNvdWxkIGJlIHNldCB0byBibGFjayB3aGlsZSBhIFNwYW5FbGVtZW50IG9iamVjdCBzZXRzIGl0IHRvIGJsdWUuIFRoZSBnZW5lcmFsIHJ1bGUgaXMgdGhhdCB0aGUgc2V0dGluZyBhdCB0aGUgbG93ZXN0IGxldmVsIG9uIHRoZSB0ZXh0IGZsb3cgdHJlZSB0YWtlcyBwcmVjZWRlbmNlLiBTbyBpZiB0aGUgbGlnYXR1cmUgbGV2ZWwgaXMgc2V0IGZvciBhIFRleHRGbG93IGluc3RhbmNlIGFuZCBhbHNvIHNldCBmb3IgYSBEaXZFbGVtZW50LCB0aGUgRGl2RWxlbWVudCBzZXR0aW5nIHRha2VzIHByZWNlZGVuY2UuIDwvcD48cD5DYXNjYWRpbmcgc3R5bGVzIHJlZmVycyB0byB0aGUgcHJvY2VzcyBvZiBhZG9wdGluZyBzdHlsZXMgZnJvbSBhIGhpZ2hlciBsZXZlbCBpbiB0aGUgdGV4dCBmbG93IGlmIGEgc3R5bGUgdmFsdWUgaXMgdW5kZWZpbmVkIGF0IGEgbG93ZXIgbGV2ZWwuIFdoZW4gYSBzdHlsZSBpcyB1bmRlZmluZWQgb24gYW4gZWxlbWVudCBhdCB0aGUgcG9pbnQgaXQgaXMgYWJvdXQgdG8gYmUgcmVuZGVyZWQsIGl0IGVpdGhlciB0YWtlcyBpdHMgZGVmYXVsdCB2YWx1ZSBvciB0aGUgdmFsdWUgY2FzY2FkZXMgb3IgZGVzY2VuZHMgZnJvbSB0aGUgdmFsdWUgb24gYSBwYXJlbnQgZWxlbWVudC4gRm9yIGV4YW1wbGUsIGlmIHRoZSB0cmFuc3BhcmVuY3kgKDxjb2RlPnRleHRBbHBoYTwvY29kZT4gcHJvcGVydHkpIG9mIHRoZSB0ZXh0IGlzIHVuZGVmaW5lZCBvbiBhIFNwYW5FbGVtZW50IG9iamVjdCwgYnV0IGlzIHNldCBvbiB0aGUgVGV4dEZsb3csIHRoZSB2YWx1ZSBvZiB0aGUgPGNvZGU+VGV4dEZsb3cudGV4dEFscGhhPC9jb2RlPiBwcm9wZXJ0eSBjYXNjYWRlcyB0byB0aGUgU3BhbkVsZW1lbnQgb2JqZWN0IGFuZCBpcyBhcHBsaWVkIHRvIHRoZSB0ZXh0IGZvciB0aGF0IHNwYW4uIFRoZSByZXN1bHQgb2YgdGhlIGNhc2NhZGUsIG9yIHRoZSBzdW0gb2YgdGhlIHN0eWxlcyB0aGF0IGlzIGFwcGxpZWQgdG8gdGhlIGVsZW1lbnQsIGlzIHN0b3JlZCBpbiB0aGUgZWxlbWVudCdzIDxjb2RlPmNvbXB1dGVkRm9ybWF0PC9jb2RlPiBwcm9wZXJ0eS48L3A+PHA+SW4gdGhlIHNhbWUgd2F5LCB5b3UgY2FuIGFwcGx5IHVzZXIgc3R5bGVzIHVzaW5nIHRoZSA8Y29kZT51c2VyU3R5bGVzPC9jb2RlPiBwcm9wZXJ0eSBvZiB0aGUgQ29udGFpbmVyQ29udHJvbGxlciBhbmQgRmxvd0VsZW1lbnQgY2xhc3Nlcy4gVGhpcyAgcHJvcGVydHkgYWxsb3dzIHlvdSB0byByZWFkIG9yIHdyaXRlIGEgZGljdGlvbmFyeSBvZiB1c2VyIHN0eWxlcyBhbmQgYXBwbHkgaXRzIHNldHRpbmdzIHRvIGEgY29udGFpbmVyIG9yIGEgdGV4dCBmbG93IGVsZW1lbnQuIFRoZSB1c2VyIHN0eWxlcyBkaWN0aW9uYXJ5IGlzIGFuIG9iamVjdCB0aGF0IGNvbnNpc3RzIG9mIDxlbT5zdHlsZW5hbWUtdmFsdWU8L2VtPiBwYWlycy4gU3R5bGVzIHNwZWNpZmllZCBieSB0aGUgPGNvZGU+dXNlclN0eWxlczwvY29kZT4gcHJvcGVydHkgdGFrZSBwcmVjZWRlbmNlIG92ZXIgYWxsIG90aGVycy48L3A+PHA+TW9zdCBzdHlsZXMgdGhhdCBhcmUgdW5kZWZpbmVkIGluaGVyaXQgdGhlIHZhbHVlIG9mIHRoZWlyIGltbWVkaWF0ZSBwYXJlbnQgZHVyaW5nIGEgY2FzY2FkZS4gQSBzbWFsbCBudW1iZXIgb2Ygc3R5bGVzLCBob3dldmVyLCBkbyBub3QgaW5oZXJpdCB0aGVpciBwYXJlbnSScyB2YWx1ZSBhbmQgdGFrZSBvbiB0aGVpciBkZWZhdWx0IHZhbHVlcyBpbnN0ZWFkLjwvcD48cD48c3Ryb25nPlN0eWxlIHByb3BlcnRpZXMgdGhhdCBhZG9wdCB0aGVpciBkZWZhdWx0IHZhbHVlcywgaWYgdW5kZWZpbmVkLCBpbmNsdWRlOjwvc3Ryb25nPiA8Y29kZT5iYWNrZ3JvdW5kQWxwaGE8L2NvZGU+LCA8Y29kZT5iYWNrZ3JvdW5kQ29sb3I8L2NvZGU+LCA8Y29kZT5jb2x1bW5Db3VudDwvY29kZT4sIDxjb2RlPmNvbHVtbkdhcDwvY29kZT4sIDxjb2RlPmNvbHVtbldpZHRoPC9jb2RlPiwgPGNvZGU+bGluZUJyZWFrPC9jb2RlPiwgPGNvZGU+cGFkZGluZ0JvdHRvbTwvY29kZT4sIDxjb2RlPnBhZGRpbmdMZWZ0PC9jb2RlPiwgPGNvZGU+cGFkZGluZ1JpZ2h0PC9jb2RlPiwgPGNvZGU+cGFkZGluZ1RvcDwvY29kZT4sIDxjb2RlPnZlcnRpY2FsQWxpZ248L2NvZGU+PC9wPi4KICAgICAqIEBpbmNsdWRlRXhhbXBsZSBleGFtcGxlc1xUZXh0TGF5b3V0Rm9ybWF0RXhhbXBsZS5hcyAtbm9zd2YKICAgICAqIEBpbmNsdWRlRXhhbXBsZSBleGFtcGxlc1xUZXh0TGF5b3V0Rm9ybWF0RXhhbXBsZTIuYXMgLW5vc3dmCiAgICAgKiBAc2VlIGZsYXNoeC50ZXh0TGF5b3V0LmVsZW1lbnRzLkZsb3dFbGVtZW50I2Zvcm1hdAogICAgICogQHNlZSBmbGFzaHgudGV4dExheW91dC5mYWN0b3J5LlRleHRGbG93VGV4dExpbmVGYWN0b3J5CiAgICAgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAogICAgICogQHBsYXllcnZlcnNpb24gQUlSIDEuNSAKICAgICAqIEBsYW5ndmVyc2lvbiAzLjAgCiAgICAgKi8KICAgIHB1YmxpYyBjbGFzcyBUZXh0TGF5b3V0Rm9ybWF0IGltcGxlbWVudHMgSVRleHRMYXlvdXRGb3JtYXQKICAgIHsKICAgICAgICAvKiogQHByaXZhdGUgKi8KICAgICAgICBzdGF0aWMgcHVibGljIGNvbnN0IGNvbG9yUHJvcGVydHk6UHJvcGVydHkgPSBQcm9wZXJ0eS5OZXdVaW50UHJvcGVydHkoImNvbG9yIiwwLHRydWUsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5DSEFSQUNURVJdKSk7CiAgICAgICAgLyoqIEBwcml2YXRlICovCiAgICAgICAgc3RhdGljIHB1YmxpYyBjb25zdCBiYWNrZ3JvdW5kQ29sb3JQcm9wZXJ0eTpQcm9wZXJ0eSA9IFByb3BlcnR5Lk5ld1VpbnRPckVudW1Qcm9wZXJ0eSgKICAgICAgICAgICAgImJhY2tncm91bmRDb2xvciIsQmFja2dyb3VuZENvbG9yLlRSQU5TUEFSRU5ULGZhbHNlLFZlY3Rvci48U3RyaW5nPihbQ2F0ZWdvcnkuQ0hBUkFDVEVSXSkKICAgICAgICAgICAgLEJhY2tncm91bmRDb2xvci5UUkFOU1BBUkVOVAogICAgICAgICk7CiAgICAgICAgLyoqIEBwcml2YXRlICovCiAgICAgICAgc3RhdGljIHB1YmxpYyBjb25zdCBsaW5lVGhyb3VnaFByb3BlcnR5OlByb3BlcnR5ID0gUHJvcGVydHkuTmV3Qm9vbGVhblByb3BlcnR5KCJsaW5lVGhyb3VnaCIsZmFsc2UsdHJ1ZSxWZWN0b3IuPFN0cmluZz4oW0NhdGVnb3J5LkNIQVJBQ1RFUl0pKTsKICAgICAgICAvKiogQHByaXZhdGUgKi8KICAgICAgICBzdGF0aWMgcHVibGljIGNvbnN0IHRleHRBbHBoYVByb3BlcnR5OlByb3BlcnR5ID0gUHJvcGVydHkuTmV3TnVtYmVyUHJvcGVydHkoInRleHRBbHBoYSIsMSx0cnVlLFZlY3Rvci48U3RyaW5nPihbQ2F0ZWdvcnkuQ0hBUkFDVEVSXSksMCwxKTsKICAgICAgICAvKiogQHByaXZhdGUgKi8KICAgICAgICBzdGF0aWMgcHVibGljIGNvbnN0IGJhY2tncm91bmRBbHBoYVByb3BlcnR5OlByb3BlcnR5ID0gUHJvcGVydHkuTmV3TnVtYmVyUHJvcGVydHkoImJhY2tncm91bmRBbHBoYSIsMSxmYWxzZSxWZWN0b3IuPFN0cmluZz4oW0NhdGVnb3J5LkNIQVJBQ1RFUl0pLDAsMSk7CiAgICAgICAgLyoqIEBwcml2YXRlICovCiAgICAgICAgc3RhdGljIHB1YmxpYyBjb25zdCBmb250U2l6ZVByb3BlcnR5OlByb3BlcnR5ID0gUHJvcGVydHkuTmV3TnVtYmVyUHJvcGVydHkoImZvbnRTaXplIiwxMix0cnVlLFZlY3Rvci48U3RyaW5nPihbQ2F0ZWdvcnkuQ0hBUkFDVEVSXSksMSw3MjApOwogICAgICAgIC8qKiBAcHJpdmF0ZSAqLwogICAgICAgIHN0YXRpYyBwdWJsaWMgY29uc3QgYmFzZWxpbmVTaGlmdFByb3BlcnR5OlByb3BlcnR5ID0gUHJvcGVydHkuTmV3TnVtYmVyT3JQZXJjZW50T3JFbnVtUHJvcGVydHkoImJhc2VsaW5lU2hpZnQiLDAuMCx0cnVlLFZlY3Rvci48U3RyaW5nPihbQ2F0ZWdvcnkuQ0hBUkFDVEVSXSksLTEwMDAsMTAwMCwiLTEwMDAlIiwiMTAwMCUiCiAgICAgICAgICAgICxCYXNlbGluZVNoaWZ0LlNVUEVSU0NSSVBUCiAgICAgICAgICAgICxCYXNlbGluZVNoaWZ0LlNVQlNDUklQVAogICAgICAgICk7CiAgICAgICAgLyoqIEBwcml2YXRlICovCiAgICAgICAgc3RhdGljIHB1YmxpYyBjb25zdCB0cmFja2luZ0xlZnRQcm9wZXJ0eTpQcm9wZXJ0eSA9IFByb3BlcnR5Lk5ld051bWJlck9yUGVyY2VudFByb3BlcnR5KCJ0cmFja2luZ0xlZnQiLDAsdHJ1ZSxWZWN0b3IuPFN0cmluZz4oW0NhdGVnb3J5LkNIQVJBQ1RFUl0pLC0xMDAwLDEwMDAsIi0xMDAwJSIsIjEwMDAlIikKICAgICAgICAvKiogQHByaXZhdGUgKi8KICAgICAgICBzdGF0aWMgcHVibGljIGNvbnN0IHRyYWNraW5nUmlnaHRQcm9wZXJ0eTpQcm9wZXJ0eSA9IFByb3BlcnR5Lk5ld051bWJlck9yUGVyY2VudFByb3BlcnR5KCJ0cmFja2luZ1JpZ2h0IiwwLHRydWUsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5DSEFSQUNURVJdKSwtMTAwMCwxMDAwLCItMTAwMCUiLCIxMDAwJSIpCiAgICAgICAgLyoqIEBwcml2YXRlICovCiAgICAgICAgc3RhdGljIHB1YmxpYyBjb25zdCBsaW5lSGVpZ2h0UHJvcGVydHk6UHJvcGVydHkgPSBQcm9wZXJ0eS5OZXdOdW1iZXJPclBlcmNlbnRQcm9wZXJ0eSgibGluZUhlaWdodCIsIjEyMCUiLHRydWUsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5DSEFSQUNURVJdKSwtNzIwLDcyMCwiLTEwMDAlIiwiMTAwMCUiKQogICAgICAgIC8qKiBAcHJpdmF0ZSAqLwogICAgICAgIHN0YXRpYyBwdWJsaWMgY29uc3QgYnJlYWtPcHBvcnR1bml0eVByb3BlcnR5OlByb3BlcnR5ID0gUHJvcGVydHkuTmV3RW51bVN0cmluZ1Byb3BlcnR5KAogICAgICAgICAgICAiYnJlYWtPcHBvcnR1bml0eSIsQnJlYWtPcHBvcnR1bml0eS5BVVRPLHRydWUsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5DSEFSQUNURVJdKQogICAgICAgICAgICAsQnJlYWtPcHBvcnR1bml0eS5BTEwKICAgICAgICAgICAgLEJyZWFrT3Bwb3J0dW5pdHkuQU5ZCiAgICAgICAgICAgICxCcmVha09wcG9ydHVuaXR5LkFVVE8KICAgICAgICAgICAgLEJyZWFrT3Bwb3J0dW5pdHkuTk9ORQogICAgICAgICk7CiAgICAgICAgLyoqIEBwcml2YXRlICovCiAgICAgICAgc3RhdGljIHB1YmxpYyBjb25zdCBkaWdpdENhc2VQcm9wZXJ0eTpQcm9wZXJ0eSA9IFByb3BlcnR5Lk5ld0VudW1TdHJpbmdQcm9wZXJ0eSgKICAgICAgICAgICAgImRpZ2l0Q2FzZSIsRGlnaXRDYXNlLkRFRkFVTFQsdHJ1ZSxWZWN0b3IuPFN0cmluZz4oW0NhdGVnb3J5LkNIQVJBQ1RFUl0pCiAgICAgICAgICAgICxEaWdpdENhc2UuREVGQVVMVAogICAgICAgICAgICAsRGlnaXRDYXNlLkxJTklORwogICAgICAgICAgICAsRGlnaXRDYXNlLk9MRF9TVFlMRQogICAgICAgICk7CiAgICAgICAgLyoqIEBwcml2YXRlICovCiAgICAgICAgc3RhdGljIHB1YmxpYyBjb25zdCBkaWdpdFdpZHRoUHJvcGVydHk6UHJvcGVydHkgPSBQcm9wZXJ0eS5OZXdFbnVtU3RyaW5nUHJvcGVydHkoCiAgICAgICAgICAgICJkaWdpdFdpZHRoIixEaWdpdFdpZHRoLkRFRkFVTFQsdHJ1ZSxWZWN0b3IuPFN0cmluZz4oW0NhdGVnb3J5LkNIQVJBQ1RFUl0pCiAgICAgICAgICAgICxEaWdpdFdpZHRoLkRFRkFVTFQKICAgICAgICAgICAgLERpZ2l0V2lkdGguUFJPUE9SVElPTkFMCiAgICAgICAgICAgICxEaWdpdFdpZHRoLlRBQlVMQVIKICAgICAgICApOwogICAgICAgIC8qKiBAcHJpdmF0ZSAqLwogICAgICAgIHN0YXRpYyBwdWJsaWMgY29uc3QgZG9taW5hbnRCYXNlbGluZVByb3BlcnR5OlByb3BlcnR5ID0gUHJvcGVydHkuTmV3RW51bVN0cmluZ1Byb3BlcnR5KAogICAgICAgICAgICAiZG9taW5hbnRCYXNlbGluZSIsRm9ybWF0VmFsdWUuQVVUTyx0cnVlLFZlY3Rvci48U3RyaW5nPihbQ2F0ZWdvcnkuQ0hBUkFDVEVSXSkKICAgICAgICAgICAgLEZvcm1hdFZhbHVlLkFVVE8KICAgICAgICAgICAgLFRleHRCYXNlbGluZS5ST01BTgogICAgICAgICAgICAsVGV4dEJhc2VsaW5lLkFTQ0VOVAogICAgICAgICAgICAsVGV4dEJhc2VsaW5lLkRFU0NFTlQKICAgICAgICAgICAgLFRleHRCYXNlbGluZS5JREVPR1JBUEhJQ19UT1AKICAgICAgICAgICAgLFRleHRCYXNlbGluZS5JREVPR1JBUEhJQ19DRU5URVIKICAgICAgICAgICAgLFRleHRCYXNlbGluZS5JREVPR1JBUEhJQ19CT1RUT00KICAgICAgICApOwogICAgICAgIC8qKiBAcHJpdmF0ZSAqLwogICAgICAgIHN0YXRpYyBwdWJsaWMgY29uc3Qga2VybmluZ1Byb3BlcnR5OlByb3BlcnR5ID0gUHJvcGVydHkuTmV3RW51bVN0cmluZ1Byb3BlcnR5KAogICAgICAgICAgICAia2VybmluZyIsS2VybmluZy5BVVRPLHRydWUsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5DSEFSQUNURVJdKQogICAgICAgICAgICAsS2VybmluZy5PTgogICAgICAgICAgICAsS2VybmluZy5PRkYKICAgICAgICAgICAgLEtlcm5pbmcuQVVUTwogICAgICAgICk7CiAgICAgICAgLyoqIEBwcml2YXRlICovCiAgICAgICAgc3RhdGljIHB1YmxpYyBjb25zdCBsaWdhdHVyZUxldmVsUHJvcGVydHk6UHJvcGVydHkgPSBQcm9wZXJ0eS5OZXdFbnVtU3RyaW5nUHJvcGVydHkoCiAgICAgICAgICAgICJsaWdhdHVyZUxldmVsIixMaWdhdHVyZUxldmVsLkNPTU1PTix0cnVlLFZlY3Rvci48U3RyaW5nPihbQ2F0ZWdvcnkuQ0hBUkFDVEVSXSkKICAgICAgICAgICAgLExpZ2F0dXJlTGV2ZWwuTUlOSU1VTQogICAgICAgICAgICAsTGlnYXR1cmVMZXZlbC5DT01NT04KICAgICAgICAgICAgLExpZ2F0dXJlTGV2ZWwuVU5DT01NT04KICAgICAgICAgICAgLExpZ2F0dXJlTGV2ZWwuRVhPVElDCiAgICAgICAgKTsKICAgICAgICAvKiogQHByaXZhdGUgKi8KICAgICAgICBzdGF0aWMgcHVibGljIGNvbnN0IGFsaWdubWVudEJhc2VsaW5lUHJvcGVydHk6UHJvcGVydHkgPSBQcm9wZXJ0eS5OZXdFbnVtU3RyaW5nUHJvcGVydHkoCiAgICAgICAgICAgICJhbGlnbm1lbnRCYXNlbGluZSIsVGV4dEJhc2VsaW5lLlVTRV9ET01JTkFOVF9CQVNFTElORSx0cnVlLFZlY3Rvci48U3RyaW5nPihbQ2F0ZWdvcnkuQ0hBUkFDVEVSXSkKICAgICAgICAgICAgLFRleHRCYXNlbGluZS5ST01BTgogICAgICAgICAgICAsVGV4dEJhc2VsaW5lLkFTQ0VOVAogICAgICAgICAgICAsVGV4dEJhc2VsaW5lLkRFU0NFTlQKICAgICAgICAgICAgLFRleHRCYXNlbGluZS5JREVPR1JBUEhJQ19UT1AKICAgICAgICAgICAgLFRleHRCYXNlbGluZS5JREVPR1JBUEhJQ19DRU5URVIKICAgICAgICAgICAgLFRleHRCYXNlbGluZS5JREVPR1JBUEhJQ19CT1RUT00KICAgICAgICAgICAgLFRleHRCYXNlbGluZS5VU0VfRE9NSU5BTlRfQkFTRUxJTkUKICAgICAgICApOwogICAgICAgIC8qKiBAcHJpdmF0ZSAqLwogICAgICAgIHN0YXRpYyBwdWJsaWMgY29uc3QgbG9jYWxlUHJvcGVydHk6UHJvcGVydHkgPSBQcm9wZXJ0eS5OZXdTdHJpbmdQcm9wZXJ0eSgibG9jYWxlIiwiZW4iLHRydWUsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5DSEFSQUNURVIsQ2F0ZWdvcnkuUEFSQUdSQVBIXSkpOwogICAgICAgIC8qKiBAcHJpdmF0ZSAqLwogICAgICAgIHN0YXRpYyBwdWJsaWMgY29uc3QgdHlwb2dyYXBoaWNDYXNlUHJvcGVydHk6UHJvcGVydHkgPSBQcm9wZXJ0eS5OZXdFbnVtU3RyaW5nUHJvcGVydHkoCiAgICAgICAgICAgICJ0eXBvZ3JhcGhpY0Nhc2UiLFRMRlR5cG9ncmFwaGljQ2FzZS5ERUZBVUxULHRydWUsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5DSEFSQUNURVJdKQogICAgICAgICAgICAsVExGVHlwb2dyYXBoaWNDYXNlLkRFRkFVTFQKICAgICAgICAgICAgLFRMRlR5cG9ncmFwaGljQ2FzZS5DQVBTX1RPX1NNQUxMX0NBUFMKICAgICAgICAgICAgLFRMRlR5cG9ncmFwaGljQ2FzZS5VUFBFUkNBU0UKICAgICAgICAgICAgLFRMRlR5cG9ncmFwaGljQ2FzZS5MT1dFUkNBU0UKICAgICAgICAgICAgLFRMRlR5cG9ncmFwaGljQ2FzZS5MT1dFUkNBU0VfVE9fU01BTExfQ0FQUwogICAgICAgICk7CiAgICAgICAgLyoqIEBwcml2YXRlICovCiAgICAgICAgc3RhdGljIHB1YmxpYyBjb25zdCBmb250RmFtaWx5UHJvcGVydHk6UHJvcGVydHkgPSBQcm9wZXJ0eS5OZXdTdHJpbmdQcm9wZXJ0eSgiZm9udEZhbWlseSIsIkFyaWFsIix0cnVlLFZlY3Rvci48U3RyaW5nPihbQ2F0ZWdvcnkuQ0hBUkFDVEVSXSkpOwogICAgICAgIC8qKiBAcHJpdmF0ZSAqLwogICAgICAgIHN0YXRpYyBwdWJsaWMgY29uc3QgdGV4dERlY29yYXRpb25Qcm9wZXJ0eTpQcm9wZXJ0eSA9IFByb3BlcnR5Lk5ld0VudW1TdHJpbmdQcm9wZXJ0eSgKICAgICAgICAgICAgInRleHREZWNvcmF0aW9uIixUZXh0RGVjb3JhdGlvbi5OT05FLHRydWUsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5DSEFSQUNURVJdKQogICAgICAgICAgICAsVGV4dERlY29yYXRpb24uTk9ORQogICAgICAgICAgICAsVGV4dERlY29yYXRpb24uVU5ERVJMSU5FCiAgICAgICAgKTsKICAgICAgICAvKiogQHByaXZhdGUgKi8KICAgICAgICBzdGF0aWMgcHVibGljIGNvbnN0IGZvbnRXZWlnaHRQcm9wZXJ0eTpQcm9wZXJ0eSA9IFByb3BlcnR5Lk5ld0VudW1TdHJpbmdQcm9wZXJ0eSgKICAgICAgICAgICAgImZvbnRXZWlnaHQiLEZvbnRXZWlnaHQuTk9STUFMLHRydWUsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5DSEFSQUNURVJdKQogICAgICAgICAgICAsRm9udFdlaWdodC5OT1JNQUwKICAgICAgICAgICAgLEZvbnRXZWlnaHQuQk9MRAogICAgICAgICk7CiAgICAgICAgLyoqIEBwcml2YXRlICovCiAgICAgICAgc3RhdGljIHB1YmxpYyBjb25zdCBmb250U3R5bGVQcm9wZXJ0eTpQcm9wZXJ0eSA9IFByb3BlcnR5Lk5ld0VudW1TdHJpbmdQcm9wZXJ0eSgKICAgICAgICAgICAgImZvbnRTdHlsZSIsRm9udFBvc3R1cmUuTk9STUFMLHRydWUsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5DSEFSQUNURVJdKQogICAgICAgICAgICAsRm9udFBvc3R1cmUuTk9STUFMCiAgICAgICAgICAgICxGb250UG9zdHVyZS5JVEFMSUMKICAgICAgICApOwogICAgICAgIC8qKiBAcHJpdmF0ZSAqLwogICAgICAgIHN0YXRpYyBwdWJsaWMgY29uc3Qgd2hpdGVTcGFjZUNvbGxhcHNlUHJvcGVydHk6UHJvcGVydHkgPSBQcm9wZXJ0eS5OZXdFbnVtU3RyaW5nUHJvcGVydHkoCiAgICAgICAgICAgICJ3aGl0ZVNwYWNlQ29sbGFwc2UiLFdoaXRlU3BhY2VDb2xsYXBzZS5DT0xMQVBTRSx0cnVlLFZlY3Rvci48U3RyaW5nPihbQ2F0ZWdvcnkuQ0hBUkFDVEVSXSkKICAgICAgICAgICAgLFdoaXRlU3BhY2VDb2xsYXBzZS5QUkVTRVJWRQogICAgICAgICAgICAsV2hpdGVTcGFjZUNvbGxhcHNlLkNPTExBUFNFCiAgICAgICAgKTsKICAgICAgICAvKiogQHByaXZhdGUgKi8KICAgICAgICBzdGF0aWMgcHVibGljIGNvbnN0IHJlbmRlcmluZ01vZGVQcm9wZXJ0eTpQcm9wZXJ0eSA9IFByb3BlcnR5Lk5ld0VudW1TdHJpbmdQcm9wZXJ0eSgKICAgICAgICAgICAgInJlbmRlcmluZ01vZGUiLFJlbmRlcmluZ01vZGUuQ0ZGLHRydWUsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5DSEFSQUNURVJdKQogICAgICAgICAgICAsUmVuZGVyaW5nTW9kZS5OT1JNQUwKICAgICAgICAgICAgLFJlbmRlcmluZ01vZGUuQ0ZGCiAgICAgICAgKTsKICAgICAgICAvKiogQHByaXZhdGUgKi8KICAgICAgICBzdGF0aWMgcHVibGljIGNvbnN0IGNmZkhpbnRpbmdQcm9wZXJ0eTpQcm9wZXJ0eSA9IFByb3BlcnR5Lk5ld0VudW1TdHJpbmdQcm9wZXJ0eSgKICAgICAgICAgICAgImNmZkhpbnRpbmciLENGRkhpbnRpbmcuSE9SSVpPTlRBTF9TVEVNLHRydWUsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5DSEFSQUNURVJdKQogICAgICAgICAgICAsQ0ZGSGludGluZy5OT05FCiAgICAgICAgICAgICxDRkZIaW50aW5nLkhPUklaT05UQUxfU1RFTQogICAgICAgICk7CiAgICAgICAgLyoqIEBwcml2YXRlICovCiAgICAgICAgc3RhdGljIHB1YmxpYyBjb25zdCBmb250TG9va3VwUHJvcGVydHk6UHJvcGVydHkgPSBQcm9wZXJ0eS5OZXdFbnVtU3RyaW5nUHJvcGVydHkoCiAgICAgICAgICAgICJmb250TG9va3VwIixGb250TG9va3VwLkRFVklDRSx0cnVlLFZlY3Rvci48U3RyaW5nPihbQ2F0ZWdvcnkuQ0hBUkFDVEVSXSkKICAgICAgICAgICAgLEZvbnRMb29rdXAuREVWSUNFCiAgICAgICAgICAgICxGb250TG9va3VwLkVNQkVEREVEX0NGRgogICAgICAgICk7CiAgICAgICAgLyoqIEBwcml2YXRlICovCiAgICAgICAgc3RhdGljIHB1YmxpYyBjb25zdCB0ZXh0Um90YXRpb25Qcm9wZXJ0eTpQcm9wZXJ0eSA9IFByb3BlcnR5Lk5ld0VudW1TdHJpbmdQcm9wZXJ0eSgKICAgICAgICAgICAgInRleHRSb3RhdGlvbiIsVGV4dFJvdGF0aW9uLkFVVE8sdHJ1ZSxWZWN0b3IuPFN0cmluZz4oW0NhdGVnb3J5LkNIQVJBQ1RFUl0pCiAgICAgICAgICAgICxUZXh0Um90YXRpb24uUk9UQVRFXzAKICAgICAgICAgICAgLFRleHRSb3RhdGlvbi5ST1RBVEVfMTgwCiAgICAgICAgICAgICxUZXh0Um90YXRpb24uUk9UQVRFXzI3MAogICAgICAgICAgICAsVGV4dFJvdGF0aW9uLlJPVEFURV85MAogICAgICAgICAgICAsVGV4dFJvdGF0aW9uLkFVVE8KICAgICAgICApOwogICAgICAgIC8qKiBAcHJpdmF0ZSAqLwogICAgICAgIHN0YXRpYyBwdWJsaWMgY29uc3QgdGV4dEluZGVudFByb3BlcnR5OlByb3BlcnR5ID0gUHJvcGVydHkuTmV3TnVtYmVyUHJvcGVydHkoInRleHRJbmRlbnQiLDAsdHJ1ZSxWZWN0b3IuPFN0cmluZz4oW0NhdGVnb3J5LlBBUkFHUkFQSF0pLC04MDAwLDgwMDApOwogICAgICAgIC8qKiBAcHJpdmF0ZSAqLwogICAgICAgIHN0YXRpYyBwdWJsaWMgY29uc3QgcGFyYWdyYXBoU3RhcnRJbmRlbnRQcm9wZXJ0eTpQcm9wZXJ0eSA9IFByb3BlcnR5Lk5ld051bWJlclByb3BlcnR5KCJwYXJhZ3JhcGhTdGFydEluZGVudCIsMCx0cnVlLFZlY3Rvci48U3RyaW5nPihbQ2F0ZWdvcnkuUEFSQUdSQVBIXSksMCw4MDAwKTsKICAgICAgICAvKiogQHByaXZhdGUgKi8KICAgICAgICBzdGF0aWMgcHVibGljIGNvbnN0IHBhcmFncmFwaEVuZEluZGVudFByb3BlcnR5OlByb3BlcnR5ID0gUHJvcGVydHkuTmV3TnVtYmVyUHJvcGVydHkoInBhcmFncmFwaEVuZEluZGVudCIsMCx0cnVlLFZlY3Rvci48U3RyaW5nPihbQ2F0ZWdvcnkuUEFSQUdSQVBIXSksMCw4MDAwKTsKICAgICAgICAvKiogQHByaXZhdGUgKi8KICAgICAgICBzdGF0aWMgcHVibGljIGNvbnN0IHBhcmFncmFwaFNwYWNlQmVmb3JlUHJvcGVydHk6UHJvcGVydHkgPSBQcm9wZXJ0eS5OZXdOdW1iZXJQcm9wZXJ0eSgicGFyYWdyYXBoU3BhY2VCZWZvcmUiLDAsdHJ1ZSxWZWN0b3IuPFN0cmluZz4oW0NhdGVnb3J5LlBBUkFHUkFQSF0pLDAsODAwMCk7CiAgICAgICAgLyoqIEBwcml2YXRlICovCiAgICAgICAgc3RhdGljIHB1YmxpYyBjb25zdCBwYXJhZ3JhcGhTcGFjZUFmdGVyUHJvcGVydHk6UHJvcGVydHkgPSBQcm9wZXJ0eS5OZXdOdW1iZXJQcm9wZXJ0eSgicGFyYWdyYXBoU3BhY2VBZnRlciIsMCx0cnVlLFZlY3Rvci48U3RyaW5nPihbQ2F0ZWdvcnkuUEFSQUdSQVBIXSksMCw4MDAwKTsKICAgICAgICAvKiogQHByaXZhdGUgKi8KICAgICAgICBzdGF0aWMgcHVibGljIGNvbnN0IHRleHRBbGlnblByb3BlcnR5OlByb3BlcnR5ID0gUHJvcGVydHkuTmV3RW51bVN0cmluZ1Byb3BlcnR5KAogICAgICAgICAgICAidGV4dEFsaWduIixUZXh0QWxpZ24uU1RBUlQsdHJ1ZSxWZWN0b3IuPFN0cmluZz4oW0NhdGVnb3J5LlBBUkFHUkFQSF0pCiAgICAgICAgICAgICxUZXh0QWxpZ24uTEVGVAogICAgICAgICAgICAsVGV4dEFsaWduLlJJR0hUCiAgICAgICAgICAgICxUZXh0QWxpZ24uQ0VOVEVSCiAgICAgICAgICAgICxUZXh0QWxpZ24uSlVTVElGWQogICAgICAgICAgICAsVGV4dEFsaWduLlNUQVJUCiAgICAgICAgICAgICxUZXh0QWxpZ24uRU5ECiAgICAgICAgKTsKICAgICAgICAvKiogQHByaXZhdGUgKi8KICAgICAgICBzdGF0aWMgcHVibGljIGNvbnN0IHRleHRBbGlnbkxhc3RQcm9wZXJ0eTpQcm9wZXJ0eSA9IFByb3BlcnR5Lk5ld0VudW1TdHJpbmdQcm9wZXJ0eSgKICAgICAgICAgICAgInRleHRBbGlnbkxhc3QiLFRleHRBbGlnbi5TVEFSVCx0cnVlLFZlY3Rvci48U3RyaW5nPihbQ2F0ZWdvcnkuUEFSQUdSQVBIXSkKICAgICAgICAgICAgLFRleHRBbGlnbi5MRUZUCiAgICAgICAgICAgICxUZXh0QWxpZ24uUklHSFQKICAgICAgICAgICAgLFRleHRBbGlnbi5DRU5URVIKICAgICAgICAgICAgLFRleHRBbGlnbi5KVVNUSUZZCiAgICAgICAgICAgICxUZXh0QWxpZ24uU1RBUlQKICAgICAgICAgICAgLFRleHRBbGlnbi5FTkQKICAgICAgICApOwogICAgICAgIC8qKiBAcHJpdmF0ZSAqLwogICAgICAgIHN0YXRpYyBwdWJsaWMgY29uc3QgdGV4dEp1c3RpZnlQcm9wZXJ0eTpQcm9wZXJ0eSA9IFByb3BlcnR5Lk5ld0VudW1TdHJpbmdQcm9wZXJ0eSgKICAgICAgICAgICAgInRleHRKdXN0aWZ5IixUZXh0SnVzdGlmeS5JTlRFUl9XT1JELHRydWUsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5QQVJBR1JBUEhdKQogICAgICAgICAgICAsVGV4dEp1c3RpZnkuSU5URVJfV09SRAogICAgICAgICAgICAsVGV4dEp1c3RpZnkuRElTVFJJQlVURQogICAgICAgICk7CiAgICAgICAgLyoqIEBwcml2YXRlICovCiAgICAgICAgc3RhdGljIHB1YmxpYyBjb25zdCBqdXN0aWZpY2F0aW9uUnVsZVByb3BlcnR5OlByb3BlcnR5ID0gUHJvcGVydHkuTmV3RW51bVN0cmluZ1Byb3BlcnR5KAogICAgICAgICAgICAianVzdGlmaWNhdGlvblJ1bGUiLEZvcm1hdFZhbHVlLkFVVE8sdHJ1ZSxWZWN0b3IuPFN0cmluZz4oW0NhdGVnb3J5LlBBUkFHUkFQSF0pCiAgICAgICAgICAgICxKdXN0aWZpY2F0aW9uUnVsZS5FQVNUX0FTSUFOCiAgICAgICAgICAgICxKdXN0aWZpY2F0aW9uUnVsZS5TUEFDRQogICAgICAgICAgICAsRm9ybWF0VmFsdWUuQVVUTwogICAgICAgICk7CiAgICAgICAgLyoqIEBwcml2YXRlICovCiAgICAgICAgc3RhdGljIHB1YmxpYyBjb25zdCBqdXN0aWZpY2F0aW9uU3R5bGVQcm9wZXJ0eTpQcm9wZXJ0eSA9IFByb3BlcnR5Lk5ld0VudW1TdHJpbmdQcm9wZXJ0eSgKICAgICAgICAgICAgImp1c3RpZmljYXRpb25TdHlsZSIsRm9ybWF0VmFsdWUuQVVUTyx0cnVlLFZlY3Rvci48U3RyaW5nPihbQ2F0ZWdvcnkuUEFSQUdSQVBIXSkKICAgICAgICAgICAgLEp1c3RpZmljYXRpb25TdHlsZS5QUklPUklUSVpFX0xFQVNUX0FESlVTVE1FTlQKICAgICAgICAgICAgLEp1c3RpZmljYXRpb25TdHlsZS5QVVNIX0lOX0tJTlNPS1UKICAgICAgICAgICAgLEp1c3RpZmljYXRpb25TdHlsZS5QVVNIX09VVF9PTkxZCiAgICAgICAgICAgICxGb3JtYXRWYWx1ZS5BVVRPCiAgICAgICAgKTsKICAgICAgICAvKiogQHByaXZhdGUgKi8KICAgICAgICBzdGF0aWMgcHVibGljIGNvbnN0IGRpcmVjdGlvblByb3BlcnR5OlByb3BlcnR5ID0gUHJvcGVydHkuTmV3RW51bVN0cmluZ1Byb3BlcnR5KAogICAgICAgICAgICAiZGlyZWN0aW9uIixEaXJlY3Rpb24uTFRSLHRydWUsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5QQVJBR1JBUEhdKQogICAgICAgICAgICAsRGlyZWN0aW9uLkxUUgogICAgICAgICAgICAsRGlyZWN0aW9uLlJUTAogICAgICAgICk7CiAgICAgICAgLyoqIEBwcml2YXRlICovCiAgICAgICAgc3RhdGljIHB1YmxpYyBjb25zdCB3b3JkU3BhY2luZ1Byb3BlcnR5OlByb3BlcnR5ID0gUHJvcGVydHkuTmV3U3BhY2luZ0xpbWl0UHJvcGVydHkoIndvcmRTcGFjaW5nIiwiMTAwJSwgNTAlLCAxNTAlIix0cnVlLFZlY3Rvci48U3RyaW5nPihbQ2F0ZWdvcnkuUEFSQUdSQVBIXSksIi0xMDAwJSIsIjEwMDAlIikKICAgICAgICAvKiogQHByaXZhdGUgKi8KICAgICAgICBzdGF0aWMgcHVibGljIGNvbnN0IHRhYlN0b3BzUHJvcGVydHk6UHJvcGVydHkgPSBQcm9wZXJ0eS5OZXdUYWJTdG9wc1Byb3BlcnR5KCJ0YWJTdG9wcyIsbnVsbCx0cnVlLFZlY3Rvci48U3RyaW5nPihbQ2F0ZWdvcnkuUEFSQUdSQVBIXSkpOwogICAgICAgIC8qKiBAcHJpdmF0ZSAqLwogICAgICAgIHN0YXRpYyBwdWJsaWMgY29uc3QgbGVhZGluZ01vZGVsUHJvcGVydHk6UHJvcGVydHkgPSBQcm9wZXJ0eS5OZXdFbnVtU3RyaW5nUHJvcGVydHkoCiAgICAgICAgICAgICJsZWFkaW5nTW9kZWwiLExlYWRpbmdNb2RlbC5BVVRPLHRydWUsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5QQVJBR1JBUEhdKQogICAgICAgICAgICAsTGVhZGluZ01vZGVsLlJPTUFOX1VQCiAgICAgICAgICAgICxMZWFkaW5nTW9kZWwuSURFT0dSQVBISUNfVE9QX1VQCiAgICAgICAgICAgICxMZWFkaW5nTW9kZWwuSURFT0dSQVBISUNfQ0VOVEVSX1VQCiAgICAgICAgICAgICxMZWFkaW5nTW9kZWwuSURFT0dSQVBISUNfVE9QX0RPV04KICAgICAgICAgICAgLExlYWRpbmdNb2RlbC5JREVPR1JBUEhJQ19DRU5URVJfRE9XTgogICAgICAgICAgICAsTGVhZGluZ01vZGVsLkFQUFJPWElNQVRFX1RFWFRfRklFTEQKICAgICAgICAgICAgLExlYWRpbmdNb2RlbC5BU0NFTlRfREVTQ0VOVF9VUAogICAgICAgICAgICAsTGVhZGluZ01vZGVsLkJPWAogICAgICAgICAgICAsTGVhZGluZ01vZGVsLkFVVE8KICAgICAgICApOwogICAgICAgIC8qKiBAcHJpdmF0ZSAqLwogICAgICAgIHN0YXRpYyBwdWJsaWMgY29uc3QgY29sdW1uR2FwUHJvcGVydHk6UHJvcGVydHkgPSBQcm9wZXJ0eS5OZXdOdW1iZXJQcm9wZXJ0eSgiY29sdW1uR2FwIiwyMCxmYWxzZSxWZWN0b3IuPFN0cmluZz4oW0NhdGVnb3J5LkNPTlRBSU5FUl0pLDAsMTAwMCk7CiAgICAgICAgLyoqIEBwcml2YXRlICovCiAgICAgICAgc3RhdGljIHB1YmxpYyBjb25zdCBwYWRkaW5nTGVmdFByb3BlcnR5OlByb3BlcnR5ID0gUHJvcGVydHkuTmV3TnVtYmVyT3JFbnVtUHJvcGVydHkoCiAgICAgICAgICAgICJwYWRkaW5nTGVmdCIsRm9ybWF0VmFsdWUuQVVUTyxmYWxzZSxWZWN0b3IuPFN0cmluZz4oW0NhdGVnb3J5LkNPTlRBSU5FUixDYXRlZ29yeS5QQVJBR1JBUEhdKSwtODAwMCw4MDAwCiAgICAgICAgICAgICxGb3JtYXRWYWx1ZS5BVVRPCiAgICAgICAgKTsKICAgICAgICAvKiogQHByaXZhdGUgKi8KICAgICAgICBzdGF0aWMgcHVibGljIGNvbnN0IHBhZGRpbmdUb3BQcm9wZXJ0eTpQcm9wZXJ0eSA9IFByb3BlcnR5Lk5ld051bWJlck9yRW51bVByb3BlcnR5KAogICAgICAgICAgICAicGFkZGluZ1RvcCIsRm9ybWF0VmFsdWUuQVVUTyxmYWxzZSxWZWN0b3IuPFN0cmluZz4oW0NhdGVnb3J5LkNPTlRBSU5FUixDYXRlZ29yeS5QQVJBR1JBUEhdKSwtODAwMCw4MDAwCiAgICAgICAgICAgICxGb3JtYXRWYWx1ZS5BVVRPCiAgICAgICAgKTsKICAgICAgICAvKiogQHByaXZhdGUgKi8KICAgICAgICBzdGF0aWMgcHVibGljIGNvbnN0IHBhZGRpbmdSaWdodFByb3BlcnR5OlByb3BlcnR5ID0gUHJvcGVydHkuTmV3TnVtYmVyT3JFbnVtUHJvcGVydHkoCiAgICAgICAgICAgICJwYWRkaW5nUmlnaHQiLEZvcm1hdFZhbHVlLkFVVE8sZmFsc2UsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5DT05UQUlORVIsQ2F0ZWdvcnkuUEFSQUdSQVBIXSksLTgwMDAsODAwMAogICAgICAgICAgICAsRm9ybWF0VmFsdWUuQVVUTwogICAgICAgICk7CiAgICAgICAgLyoqIEBwcml2YXRlICovCiAgICAgICAgc3RhdGljIHB1YmxpYyBjb25zdCBwYWRkaW5nQm90dG9tUHJvcGVydHk6UHJvcGVydHkgPSBQcm9wZXJ0eS5OZXdOdW1iZXJPckVudW1Qcm9wZXJ0eSgKICAgICAgICAgICAgInBhZGRpbmdCb3R0b20iLEZvcm1hdFZhbHVlLkFVVE8sZmFsc2UsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5DT05UQUlORVIsQ2F0ZWdvcnkuUEFSQUdSQVBIXSksLTgwMDAsODAwMAogICAgICAgICAgICAsRm9ybWF0VmFsdWUuQVVUTwogICAgICAgICk7CiAgICAgICAgLyoqIEBwcml2YXRlICovCiAgICAgICAgc3RhdGljIHB1YmxpYyBjb25zdCBjb2x1bW5Db3VudFByb3BlcnR5OlByb3BlcnR5ID0gUHJvcGVydHkuTmV3SW50T3JFbnVtUHJvcGVydHkoCiAgICAgICAgICAgICJjb2x1bW5Db3VudCIsRm9ybWF0VmFsdWUuQVVUTyxmYWxzZSxWZWN0b3IuPFN0cmluZz4oW0NhdGVnb3J5LkNPTlRBSU5FUl0pLDEsNTAKICAgICAgICAgICAgLEZvcm1hdFZhbHVlLkFVVE8KICAgICAgICApOwogICAgICAgIC8qKiBAcHJpdmF0ZSAqLwogICAgICAgIHN0YXRpYyBwdWJsaWMgY29uc3QgY29sdW1uV2lkdGhQcm9wZXJ0eTpQcm9wZXJ0eSA9IFByb3BlcnR5Lk5ld051bWJlck9yRW51bVByb3BlcnR5KAogICAgICAgICAgICAiY29sdW1uV2lkdGgiLEZvcm1hdFZhbHVlLkFVVE8sZmFsc2UsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5DT05UQUlORVJdKSwwLDgwMDAKICAgICAgICAgICAgLEZvcm1hdFZhbHVlLkFVVE8KICAgICAgICApOwogICAgICAgIC8qKiBAcHJpdmF0ZSAqLwogICAgICAgIHN0YXRpYyBwdWJsaWMgY29uc3QgZmlyc3RCYXNlbGluZU9mZnNldFByb3BlcnR5OlByb3BlcnR5ID0gUHJvcGVydHkuTmV3TnVtYmVyT3JFbnVtUHJvcGVydHkoCiAgICAgICAgICAgICJmaXJzdEJhc2VsaW5lT2Zmc2V0IixCYXNlbGluZU9mZnNldC5BVVRPLHRydWUsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5DT05UQUlORVJdKSwwLDEwMDAKICAgICAgICAgICAgLEJhc2VsaW5lT2Zmc2V0LkFVVE8KICAgICAgICAgICAgLEJhc2VsaW5lT2Zmc2V0LkFTQ0VOVAogICAgICAgICAgICAsQmFzZWxpbmVPZmZzZXQuTElORV9IRUlHSFQKICAgICAgICApOwogICAgICAgIC8qKiBAcHJpdmF0ZSAqLwogICAgICAgIHN0YXRpYyBwdWJsaWMgY29uc3QgdmVydGljYWxBbGlnblByb3BlcnR5OlByb3BlcnR5ID0gUHJvcGVydHkuTmV3RW51bVN0cmluZ1Byb3BlcnR5KAogICAgICAgICAgICAidmVydGljYWxBbGlnbiIsVmVydGljYWxBbGlnbi5UT1AsZmFsc2UsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5DT05UQUlORVJdKQogICAgICAgICAgICAsVmVydGljYWxBbGlnbi5UT1AKICAgICAgICAgICAgLFZlcnRpY2FsQWxpZ24uTUlERExFCiAgICAgICAgICAgICxWZXJ0aWNhbEFsaWduLkJPVFRPTQogICAgICAgICAgICAsVmVydGljYWxBbGlnbi5KVVNUSUZZCiAgICAgICAgKTsKICAgICAgICAvKiogQHByaXZhdGUgKi8KICAgICAgICBzdGF0aWMgcHVibGljIGNvbnN0IGJsb2NrUHJvZ3Jlc3Npb25Qcm9wZXJ0eTpQcm9wZXJ0eSA9IFByb3BlcnR5Lk5ld0VudW1TdHJpbmdQcm9wZXJ0eSgKICAgICAgICAgICAgImJsb2NrUHJvZ3Jlc3Npb24iLEJsb2NrUHJvZ3Jlc3Npb24uVEIsdHJ1ZSxWZWN0b3IuPFN0cmluZz4oW0NhdGVnb3J5LkNPTlRBSU5FUl0pCiAgICAgICAgICAgICxCbG9ja1Byb2dyZXNzaW9uLlJMCiAgICAgICAgICAgICxCbG9ja1Byb2dyZXNzaW9uLlRCCiAgICAgICAgKTsKICAgICAgICAvKiogQHByaXZhdGUgKi8KICAgICAgICBzdGF0aWMgcHVibGljIGNvbnN0IGxpbmVCcmVha1Byb3BlcnR5OlByb3BlcnR5ID0gUHJvcGVydHkuTmV3RW51bVN0cmluZ1Byb3BlcnR5KAogICAgICAgICAgICAibGluZUJyZWFrIixMaW5lQnJlYWsuVE9fRklULGZhbHNlLFZlY3Rvci48U3RyaW5nPihbQ2F0ZWdvcnkuQ09OVEFJTkVSXSkKICAgICAgICAgICAgLExpbmVCcmVhay5FWFBMSUNJVAogICAgICAgICAgICAsTGluZUJyZWFrLlRPX0ZJVAogICAgICAgICk7CiAgICAgICAgLyoqIEBwcml2YXRlICovCiAgICAgICAgc3RhdGljIHB1YmxpYyBjb25zdCBsaXN0U3R5bGVUeXBlUHJvcGVydHk6UHJvcGVydHkgPSBQcm9wZXJ0eS5OZXdFbnVtU3RyaW5nUHJvcGVydHkoCiAgICAgICAgICAgICJsaXN0U3R5bGVUeXBlIixMaXN0U3R5bGVUeXBlLkRJU0MsdHJ1ZSxWZWN0b3IuPFN0cmluZz4oW0NhdGVnb3J5LkxJU1RdKQogICAgICAgICAgICAsTGlzdFN0eWxlVHlwZS5VUFBFUl9BTFBIQQogICAgICAgICAgICAsTGlzdFN0eWxlVHlwZS5MT1dFUl9BTFBIQQogICAgICAgICAgICAsTGlzdFN0eWxlVHlwZS5VUFBFUl9ST01BTgogICAgICAgICAgICAsTGlzdFN0eWxlVHlwZS5MT1dFUl9ST01BTgogICAgICAgICAgICAsTGlzdFN0eWxlVHlwZS5OT05FCiAgICAgICAgICAgICxMaXN0U3R5bGVUeXBlLkRJU0MKICAgICAgICAgICAgLExpc3RTdHlsZVR5cGUuQ0lSQ0xFCiAgICAgICAgICAgICxMaXN0U3R5bGVUeXBlLlNRVUFSRQogICAgICAgICAgICAsTGlzdFN0eWxlVHlwZS5CT1gKICAgICAgICAgICAgLExpc3RTdHlsZVR5cGUuQ0hFQ0sKICAgICAgICAgICAgLExpc3RTdHlsZVR5cGUuRElBTU9ORAogICAgICAgICAgICAsTGlzdFN0eWxlVHlwZS5IWVBIRU4KICAgICAgICAgICAgLExpc3RTdHlsZVR5cGUuQVJBQklDX0lORElDCiAgICAgICAgICAgICxMaXN0U3R5bGVUeXBlLkJFTkdBTEkKICAgICAgICAgICAgLExpc3RTdHlsZVR5cGUuREVDSU1BTAogICAgICAgICAgICAsTGlzdFN0eWxlVHlwZS5ERUNJTUFMX0xFQURJTkdfWkVSTwogICAgICAgICAgICAsTGlzdFN0eWxlVHlwZS5ERVZBTkFHQVJJCiAgICAgICAgICAgICxMaXN0U3R5bGVUeXBlLkdVSkFSQVRJCiAgICAgICAgICAgICxMaXN0U3R5bGVUeXBlLkdVUk1VS0hJCiAgICAgICAgICAgICxMaXN0U3R5bGVUeXBlLktBTk5BREEKICAgICAgICAgICAgLExpc3RTdHlsZVR5cGUuUEVSU0lBTgogICAgICAgICAgICAsTGlzdFN0eWxlVHlwZS5USEFJCiAgICAgICAgICAgICxMaXN0U3R5bGVUeXBlLlVSRFUKICAgICAgICAgICAgLExpc3RTdHlsZVR5cGUuQ0pLX0VBUlRITFlfQlJBTkNICiAgICAgICAgICAgICxMaXN0U3R5bGVUeXBlLkNKS19IRUFWRU5MWV9TVEVNCiAgICAgICAgICAgICxMaXN0U3R5bGVUeXBlLkhBTkdVTAogICAgICAgICAgICAsTGlzdFN0eWxlVHlwZS5IQU5HVUxfQ09OU1RBTlQKICAgICAgICAgICAgLExpc3RTdHlsZVR5cGUuSElSQUdBTkEKICAgICAgICAgICAgLExpc3RTdHlsZVR5cGUuSElSQUdBTkFfSVJPSEEKICAgICAgICAgICAgLExpc3RTdHlsZVR5cGUuS0FUQUtBTkEKICAgICAgICAgICAgLExpc3RTdHlsZVR5cGUuS0FUQUtBTkFfSVJPSEEKICAgICAgICAgICAgLExpc3RTdHlsZVR5cGUuTE9XRVJfQUxQSEEKICAgICAgICAgICAgLExpc3RTdHlsZVR5cGUuTE9XRVJfR1JFRUsKICAgICAgICAgICAgLExpc3RTdHlsZVR5cGUuTE9XRVJfTEFUSU4KICAgICAgICAgICAgLExpc3RTdHlsZVR5cGUuVVBQRVJfQUxQSEEKICAgICAgICAgICAgLExpc3RTdHlsZVR5cGUuVVBQRVJfR1JFRUsKICAgICAgICAgICAgLExpc3RTdHlsZVR5cGUuVVBQRVJfTEFUSU4KICAgICAgICApOwogICAgICAgIC8qKiBAcHJpdmF0ZSAqLwogICAgICAgIHN0YXRpYyBwdWJsaWMgY29uc3QgbGlzdFN0eWxlUG9zaXRpb25Qcm9wZXJ0eTpQcm9wZXJ0eSA9IFByb3BlcnR5Lk5ld0VudW1TdHJpbmdQcm9wZXJ0eSgKICAgICAgICAgICAgImxpc3RTdHlsZVBvc2l0aW9uIixMaXN0U3R5bGVQb3NpdGlvbi5PVVRTSURFLHRydWUsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5MSVNUXSkKICAgICAgICAgICAgLExpc3RTdHlsZVBvc2l0aW9uLklOU0lERQogICAgICAgICAgICAsTGlzdFN0eWxlUG9zaXRpb24uT1VUU0lERQogICAgICAgICk7CiAgICAgICAgLyoqIEBwcml2YXRlICovCiAgICAgICAgc3RhdGljIHB1YmxpYyBjb25zdCBsaXN0QXV0b1BhZGRpbmdQcm9wZXJ0eTpQcm9wZXJ0eSA9IFByb3BlcnR5Lk5ld051bWJlclByb3BlcnR5KCJsaXN0QXV0b1BhZGRpbmciLDQwLHRydWUsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5DT05UQUlORVJdKSwtMTAwMCwxMDAwKTsKICAgICAgICAvKiogQHByaXZhdGUgKi8KICAgICAgICBzdGF0aWMgcHVibGljIGNvbnN0IGNsZWFyRmxvYXRzUHJvcGVydHk6UHJvcGVydHkgPSBQcm9wZXJ0eS5OZXdFbnVtU3RyaW5nUHJvcGVydHkoCiAgICAgICAgICAgICJjbGVhckZsb2F0cyIsQ2xlYXJGbG9hdHMuTk9ORSxmYWxzZSxWZWN0b3IuPFN0cmluZz4oW0NhdGVnb3J5LlBBUkFHUkFQSF0pCiAgICAgICAgICAgICxDbGVhckZsb2F0cy5TVEFSVAogICAgICAgICAgICAsQ2xlYXJGbG9hdHMuRU5ECiAgICAgICAgICAgICxDbGVhckZsb2F0cy5MRUZUCiAgICAgICAgICAgICxDbGVhckZsb2F0cy5SSUdIVAogICAgICAgICAgICAsQ2xlYXJGbG9hdHMuQk9USAogICAgICAgICAgICAsQ2xlYXJGbG9hdHMuTk9ORQogICAgICAgICk7CiAgICAgICAgLyoqIEBwcml2YXRlICovCiAgICAgICAgc3RhdGljIHB1YmxpYyBjb25zdCBzdHlsZU5hbWVQcm9wZXJ0eTpQcm9wZXJ0eSA9IFByb3BlcnR5Lk5ld1N0cmluZ1Byb3BlcnR5KCJzdHlsZU5hbWUiLG51bGwsZmFsc2UsVmVjdG9yLjxTdHJpbmc+KFtDYXRlZ29yeS5TVFlMRV0pKTsKICAgICAgICAvKiogQHByaXZhdGUgKi8KICAgICAgICBzdGF0aWMgcHVibGljIGNvbnN0IGxpbmtOb3JtYWxGb3JtYXRQcm9wZXJ0eTpQcm9wZXJ0eSA9IFByb3BlcnR5Lk5ld1RleHRMYXlvdXRGb3JtYXRQcm9wZXJ0eSgibGlua05vcm1hbEZvcm1hdCIsbnVsbCx0cnVlLFZlY3Rvci48U3RyaW5nPihbQ2F0ZWdvcnkuU1RZTEVdKSk7CiAgICAgICAgLyoqIEBwcml2YXRlICovCiAgICAgICAgc3RhdGljIHB1YmxpYyBjb25zdCBsaW5rQWN0aXZlRm9ybWF0UHJvcGVydHk6UHJvcGVydHkgPSBQcm9wZXJ0eS5OZXdUZXh0TGF5b3V0Rm9ybWF0UHJvcGVydHkoImxpbmtBY3RpdmVGb3JtYXQiLG51bGwsdHJ1ZSxWZWN0b3IuPFN0cmluZz4oW0NhdGVnb3J5LlNUWUxFXSkpOwogICAgICAgIC8qKiBAcHJpdmF0ZSAqLwogICAgICAgIHN0YXRpYyBwdWJsaWMgY29uc3QgbGlua0hvdmVyRm9ybWF0UHJvcGVydHk6UHJvcGVydHkgPSBQcm9wZXJ0eS5OZXdUZXh0TGF5b3V0Rm9ybWF0UHJvcGVydHkoImxpbmtIb3ZlckZvcm1hdCIsbnVsbCx0cnVlLFZlY3Rvci48U3RyaW5nPihbQ2F0ZWdvcnkuU1RZTEVdKSk7CiAgICAgICAgLyoqIEBwcml2YXRlICovCiAgICAgICAgc3RhdGljIHB1YmxpYyBjb25zdCBsaXN0TWFya2VyRm9ybWF0UHJvcGVydHk6UHJvcGVydHkgPSBQcm9wZXJ0eS5OZXdMaXN0TWFya2VyRm9ybWF0UHJvcGVydHkoImxpc3RNYXJrZXJGb3JtYXQiLG51bGwsdHJ1ZSxWZWN0b3IuPFN0cmluZz4oW0NhdGVnb3J5LlNUWUxFXSkpOwoKICAgICAgICBzdGF0aWMgcHJpdmF0ZSB2YXIgX2Rlc2NyaXB0aW9uOk9iamVjdCA9IHsKICAgICAgICAgICAgICBjb2xvcjpjb2xvclByb3BlcnR5CiAgICAgICAgICAgICwgYmFja2dyb3VuZENvbG9yOmJhY2tncm91bmRDb2xvclByb3BlcnR5CiAgICAgICAgICAgICwgbGluZVRocm91Z2g6bGluZVRocm91Z2hQcm9wZXJ0eQogICAgICAgICAgICAsIHRleHRBbHBoYTp0ZXh0QWxwaGFQcm9wZXJ0eQogICAgICAgICAgICAsIGJhY2tncm91bmRBbHBoYTpiYWNrZ3JvdW5kQWxwaGFQcm9wZXJ0eQogICAgICAgICAgICAsIGZvbnRTaXplOmZvbnRTaXplUHJvcGVydHkKICAgICAgICAgICAgLCBiYXNlbGluZVNoaWZ0OmJhc2VsaW5lU2hpZnRQcm9wZXJ0eQogICAgICAgICAgICAsIHRyYWNraW5nTGVmdDp0cmFja2luZ0xlZnRQcm9wZXJ0eQogICAgICAgICAgICAsIHRyYWNraW5nUmlnaHQ6dHJhY2tpbmdSaWdodFByb3BlcnR5CiAgICAgICAgICAgICwgbGluZUhlaWdodDpsaW5lSGVpZ2h0UHJvcGVydHkKICAgICAgICAgICAgLCBicmVha09wcG9ydHVuaXR5OmJyZWFrT3Bwb3J0dW5pdHlQcm9wZXJ0eQogICAgICAgICAgICAsIGRpZ2l0Q2FzZTpkaWdpdENhc2VQcm9wZXJ0eQogICAgICAgICAgICAsIGRpZ2l0V2lkdGg6ZGlnaXRXaWR0aFByb3BlcnR5CiAgICAgICAgICAgICwgZG9taW5hbnRCYXNlbGluZTpkb21pbmFudEJhc2VsaW5lUHJvcGVydHkKICAgICAgICAgICAgLCBrZXJuaW5nOmtlcm5pbmdQcm9wZXJ0eQogICAgICAgICAgICAsIGxpZ2F0dXJlTGV2ZWw6bGlnYXR1cmVMZXZlbFByb3BlcnR5CiAgICAgICAgICAgICwgYWxpZ25tZW50QmFzZWxpbmU6YWxpZ25tZW50QmFzZWxpbmVQcm9wZXJ0eQogICAgICAgICAgICAsIGxvY2FsZTpsb2NhbGVQcm9wZXJ0eQogICAgICAgICAgICAsIHR5cG9ncmFwaGljQ2FzZTp0eXBvZ3JhcGhpY0Nhc2VQcm9wZXJ0eQogICAgICAgICAgICAsIGZvbnRGYW1pbHk6Zm9udEZhbWlseVByb3BlcnR5CiAgICAgICAgICAgICwgdGV4dERlY29yYXRpb246dGV4dERlY29yYXRpb25Qcm9wZXJ0eQogICAgICAgICAgICAsIGZvbnRXZWlnaHQ6Zm9udFdlaWdodFByb3BlcnR5CiAgICAgICAgICAgICwgZm9udFN0eWxlOmZvbnRTdHlsZVByb3BlcnR5CiAgICAgICAgICAgICwgd2hpdGVTcGFjZUNvbGxhcHNlOndoaXRlU3BhY2VDb2xsYXBzZVByb3BlcnR5CiAgICAgICAgICAgICwgcmVuZGVyaW5nTW9kZTpyZW5kZXJpbmdNb2RlUHJvcGVydHkKICAgICAgICAgICAgLCBjZmZIaW50aW5nOmNmZkhpbnRpbmdQcm9wZXJ0eQogICAgICAgICAgICAsIGZvbnRMb29rdXA6Zm9udExvb2t1cFByb3BlcnR5CiAgICAgICAgICAgICwgdGV4dFJvdGF0aW9uOnRleHRSb3RhdGlvblByb3BlcnR5CiAgICAgICAgICAgICwgdGV4dEluZGVudDp0ZXh0SW5kZW50UHJvcGVydHkKICAgICAgICAgICAgLCBwYXJhZ3JhcGhTdGFydEluZGVudDpwYXJhZ3JhcGhTdGFydEluZGVudFByb3BlcnR5CiAgICAgICAgICAgICwgcGFyYWdyYXBoRW5kSW5kZW50OnBhcmFncmFwaEVuZEluZGVudFByb3BlcnR5CiAgICAgICAgICAgICwgcGFyYWdyYXBoU3BhY2VCZWZvcmU6cGFyYWdyYXBoU3BhY2VCZWZvcmVQcm9wZXJ0eQogICAgICAgICAgICAsIHBhcmFncmFwaFNwYWNlQWZ0ZXI6cGFyYWdyYXBoU3BhY2VBZnRlclByb3BlcnR5CiAgICAgICAgICAgICwgdGV4dEFsaWduOnRleHRBbGlnblByb3BlcnR5CiAgICAgICAgICAgICwgdGV4dEFsaWduTGFzdDp0ZXh0QWxpZ25MYXN0UHJvcGVydHkKICAgICAgICAgICAgLCB0ZXh0SnVzdGlmeTp0ZXh0SnVzdGlmeVByb3BlcnR5CiAgICAgICAgICAgICwganVzdGlmaWNhdGlvblJ1bGU6anVzdGlmaWNhdGlvblJ1bGVQcm9wZXJ0eQogICAgICAgICAgICAsIGp1c3RpZmljYXRpb25TdHlsZTpqdXN0aWZpY2F0aW9uU3R5bGVQcm9wZXJ0eQogICAgICAgICAgICAsIGRpcmVjdGlvbjpkaXJlY3Rpb25Qcm9wZXJ0eQogICAgICAgICAgICAsIHdvcmRTcGFjaW5nOndvcmRTcGFjaW5nUHJvcGVydHkKICAgICAgICAgICAgLCB0YWJTdG9wczp0YWJTdG9wc1Byb3BlcnR5CiAgICAgICAgICAgICwgbGVhZGluZ01vZGVsOmxlYWRpbmdNb2RlbFByb3BlcnR5CiAgICAgICAgICAgICwgY29sdW1uR2FwOmNvbHVtbkdhcFByb3BlcnR5CiAgICAgICAgICAgICwgcGFkZGluZ0xlZnQ6cGFkZGluZ0xlZnRQcm9wZXJ0eQogICAgICAgICAgICAsIHBhZGRpbmdUb3A6cGFkZGluZ1RvcFByb3BlcnR5CiAgICAgICAgICAgICwgcGFkZGluZ1JpZ2h0OnBhZGRpbmdSaWdodFByb3BlcnR5CiAgICAgICAgICAgICwgcGFkZGluZ0JvdHRvbTpwYWRkaW5nQm90dG9tUHJvcGVydHkKICAgICAgICAgICAgLCBjb2x1bW5Db3VudDpjb2x1bW5Db3VudFByb3BlcnR5CiAgICAgICAgICAgICwgY29sdW1uV2lkdGg6Y29sdW1uV2lkdGhQcm9wZXJ0eQogICAgICAgICAgICAsIGZpcnN0QmFzZWxpbmVPZmZzZXQ6Zmlyc3RCYXNlbGluZU9mZnNldFByb3BlcnR5CiAgICAgICAgICAgICwgdmVydGljYWxBbGlnbjp2ZXJ0aWNhbEFsaWduUHJvcGVydHkKICAgICAgICAgICAgLCBibG9ja1Byb2dyZXNzaW9uOmJsb2NrUHJvZ3Jlc3Npb25Qcm9wZXJ0eQogICAgICAgICAgICAsIGxpbmVCcmVhazpsaW5lQnJlYWtQcm9wZXJ0eQogICAgICAgICAgICAsIGxpc3RTdHlsZVR5cGU6bGlzdFN0eWxlVHlwZVByb3BlcnR5CiAgICAgICAgICAgICwgbGlzdFN0eWxlUG9zaXRpb246bGlzdFN0eWxlUG9zaXRpb25Qcm9wZXJ0eQogICAgICAgICAgICAsIGxpc3RBdXRvUGFkZGluZzpsaXN0QXV0b1BhZGRpbmdQcm9wZXJ0eQogICAgICAgICAgICAsIGNsZWFyRmxvYXRzOmNsZWFyRmxvYXRzUHJvcGVydHkKICAgICAgICAgICAgLCBzdHlsZU5hbWU6c3R5bGVOYW1lUHJvcGVydHkKICAgICAgICAgICAgLCBsaW5rTm9ybWFsRm9ybWF0OmxpbmtOb3JtYWxGb3JtYXRQcm9wZXJ0eQogICAgICAgICAgICAsIGxpbmtBY3RpdmVGb3JtYXQ6bGlua0FjdGl2ZUZvcm1hdFByb3BlcnR5CiAgICAgICAgICAgICwgbGlua0hvdmVyRm9ybWF0OmxpbmtIb3ZlckZvcm1hdFByb3BlcnR5CiAgICAgICAgICAgICwgbGlzdE1hcmtlckZvcm1hdDpsaXN0TWFya2VyRm9ybWF0UHJvcGVydHkKICAgICAgICB9CgogICAgICAgIC8qKiBQcm9wZXJ0eSBkZXNjcmlwdGlvbnMgYWNjZXNzaWJsZSBieSBuYW1lLiBAcHJpdmF0ZSAqLwogICAgICAgIHN0YXRpYyB0bGZfaW50ZXJuYWwgZnVuY3Rpb24gZ2V0IGRlc2NyaXB0aW9uKCk6T2JqZWN0CiAgICAgICAgeyByZXR1cm4gX2Rlc2NyaXB0aW9uOyB9CgogICAgICAgIC8qKiBAcHJpdmF0ZSAqLwogICAgICAgIHN0YXRpYyBwcml2YXRlIHZhciBfZW1wdHlUZXh0TGF5b3V0Rm9ybWF0OklUZXh0TGF5b3V0Rm9ybWF0OwogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybnMgYW4gSVRleHRMYXlvdXRGb3JtYXQgaW5zdGFuY2Ugd2l0aCBhbGwgcHJvcGVydGllcyBzZXQgdG8gPGNvZGU+dW5kZWZpbmVkPC9jb2RlPi4KICAgICAgICAgKiBAcHJpdmF0ZQogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQogICAgICAgICAqIEBsYW5ndmVyc2lvbiAzLjAKICAgICAgICAgKi8KICAgICAgICBzdGF0aWMgdGxmX2ludGVybmFsIGZ1bmN0aW9uIGdldCBlbXB0eVRleHRMYXlvdXRGb3JtYXQoKTpJVGV4dExheW91dEZvcm1hdAogICAgICAgIHsKICAgICAgICAgICAgaWYgKF9lbXB0eVRleHRMYXlvdXRGb3JtYXQgPT0gbnVsbCkKICAgICAgICAgICAgICAgIF9lbXB0eVRleHRMYXlvdXRGb3JtYXQgPSBuZXcgVGV4dExheW91dEZvcm1hdCgpOwogICAgICAgICAgICByZXR1cm4gX2VtcHR5VGV4dExheW91dEZvcm1hdDsKICAgICAgICB9CgoKICAgICAgICBwcml2YXRlIHN0YXRpYyBjb25zdCBfZW1wdHlTdHlsZXM6T2JqZWN0ID0gbmV3IE9iamVjdCgpOwogICAgICAgIC8qKiBfc3R5bGVzIGlzIG5ldmVyIG51bGwgKi8KICAgICAgICBwcml2YXRlIHZhciBfc3R5bGVzOk9iamVjdDsKICAgICAgICBwcml2YXRlIHZhciBfc2hhcmVkU3R5bGVzOkJvb2xlYW47CgogICAgICAgIC8qKgogICAgICAgICAqIENyZWF0ZXMgYSBuZXcgVGV4dExheW91dEZvcm1hdCBvYmplY3QuIEFsbCBzZXR0aW5ncyBhcmUgZW1wdHkgb3IsIG9wdGlvbmFsbHksIGFyZSBpbml0aWFsaXplZCBmcm9tIHRoZQogICAgICAgICAqIHN1cHBsaWVkIDxjb2RlPmluaXRpYWxWYWx1ZXM8L2NvZGU+IG9iamVjdC4KICAgICAgICAgKiAKICAgICAgICAgKiBAcGFyYW0gaW5pdGlhbFZhbHVlcyBvcHRpb25hbCBpbnN0YW5jZSBmcm9tIHdoaWNoIHRvIGNvcHkgaW5pdGlhbCB2YWx1ZXMuCiAgICAgICAgICogCiAgICAgICAgICogQHNlZSAjZGVmYXVsdEZvcm1hdAogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQogICAgICAgICAqIEBsYW5ndmVyc2lvbiAzLjAKICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgZnVuY3Rpb24gVGV4dExheW91dEZvcm1hdChpbml0aWFsVmFsdWVzOklUZXh0TGF5b3V0Rm9ybWF0ID0gbnVsbCkKICAgICAgICB7CiAgICAgICAgICAgIHRoaXMuY29weShpbml0aWFsVmFsdWVzKTsKICAgICAgICB9CgogICAgICAgIHByaXZhdGUgZnVuY3Rpb24gd3JpdGFibGVTdHlsZXMoKTp2b2lkCiAgICAgICAgewogICAgICAgICAgICBpZiAoX3NoYXJlZFN0eWxlcykKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgX3N0eWxlcyA9IF9zdHlsZXMgPT0gX2VtcHR5U3R5bGVzID8gbmV3IE9iamVjdCgpIDogUHJvcGVydHkuY3JlYXRlT2JqZWN0V2l0aFByb3RvdHlwZShfc3R5bGVzKTsKICAgICAgICAgICAgICAgIF9zaGFyZWRTdHlsZXMgPSBmYWxzZTsKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgLyoqIEBwcml2YXRlIFJldHVybnMgdGhlIGludGVybmFsIHN0eWxlcyBvYmplY3QuICovCiAgICAgICAgdGxmX2ludGVybmFsIGZ1bmN0aW9uIGdldFN0eWxlcygpOk9iamVjdAogICAgICAgIHsgcmV0dXJuIF9zdHlsZXMgPT0gX2VtcHR5U3R5bGVzID8gbnVsbCA6IF9zdHlsZXM7IH0KICAgICAgICAvKiogQHByaXZhdGUgKi8KICAgICAgICB0bGZfaW50ZXJuYWwgZnVuY3Rpb24gc2V0U3R5bGVzKHZhbDpPYmplY3Qsc2hhcmVkOkJvb2xlYW4pOnZvaWQKICAgICAgICB7CiAgICAgICAgICAgIENPTkZJRzo6ZGVidWcgeyBhc3NlcnQodmFsLCJCQUQgc2V0U3R5bGVzIGNhbGwiKTsgfQogICAgICAgICAgICBpZiAoX3N0eWxlcyAhPSB2YWwpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIF9zdHlsZXMgPSB2YWw7CiAgICAgICAgICAgICAgICBfc2hhcmVkU3R5bGVzID0gc2hhcmVkOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIC8qKiBAcHJpdmF0ZSAqLwogICAgICAgIHRsZl9pbnRlcm5hbCBmdW5jdGlvbiBjbGVhclN0eWxlcygpOnZvaWQKICAgICAgICB7CiAgICAgICAgICAgIF9zdHlsZXMgPSBfZW1wdHlTdHlsZXM7CiAgICAgICAgICAgIF9zaGFyZWRTdHlsZXMgPSB0cnVlOwogICAgICAgIH0KCiAgICAgICAgLyoqIFJldHVybnMgdGhlIDxjb2RlPmNvcmVTdHlsZXM8L2NvZGU+IG9uIHRoaXMgVGV4dExheW91dEZvcm1hdC4gIAogICAgICAgICAqIFRoZSBjb3JlU3R5bGVzIG9iamVjdCBpbmNsdWRlcyB0aGUgZm9ybWF0cyB0aGF0IGFyZSBkZWZpbmVkIGJ5IFRleHRMYXlvdXRGb3JtYXQgYW5kIGFyZSBpbiBUZXh0TGF5b3V0Rm9ybWF0LmRlc2NyaXB0aW9uLiBUaGUKICAgICAgICAgKiByZXR1cm5lZCA8Y29kZT5jb3JlU3R5bGVzPC9jb2RlPiBvYmplY3QgY29uc2lzdHMgb2YgYW4gYXJyYXkgb2YgPGVtPnN0eWxlbmFtZS12YWx1ZTwvZW0+IHBhaXJzLgogICAgICAgICAqIAogICAgICAgICAqIEBzZWUgZmxhc2h4LnRleHRMYXlvdXQuZm9ybWF0cy5UZXh0TGF5b3V0Rm9ybWF0CiAgICAgICAgICogCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gRmxhc2ggMTAKICAgICAgICAgKiBAcGxheWVydmVyc2lvbiBBSVIgMS41CiAgICAgICAgICogQGxhbmd2ZXJzaW9uIDMuMAogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBmdW5jdGlvbiBnZXQgY29yZVN0eWxlcygpOk9iamVjdAogICAgICAgIHsKICAgICAgICAgICAgcmV0dXJuIF9zdHlsZXMgPT0gX2VtcHR5U3R5bGVzID8gbnVsbCA6IFByb3BlcnR5LnNoYWxsb3dDb3B5SW5GaWx0ZXIoX3N0eWxlcyxkZXNjcmlwdGlvbik7CiAgICAgICAgfQoKICAgICAgICAvKiogUmV0dXJucyB0aGUgPGNvZGU+dXNlclN0eWxlczwvY29kZT4gb24gdGhpcyBUZXh0TGF5b3V0Rm9ybWF0LiAgCiAgICAgICAgICogVGhlIHVzZXJTdHlsZXMgb2JqZWN0IGluY2x1ZGVzIHRoZSBmb3JtYXRzIHRoYXQgYXJlIGRlZmluZWQgYnkgVGV4dExheW91dEZvcm1hdCBhbmQgYXJlIG5vdCBpbiBUZXh0TGF5b3V0Rm9ybWF0LmRlc2NyaXB0aW9uLiBUaGUKICAgICAgICAgKiByZXR1cm5lZCA8Y29kZT51c2VyU3R5bGVzPC9jb2RlPiBvYmplY3QgY29uc2lzdHMgb2YgYW4gYXJyYXkgb2YgPGVtPnN0eWxlbmFtZS12YWx1ZTwvZW0+IHBhaXJzLgogICAgICAgICAqIAogICAgICAgICAqIEBzZWUgZmxhc2h4LnRleHRMYXlvdXQuZm9ybWF0cy5UZXh0TGF5b3V0Rm9ybWF0CiAgICAgICAgICogCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gRmxhc2ggMTAKICAgICAgICAgKiBAcGxheWVydmVyc2lvbiBBSVIgMS41CiAgICAgICAgICogQGxhbmd2ZXJzaW9uIDMuMAogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBmdW5jdGlvbiBnZXQgdXNlclN0eWxlcygpOk9iamVjdAogICAgICAgIHsKICAgICAgICAgICAgcmV0dXJuIF9zdHlsZXMgPT0gX2VtcHR5U3R5bGVzID8gbnVsbCA6IFByb3BlcnR5LnNoYWxsb3dDb3B5Tm90SW5GaWx0ZXIoX3N0eWxlcyxkZXNjcmlwdGlvbik7CiAgICAgICAgfQoKICAgICAgICAvKiogUmV0dXJucyB0aGUgc3R5bGVzIG9uIHRoaXMgVGV4dExheW91dEZvcm1hdC4gIE5vdGUgdGhhdCB0aGUgZ2V0dGVyIG1ha2VzIGEgY29weSBvZiB0aGUgIAogICAgICAgICAqIHN0eWxlcyBkaWN0aW9uYXJ5LiBUaGUgY29yZVN0eWxlcyBvYmplY3QgZW5jYXBzdWxhdGVzIGFsbCBzdHlsZXMgc2V0IGluIHRoZSBmb3JtYXQgcHJvcGVydHkgaW5jbHVkaW5nIGNvcmUgYW5kIHVzZXIgc3R5bGVzLiBUaGUKICAgICAgICAgKiByZXR1cm5lZCBvYmplY3QgY29uc2lzdHMgb2YgYW4gYXJyYXkgb2YgPGVtPnN0eWxlbmFtZS12YWx1ZTwvZW0+IHBhaXJzLgogICAgICAgICAqIAogICAgICAgICAqIEBzZWUgZmxhc2h4LnRleHRMYXlvdXQuZm9ybWF0cy5UZXh0TGF5b3V0Rm9ybWF0CiAgICAgICAgICogCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gRmxhc2ggMTAKICAgICAgICAgKiBAcGxheWVydmVyc2lvbiBBSVIgMS41CiAgICAgICAgICogQGxhbmd2ZXJzaW9uIDMuMAogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBmdW5jdGlvbiBnZXQgc3R5bGVzKCk6T2JqZWN0CiAgICAgICAgewogICAgICAgICAgICByZXR1cm4gX3N0eWxlcyA9PSBfZW1wdHlTdHlsZXMgPyBudWxsIDogUHJvcGVydHkuc2hhbGxvd0NvcHkoX3N0eWxlcyk7CiAgICAgICAgfQoKICAgICAgICAvKiogQHByaXZhdGUgKi8KICAgICAgICB0bGZfaW50ZXJuYWwgZnVuY3Rpb24gc2V0U3R5bGVCeU5hbWUobmFtZTpTdHJpbmcsIG5ld1ZhbHVlOiopOnZvaWQKICAgICAgICB7CiAgICAgICAgICAgIHdyaXRhYmxlU3R5bGVzKCk7CiAgICAgICAgICAgICAgICAKICAgICAgICAgICAgaWYgKG5ld1ZhbHVlICE9PSB1bmRlZmluZWQpCiAgICAgICAgICAgICAgICBfc3R5bGVzW25hbWVdID0gbmV3VmFsdWU7CiAgICAgICAgICAgIGVsc2UKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgZGVsZXRlIF9zdHlsZXNbbmFtZV07CiAgICAgICAgICAgICAgICBpZiAoX3N0eWxlc1tuYW1lXSAhPT0gdW5kZWZpbmVkKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIF9zdHlsZXMgPSBQcm9wZXJ0eS5zaGFsbG93Q29weShfc3R5bGVzKTsKICAgICAgICAgICAgICAgICAgICBkZWxldGUgX3N0eWxlc1tuYW1lXTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgLyoqIEludGVudGlvbmFsbHkgaGlkZGVuIHNvIHRoYXQgb3ZlcnJpZGVycyBjYW4gb3ZlcnJpZGUgaW5kaXZpZHVhbCBwcm9wZXJ0eSBzZXR0ZXJzICovCiAgICAgICAgcHJpdmF0ZSBmdW5jdGlvbiBzZXRTdHlsZUJ5UHJvcGVydHkoc3R5bGVQcm9wOlByb3BlcnR5LG5ld1ZhbHVlOiopOnZvaWQKICAgICAgICB7CiAgICAgICAgICAgIHZhciBuYW1lOlN0cmluZyA9IHN0eWxlUHJvcC5uYW1lOwogICAgICAgICAgICBuZXdWYWx1ZSA9IHN0eWxlUHJvcC5zZXRIZWxwZXIoX3N0eWxlc1tuYW1lXSxuZXdWYWx1ZSk7CiAgICAgICAgICAgIHNldFN0eWxlQnlOYW1lKG5hbWUsIG5ld1ZhbHVlKTsKICAgICAgICB9CgogICAgICAgIC8qKiBTZXRzIHRoZSBzdHlsZSBzcGVjaWZpZWQgYnkgdGhlIDxjb2RlPnN0eWxlUHJvcDwvY29kZT4gcGFyYW1ldGVyIHRvIHRoZSB2YWx1ZSBzcGVjaWZpZWQgYnkgdGhlCiAgICAgICAgICogPGNvZGU+bmV3VmFsdWU8L2NvZGU+IHBhcmFtZXRlci4gCiAgICAgICAgICoKICAgICAgICAgKiBAcGFyYW0gc3R5bGVQcm9wIFRoZSBuYW1lIG9mIHRoZSBzdHlsZSB0byBzZXQuCiAgICAgICAgICogQHBhcmFtIG5ld1ZhbHVlIFRoZSB2YWx1ZSB0byB3aGljaCB0byBzZXQgdGhlIHN0eWxlLgogICAgICAgICAqLgogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQogICAgICAgICAqIEBsYW5ndmVyc2lvbiAzLjAKCiAgICAgICAgICovCiAgICAgICAgcHVibGljIGZ1bmN0aW9uIHNldFN0eWxlKHN0eWxlUHJvcDpTdHJpbmcsbmV3VmFsdWU6Kik6dm9pZAogICAgICAgIHsKICAgICAgICAgICAgLyoqIHJlZGlyZWN0IHRvIGV4aXN0aW5nIHByb3BlcnR5IHNldHRlcnMgZm9yIG92ZXJyaWRlcnMqLwogICAgICAgICAgICBpZiAoZGVzY3JpcHRpb24uaGFzT3duUHJvcGVydHkoc3R5bGVQcm9wKSkKICAgICAgICAgICAgICAgIHRoaXNbc3R5bGVQcm9wXSA9IG5ld1ZhbHVlOwogICAgICAgICAgICBlbHNlCiAgICAgICAgICAgICAgICBzZXRTdHlsZUJ5TmFtZShzdHlsZVByb3AsbmV3VmFsdWUpOwogICAgICAgIH0KCiAgICAgICAgLyoqIFJldHVybnMgdGhlIHZhbHVlIG9mIHRoZSBzdHlsZSBzcGVjaWZpZWQgYnkgdGhlIDxjb2RlPnN0eWxlUHJvcDwvY29kZT4gcGFyYW1ldGVyLCB3aGljaCBzcGVjaWZpZXMKICAgICAgICAgKiB0aGUgc3R5bGUgbmFtZS4KICAgICAgICAgKgogICAgICAgICAqIEBwYXJhbSBzdHlsZVByb3AgVGhlIG5hbWUgb2YgdGhlIHN0eWxlIHdob3NlIHZhbHVlIGlzIHRvIGJlIHJldHJpZXZlZC4KICAgICAgICAgKgogICAgICAgICAqIEByZXR1cm4gVGhlIHZhbHVlIG9mIHRoZSBzcGVjaWZpZWQgc3R5bGUuIFRoZSB0eXBlIHZhcmllcyBkZXBlbmRpbmcgb24gdGhlIHR5cGUgb2YgdGhlIHN0eWxlIGJlaW5nCiAgICAgICAgICogYWNjZXNzZWQuIFJldHVybnMgPGNvZGU+dW5kZWZpbmVkPC9jb2RlPiBpZiB0aGUgc3R5bGUgaXMgbm90IHNldC4KICAgICAgICAgKiAKICAgICAgICAgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKICAgICAgICAgKiBAbGFuZ3ZlcnNpb24gMy4wCiAgICAgICAgICovCiAgICAgICAgcHVibGljIGZ1bmN0aW9uIGdldFN0eWxlKHN0eWxlUHJvcDpTdHJpbmcpOioKICAgICAgICB7IHJldHVybiBfc3R5bGVzW3N0eWxlUHJvcF07IH0KCiAgICAgICAgLyoqCiAgICAgICAgICogQ29waWVzIFRleHRMYXlvdXRGb3JtYXQgc2V0dGluZ3MgZnJvbSB0aGUgPGNvZGU+dmFsdWVzPC9jb2RlPiBJVGV4dExheW91dEZvcm1hdCBpbnN0YW5jZSBpbnRvIHRoaXMgVGV4dExheW91dEZvcm1hdCBvYmplY3QuCiAgICAgICAgICogSWYgPGNvZGU+dmFsdWVzPC9jb2RlPiBpcyA8Y29kZT5udWxsPC9jb2RlPiwgdGhpcyBUZXh0TGF5b3V0Rm9ybWF0IG9iamVjdCBpcyBpbml0aWFsaXplZCB3aXRoIHVuZGVmaW5lZCB2YWx1ZXMgZm9yIGFsbCBwcm9wZXJ0aWVzLgogICAgICAgICAqIEBwYXJhbSB2YWx1ZXMgb3B0aW9uYWwgaW5zdGFuY2UgZnJvbSB3aGljaCB0byBjb3B5IHZhbHVlcy4KICAgICAgICAgKiAKICAgICAgICAgKiBAaW5jbHVkZUV4YW1wbGUgZXhhbXBsZXNcVGV4dExheW91dEZvcm1hdF9jb3B5RXhhbXBsZS5hcyAtbm9zd2YKICAgICAgICAgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKICAgICAgICAgKiBAbGFuZ3ZlcnNpb24gMy4wCiAgICAgICAgICovCiAgICAgICAgcHVibGljIGZ1bmN0aW9uIGNvcHkoaW5jb21pbmc6SVRleHRMYXlvdXRGb3JtYXQpOnZvaWQKICAgICAgICB7CiAgICAgICAgICAgIGlmICh0aGlzID09IGluY29taW5nKQogICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICB2YXIgaG9sZGVyOlRleHRMYXlvdXRGb3JtYXQgPSBpbmNvbWluZyBhcyBUZXh0TGF5b3V0Rm9ybWF0OwogICAgICAgICAgICBpZiAoaG9sZGVyKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBfc3R5bGVzID0gaG9sZGVyLl9zdHlsZXM7CiAgICAgICAgICAgICAgICBfc2hhcmVkU3R5bGVzID0gdHJ1ZTsKICAgICAgICAgICAgICAgIGhvbGRlci5fc2hhcmVkU3R5bGVzID0gdHJ1ZTsKICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgX3N0eWxlcyA9IF9lbXB0eVN0eWxlczsKICAgICAgICAgICAgX3NoYXJlZFN0eWxlcyA9IHRydWU7CgogICAgICAgICAgICBpZiAoaW5jb21pbmcpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIGZvciBlYWNoICh2YXIgcHJvcDpQcm9wZXJ0eSBpbiBUZXh0TGF5b3V0Rm9ybWF0LmRlc2NyaXB0aW9uKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIHZhciB2YWw6KiA9IGluY29taW5nW3Byb3AubmFtZV07CiAgICAgICAgICAgICAgICAgICAgaWYgKHZhbCAhPT0gdW5kZWZpbmVkKQogICAgICAgICAgICAgICAgICAgICAgICB0aGlzW3Byb3AubmFtZV0gPSB2YWw7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIC8qKgogICAgICAgICAqIENvbmNhdGVuYXRlcyB0aGUgdmFsdWVzIG9mIHByb3BlcnRpZXMgaW4gdGhlIDxjb2RlPmluY29taW5nPC9jb2RlPiBJVGV4dExheW91dEZvcm1hdCBpbnN0YW5jZQogICAgICAgICAqIHdpdGggdGhlIHZhbHVlcyBvZiB0aGlzIFRleHRMYXlvdXRGb3JtYXQgb2JqZWN0LiBJbiB0aGlzICh0aGUgcmVjZWl2aW5nKSBUZXh0TGF5b3V0Rm9ybWF0IG9iamVjdCwgcHJvcGVydGllcyB3aG9zZSB2YWx1ZXMgYXJlIDxjb2RlPkZvcm1hdFZhbHVlLklOSEVSSVQ8L2NvZGU+LAogICAgICAgICAqIGFuZCBpbmhlcml0aW5nIHByb3BlcnRpZXMgd2hvc2UgdmFsdWVzIGFyZSA8Y29kZT51bmRlZmluZWQ8L2NvZGU+IHdpbGwgZ2V0IG5ldyB2YWx1ZXMgZnJvbSB0aGUgPGNvZGU+aW5jb21pbmc8L2NvZGU+IG9iamVjdC4KICAgICAgICAgKiBOb24taW5oZXJpdGluZyBwcm9wZXJ0aWVzIHdob3NlIHZhbHVlcyBhcmUgPGNvZGU+dW5kZWZpbmVkPC9jb2RlPiB3aWxsIGdldCB0aGVpciBkZWZhdWx0IHZhbHVlcy4KICAgICAgICAgKiBBbGwgb3RoZXIgcHJvcGVydHkgdmFsdWVzIHdpbGwgcmVtYWluIHVubW9kaWZpZWQuCiAgICAgICAgICogCiAgICAgICAgICogQHBhcmFtIGluY29taW5nIGluc3RhbmNlIGZyb20gd2hpY2ggdmFsdWVzIGFyZSBjb25jYXRlbmF0ZWQuCiAgICAgICAgICogQHNlZSBmbGFzaHgudGV4dExheW91dC5mb3JtYXRzLkZvcm1hdFZhbHVlI0lOSEVSSVQKICAgICAgICAgKiAKICAgICAgICAgKiBAaW5jbHVkZUV4YW1wbGUgZXhhbXBsZXNcVGV4dExheW91dEZvcm1hdF9jb25jYXRFeGFtcGxlLmFzIC1ub3N3ZgogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQogICAgICAgICAqIEBsYW5ndmVyc2lvbiAzLjAKICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgZnVuY3Rpb24gY29uY2F0KGluY29taW5nOklUZXh0TGF5b3V0Rm9ybWF0KTp2b2lkCiAgICAgICAgewogICAgICAgICAgICB2YXIgaG9sZGVyOlRleHRMYXlvdXRGb3JtYXQgPSBpbmNvbWluZyBhcyBUZXh0TGF5b3V0Rm9ybWF0OwogICAgICAgICAgICB2YXIgcHJvcDpQcm9wZXJ0eTsKICAgICAgICAgICAgaWYgKGhvbGRlcikKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgdmFyIGhvbGRlclN0eWxlczpPYmplY3QgPSBob2xkZXIuX3N0eWxlczsKICAgICAgICAgICAgICAgIGZvciAodmFyIGtleTpTdHJpbmcgaW4gaG9sZGVyU3R5bGVzKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIHByb3AgPSBkZXNjcmlwdGlvbltrZXldOwogICAgICAgICAgICAgICAgICAgIGlmIChwcm9wKQogICAgICAgICAgICAgICAgICAgICAgICBzZXRTdHlsZUJ5UHJvcGVydHkocHJvcCxwcm9wLmNvbmNhdEhlbHBlcihfc3R5bGVzW2tleV0saG9sZGVyU3R5bGVzW2tleV0pKTsKICAgICAgICAgICAgICAgICAgICBlbHNlCiAgICAgICAgICAgICAgICAgICAgICAgIHNldFN0eWxlQnlOYW1lKGtleSxQcm9wZXJ0eS5kZWZhdWx0Q29uY2F0SGVscGVyKF9zdHlsZXNba2V5XSxob2xkZXJTdHlsZXNba2V5XSkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICB9CgogICAgICAgICAgICAvLyBJZ25vcmVzIHVzZXJTdHlsZXMKICAgICAgICAgICAgZm9yIGVhY2ggKHByb3AgaW4gVGV4dExheW91dEZvcm1hdC5kZXNjcmlwdGlvbikKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgc2V0U3R5bGVCeVByb3BlcnR5KHByb3AscHJvcC5jb25jYXRIZWxwZXIoX3N0eWxlc1twcm9wLm5hbWVdLGluY29taW5nW3Byb3AubmFtZV0pKTsKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgLyoqCiAgICAgICAgICogQ29uY2F0ZW5hdGVzIHRoZSB2YWx1ZXMgb2YgcHJvcGVydGllcyBpbiB0aGUgPGNvZGU+aW5jb21pbmc8L2NvZGU+IElUZXh0TGF5b3V0Rm9ybWF0IGluc3RhbmNlCiAgICAgICAgICogd2l0aCB0aGUgdmFsdWVzIG9mIHRoaXMgVGV4dExheW91dEZvcm1hdCBvYmplY3QuIEluIHRoaXMgKHRoZSByZWNlaXZpbmcpIFRleHRMYXlvdXRGb3JtYXQgb2JqZWN0LCBwcm9wZXJ0aWVzIHdob3NlIHZhbHVlcyBhcmUgPGNvZGU+Rm9ybWF0VmFsdWUuSU5IRVJJVDwvY29kZT4sCiAgICAgICAgICogYW5kIGluaGVyaXRpbmcgcHJvcGVydGllcyB3aG9zZSB2YWx1ZXMgYXJlIDxjb2RlPnVuZGVmaW5lZDwvY29kZT4gd2lsbCBnZXQgbmV3IHZhbHVlcyBmcm9tIHRoZSA8Y29kZT5pbmNvbWluZzwvY29kZT4gb2JqZWN0LgogICAgICAgICAqIEFsbCBvdGhlciBwcm9wZXJ0eSB2YWx1ZXMgd2lsbCByZW1haW4gdW5tb2RpZmllZC4KICAgICAgICAgKiAKICAgICAgICAgKiBAcGFyYW0gaW5jb21pbmcgaW5zdGFuY2UgZnJvbSB3aGljaCB2YWx1ZXMgYXJlIGNvbmNhdGVuYXRlZC4KICAgICAgICAgKiBAc2VlIGZsYXNoeC50ZXh0TGF5b3V0LmZvcm1hdHMuRm9ybWF0VmFsdWUjSU5IRVJJVAogICAgICAgICAqIAogICAgICAgICAqIEBpbmNsdWRlRXhhbXBsZSBleGFtcGxlc1xUZXh0TGF5b3V0Rm9ybWF0X2NvbmNhdEluaGVyaXRPbmx5RXhhbXBsZS5hcyAtbm9zd2YKICAgICAgICAgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKICAgICAgICAgKiBAbGFuZ3ZlcnNpb24gMy4wCiAgICAgICAgICovCiAgICAgICAgcHVibGljIGZ1bmN0aW9uIGNvbmNhdEluaGVyaXRPbmx5KGluY29taW5nOklUZXh0TGF5b3V0Rm9ybWF0KTp2b2lkCiAgICAgICAgewogICAgICAgICAgICB2YXIgaG9sZGVyOlRleHRMYXlvdXRGb3JtYXQgPSBpbmNvbWluZyBhcyBUZXh0TGF5b3V0Rm9ybWF0OwogICAgICAgICAgICB2YXIgcHJvcDpQcm9wZXJ0eTsKCiAgICAgICAgICAgIGlmIChob2xkZXIpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIHZhciBob2xkZXJTdHlsZXM6T2JqZWN0ID0gaG9sZGVyLl9zdHlsZXM7CiAgICAgICAgICAgICAgICBmb3IgKHZhciBrZXk6U3RyaW5nIGluIGhvbGRlclN0eWxlcykKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBwcm9wID0gZGVzY3JpcHRpb25ba2V5XTsKICAgICAgICAgICAgICAgICAgICBpZiAocHJvcCkKICAgICAgICAgICAgICAgICAgICAgICAgc2V0U3R5bGVCeVByb3BlcnR5KHByb3AscHJvcC5jb25jYXRJbmhlcml0T25seUhlbHBlcihfc3R5bGVzW2tleV0saG9sZGVyU3R5bGVzW2tleV0pKTsKICAgICAgICAgICAgICAgICAgICBlbHNlCiAgICAgICAgICAgICAgICAgICAgICAgIHNldFN0eWxlQnlOYW1lKGtleSxQcm9wZXJ0eS5kZWZhdWx0Q29uY2F0SGVscGVyKF9zdHlsZXNba2V5XSxob2xkZXJTdHlsZXNba2V5XSkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICB9CgogICAgICAgICAgICAvLyBJZ25vcmVzIHVzZXJTdHlsZXMKICAgICAgICAgICAgZm9yIGVhY2ggKHByb3AgaW4gVGV4dExheW91dEZvcm1hdC5kZXNjcmlwdGlvbikKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgc2V0U3R5bGVCeVByb3BlcnR5KHByb3AscHJvcC5jb25jYXRJbmhlcml0T25seUhlbHBlcihfc3R5bGVzW3Byb3AubmFtZV0saW5jb21pbmdbcHJvcC5uYW1lXSkpOwogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICAvKioKICAgICAgICAgKiBSZXBsYWNlcyBwcm9wZXJ0eSB2YWx1ZXMgaW4gdGhpcyBUZXh0TGF5b3V0Rm9ybWF0IG9iamVjdCB3aXRoIHRoZSB2YWx1ZXMgb2YgcHJvcGVydGllcyB0aGF0IGFyZSBzZXQgaW4KICAgICAgICAgKiB0aGUgPGNvZGU+aW5jb21pbmc8L2NvZGU+IElUZXh0TGF5b3V0Rm9ybWF0IGluc3RhbmNlLiBQcm9wZXJ0aWVzIHRoYXQgYXJlIDxjb2RlPnVuZGVmaW5lZDwvY29kZT4gaW4gdGhlIDxjb2RlPmluY29taW5nPC9jb2RlPgogICAgICAgICAqIElUZXh0TGF5b3V0Rm9ybWF0IGluc3RhbmNlIGFyZSBub3QgY2hhbmdlZCBpbiB0aGlzIG9iamVjdC4KICAgICAgICAgKiAKICAgICAgICAgKiBAcGFyYW0gaW5jb21pbmcgaW5zdGFuY2Ugd2hvc2UgcHJvcGVydHkgdmFsdWVzIGFyZSBhcHBsaWVkIHRvIHRoaXMgVGV4dExheW91dEZvcm1hdCBvYmplY3QuCiAgICAgICAgICogCiAgICAgICAgICogQGluY2x1ZGVFeGFtcGxlIGV4YW1wbGVzXFRleHRMYXlvdXRGb3JtYXRfYXBwbHlFeGFtcGxlLmFzIC1ub3N3ZgogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQogICAgICAgICAqIEBsYW5ndmVyc2lvbiAzLjAKICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgZnVuY3Rpb24gYXBwbHkoaW5jb21pbmc6SVRleHRMYXlvdXRGb3JtYXQpOnZvaWQKICAgICAgICB7CiAgICAgICAgICAgIHZhciBob2xkZXI6VGV4dExheW91dEZvcm1hdCA9IGluY29taW5nIGFzIFRleHRMYXlvdXRGb3JtYXQ7CiAgICAgICAgICAgIHZhciB2YWw6KjsKCiAgICAgICAgICAgIGlmIChob2xkZXIpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIHZhciBob2xkZXJTdHlsZXM6T2JqZWN0ID0gaG9sZGVyLl9zdHlsZXM7CiAgICAgICAgICAgICAgICBmb3IgKHZhciBrZXk6U3RyaW5nIGluIGhvbGRlclN0eWxlcykKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBDT05GSUc6OmRlYnVnIHsgYXNzZXJ0KGhvbGRlclN0eWxlc1trZXldICE9PSB1bmRlZmluZWQsImJhZCB2YWx1ZSBpbiBhcHBseSIpOyB9CiAgICAgICAgICAgICAgICAgICAgdmFsID0gaG9sZGVyU3R5bGVzW2tleV07CiAgICAgICAgICAgICAgICAgICAgaWYgKHZhbCAhPT0gdW5kZWZpbmVkKQogICAgICAgICAgICAgICAgICAgICAgICBzZXRTdHlsZShrZXksdmFsKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgZm9yIGVhY2ggKHZhciBwcm9wOlByb3BlcnR5IGluIFRleHRMYXlvdXRGb3JtYXQuZGVzY3JpcHRpb24pCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIHZhciBuYW1lOlN0cmluZyA9IHByb3AubmFtZTsKICAgICAgICAgICAgICAgIHZhbCA9IGluY29taW5nW25hbWVdOwogICAgICAgICAgICAgICAgaWYgKHZhbCAhPT0gdW5kZWZpbmVkKQogICAgICAgICAgICAgICAgICAgIHNldFN0eWxlKG5hbWUsdmFsKTsKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgLyoqCiAgICAgICAgICogQ29tcGFyZXMgcHJvcGVydGllcyBpbiBJVGV4dExheW91dEZvcm1hdCBpbnN0YW5jZSA8Y29kZT5wMTwvY29kZT4gd2l0aCBwcm9wZXJ0aWVzIGluIElUZXh0TGF5b3V0Rm9ybWF0IGluc3RhbmNlIDxjb2RlPnAyPC9jb2RlPgogICAgICAgICAqIGFuZCByZXR1cm5zIDxjb2RlPnRydWU8L2NvZGU+IGlmIGFsbCBwcm9wZXJ0aWVzIG1hdGNoLgogICAgICAgICAqIAogICAgICAgICAqIEBwYXJhbSBwMSBpbnN0YW5jZSB0byBjb21wYXJlIHRvIDxjb2RlPnAyPC9jb2RlPi4KICAgICAgICAgKiBAcGFyYW0gcDIgaW5zdGFuY2UgdG8gY29tcGFyZSB0byA8Y29kZT5wMTwvY29kZT4uCiAgICAgICAgICogCiAgICAgICAgICogQHJldHVybiB0cnVlIGlmIGFsbCBwcm9wZXJ0aWVzIG1hdGNoLCBmYWxzZSBvdGhlcndpc2UuCiAgICAgICAgICogCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gRmxhc2ggMTAKICAgICAgICAgKiBAcGxheWVydmVyc2lvbiBBSVIgMS41CiAgICAgICAgICogQGxhbmd2ZXJzaW9uIDMuMAogICAgICAgICAqLwogICAgICAgIHN0YXRpYyBwdWJsaWMgZnVuY3Rpb24gaXNFcXVhbChwMTpJVGV4dExheW91dEZvcm1hdCxwMjpJVGV4dExheW91dEZvcm1hdCk6Qm9vbGVhbgogICAgICAgIHsKICAgICAgICAgICAgaWYgKHAxID09IG51bGwpCiAgICAgICAgICAgICAgICBwMSA9IGVtcHR5VGV4dExheW91dEZvcm1hdDsKICAgICAgICAgICAgaWYgKHAyID09IG51bGwpCiAgICAgICAgICAgICAgICBwMiA9IGVtcHR5VGV4dExheW91dEZvcm1hdDsKICAgICAgICAgICAgaWYgKHAxID09IHAyKQogICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgICAgIHZhciBwMUhvbGRlcjpUZXh0TGF5b3V0Rm9ybWF0ID0gcDEgYXMgVGV4dExheW91dEZvcm1hdDsKICAgICAgICAgICAgdmFyIHAySG9sZGVyOlRleHRMYXlvdXRGb3JtYXQgPSBwMiBhcyBUZXh0TGF5b3V0Rm9ybWF0OwogICAgICAgICAgICBpZiAocDFIb2xkZXIgJiYgcDJIb2xkZXIpCiAgICAgICAgICAgICAgICByZXR1cm4gUHJvcGVydHkuZXF1YWxTdHlsZXMocDFIb2xkZXIuZ2V0U3R5bGVzKCkscDJIb2xkZXIuZ2V0U3R5bGVzKCksVGV4dExheW91dEZvcm1hdC5kZXNjcmlwdGlvbik7CgogICAgICAgICAgICBmb3IgZWFjaCAodmFyIHByb3A6UHJvcGVydHkgaW4gVGV4dExheW91dEZvcm1hdC5kZXNjcmlwdGlvbikKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgaWYgKCFwcm9wLmVxdWFsSGVscGVyKHAxW3Byb3AubmFtZV0scDJbcHJvcC5uYW1lXSkpCiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgICB9CgogICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9CgogICAgICAgIC8qKgogICAgICAgICAqIFNldHMgcHJvcGVydGllcyBpbiB0aGlzIFRleHRMYXlvdXRGb3JtYXQgb2JqZWN0IHRvIDxjb2RlPnVuZGVmaW5lZDwvY29kZT4gaWYgdGhleSBtYXRjaCB0aG9zZSBpbiB0aGUgPGNvZGU+aW5jb21pbmc8L2NvZGU+CiAgICAgICAgICogSVRleHRMYXlvdXRGb3JtYXQgaW5zdGFuY2UuCiAgICAgICAgICogCiAgICAgICAgICogQHBhcmFtIGluY29taW5nIGluc3RhbmNlIGFnYWluc3Qgd2hpY2ggdG8gY29tcGFyZSB0aGlzIFRleHRMYXlvdXRGb3JtYXQgb2JqZWN0J3MgcHJvcGVydHkgdmFsdWVzLgogICAgICAgICAqIAogICAgICAgICAqIEBpbmNsdWRlRXhhbXBsZSBleGFtcGxlc1xUZXh0TGF5b3V0Rm9ybWF0X3JlbW92ZU1hdGNoaW5nRXhhbXBsZS5hcyAtbm9zd2YKICAgICAgICAgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKICAgICAgICAgKiBAbGFuZ3ZlcnNpb24gMy4wCiAgICAgICAgICovCiAgICAgICAgcHVibGljIGZ1bmN0aW9uIHJlbW92ZU1hdGNoaW5nKGluY29taW5nOklUZXh0TGF5b3V0Rm9ybWF0KTp2b2lkCiAgICAgICAgewogICAgICAgICAgICBpZiAoaW5jb21pbmcgPT0gbnVsbCkKICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgCiAgICAgICAgICAgIHZhciBwcm9wOlByb3BlcnR5OwogICAgICAgICAgICB2YXIgaG9sZGVyOlRleHRMYXlvdXRGb3JtYXQgPSBpbmNvbWluZyBhcyBUZXh0TGF5b3V0Rm9ybWF0OwogICAgICAgICAgICBpZiAoaG9sZGVyKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICB2YXIgaG9sZGVyU3R5bGVzOk9iamVjdCA9IGhvbGRlci5fc3R5bGVzOwogICAgICAgICAgICAgICAgZm9yICh2YXIga2V5OlN0cmluZyBpbiBob2xkZXJTdHlsZXMpCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgcHJvcCA9IGRlc2NyaXB0aW9uW2tleV07CiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3ApCiAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcC5lcXVhbEhlbHBlcihfc3R5bGVzW2tleV0saG9sZGVyU3R5bGVzW2tleV0pKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpc1trZXldID0gdW5kZWZpbmVkOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChfc3R5bGVzW2tleV0gPT0gaG9sZGVyU3R5bGVzW2tleV0pCiAgICAgICAgICAgICAgICAgICAgICAgIHNldFN0eWxlKGtleSwgdW5kZWZpbmVkKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfQogICAgICAgICAgICAKICAgICAgICAgICAgLy8gaWdub3JlIHVzZXJTdHlsZXMgCiAgICAgICAgICAgIGZvciBlYWNoIChwcm9wIGluIFRleHRMYXlvdXRGb3JtYXQuZGVzY3JpcHRpb24pCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIGlmIChwcm9wLmVxdWFsSGVscGVyKF9zdHlsZXNbcHJvcC5uYW1lXSxpbmNvbWluZ1twcm9wLm5hbWVdKSkKICAgICAgICAgICAgICAgICAgICB0aGlzW3Byb3AubmFtZV0gPSB1bmRlZmluZWQ7CiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIC8qKgogICAgICAgICAqIFNldHMgcHJvcGVydGllcyBpbiB0aGlzIFRleHRMYXlvdXRGb3JtYXQgb2JqZWN0IHRvIDxjb2RlPnVuZGVmaW5lZDwvY29kZT4gaWYgdGhleSBkbyBub3QgbWF0Y2ggdGhvc2UgaW4gdGhlCiAgICAgICAgICogPGNvZGU+aW5jb21pbmc8L2NvZGU+IElUZXh0TGF5b3V0Rm9ybWF0IGluc3RhbmNlLgogICAgICAgICAqIAogICAgICAgICAqIEBwYXJhbSBpbmNvbWluZyBpbnN0YW5jZSBhZ2FpbnN0IHdoaWNoIHRvIGNvbXBhcmUgdGhpcyBUZXh0TGF5b3V0Rm9ybWF0IG9iamVjdCdzIHByb3BlcnR5IHZhbHVlcy4KICAgICAgICAgKiAKICAgICAgICAgKiBAaW5jbHVkZUV4YW1wbGUgZXhhbXBsZXNcVGV4dExheW91dEZvcm1hdF9yZW1vdmVDbGFzaGluZ0V4YW1wbGUuYXMgLW5vc3dmCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gRmxhc2ggMTAKICAgICAgICAgKiBAcGxheWVydmVyc2lvbiBBSVIgMS41CiAgICAgICAgICogQGxhbmd2ZXJzaW9uIDMuMAogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBmdW5jdGlvbiByZW1vdmVDbGFzaGluZyhpbmNvbWluZzpJVGV4dExheW91dEZvcm1hdCk6dm9pZAogICAgICAgIHsKICAgICAgICAgICAgaWYgKGluY29taW5nID09IG51bGwpCiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgIAogICAgICAgICAgICB2YXIgcHJvcDpQcm9wZXJ0eTsKICAgICAgICAgICAgdmFyIGhvbGRlcjpUZXh0TGF5b3V0Rm9ybWF0ID0gaW5jb21pbmcgYXMgVGV4dExheW91dEZvcm1hdDsKICAgICAgICAgICAgaWYgKGhvbGRlcikKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgdmFyIGhvbGRlclN0eWxlczpPYmplY3QgPSBob2xkZXIuX3N0eWxlczsKICAgICAgICAgICAgICAgIGZvciAodmFyIGtleTpTdHJpbmcgaW4gaG9sZGVyU3R5bGVzKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIENPTkZJRzo6ZGVidWcgeyBhc3NlcnQoaG9sZGVyU3R5bGVzW2tleV0gIT09IHVuZGVmaW5lZCwiYmFkIHZhbHVlIGluIHJlbW92ZUNsYXNoaW5nIik7IH0KICAgICAgICAgICAgICAgICAgICBwcm9wID0gZGVzY3JpcHRpb25ba2V5XTsKICAgICAgICAgICAgICAgICAgICBpZiAocHJvcCkKICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghcHJvcC5lcXVhbEhlbHBlcihfc3R5bGVzW2tleV0saG9sZGVyU3R5bGVzW2tleV0pKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpc1trZXldID0gdW5kZWZpbmVkOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChfc3R5bGVzW2tleV0gIT0gaG9sZGVyU3R5bGVzW2tleV0pCiAgICAgICAgICAgICAgICAgICAgICAgIHNldFN0eWxlKGtleSwgdW5kZWZpbmVkKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfQogICAgICAgICAgICBmb3IgZWFjaCAocHJvcCBpbiBUZXh0TGF5b3V0Rm9ybWF0LmRlc2NyaXB0aW9uKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBpZiAoIXByb3AuZXF1YWxIZWxwZXIoX3N0eWxlc1twcm9wLm5hbWVdLGluY29taW5nW3Byb3AubmFtZV0pKQogICAgICAgICAgICAgICAgICAgIHRoaXNbcHJvcC5uYW1lXSA9IHVuZGVmaW5lZDsKICAgICAgICAgICAgfSAgICAgICAgICAgCiAgICAgICAgfQoKICAgICAgICAvKioKICAgICAgICAgKiBDb2xvciBvZiB0aGUgdGV4dC4gQSBoZXhhZGVjaW1hbCBudW1iZXIgdGhhdCBzcGVjaWZpZXMgdGhyZWUgOC1iaXQgUkdCIChyZWQsIGdyZWVuLCBibHVlKSB2YWx1ZXM7IGZvciBleGFtcGxlLCAweEZGMDAwMCBpcyByZWQgYW5kIDB4MDBGRjAwIGlzIGdyZWVuLiAKICAgICAgICAgKiA8cD5EZWZhdWx0IHZhbHVlIGlzIHVuZGVmaW5lZCBpbmRpY2F0aW5nIG5vdCBzZXQuPC9wPgogICAgICAgICAqIDxwPklmIHVuZGVmaW5lZCBkdXJpbmcgdGhlIGNhc2NhZGUgdGhpcyBwcm9wZXJ0eSB3aWxsIGluaGVyaXQgaXRzIHZhbHVlIGZyb20gYW4gYW5jZXN0b3IuIElmIG5vIGFuY2VzdG9yIGhhcyBzZXQgdGhpcyBwcm9wZXJ0eSwgaXQgd2lsbCBoYXZlIGEgdmFsdWUgb2YgMC48L3A+CiAgICAgICAgICogCiAgICAgICAgICogQHRocm93cyBSYW5nZUVycm9yIHdoZW4gc2V0IHZhbHVlIGlzIG5vdCB3aXRoaW4gcmFuZ2UgZm9yIHRoaXMgcHJvcGVydHkKICAgICAgICAgKiAKICAgICAgICAgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKICAgICAgICAgKiBAbGFuZ3ZlcnNpb24gMy4wCiAgICAgICAgICovCiAgICAgICAgcHVibGljIGZ1bmN0aW9uIGdldCBjb2xvcigpOioKICAgICAgICB7IHJldHVybiBfc3R5bGVzLmNvbG9yOyB9CiAgICAgICAgcHVibGljIGZ1bmN0aW9uIHNldCBjb2xvcih2YWx1ZToqKTp2b2lkCiAgICAgICAgeyBzZXRTdHlsZUJ5UHJvcGVydHkoVGV4dExheW91dEZvcm1hdC5jb2xvclByb3BlcnR5LHZhbHVlKTsgfQoKICAgICAgICAvKioKICAgICAgICAgKiBCYWNrZ3JvdW5kIGNvbG9yIG9mIHRoZSB0ZXh0IChhZG9wdHMgZGVmYXVsdCB2YWx1ZSBpZiB1bmRlZmluZWQgZHVyaW5nIGNhc2NhZGUpLiBDYW4gYmUgZWl0aGVyIHRoZSBjb25zdGFudCB2YWx1ZSAgPGNvZGU+QmFja2dyb3VuZENvbG9yLlRSQU5TUEFSRU5UPC9jb2RlPiwgb3IgYSBoZXhhZGVjaW1hbCB2YWx1ZSB0aGF0IHNwZWNpZmllcyB0aGUgdGhyZWUgOC1iaXQgUkdCIChyZWQsIGdyZWVuLCBibHVlKSB2YWx1ZXM7IGZvciBleGFtcGxlLCAweEZGMDAwMCBpcyByZWQgYW5kIDB4MDBGRjAwIGlzIGdyZWVuLgogICAgICAgICAqIDxwPkxlZ2FsIHZhbHVlcyBhcyBhIHN0cmluZyBhcmUgQmFja2dyb3VuZENvbG9yLlRSQU5TUEFSRU5ULCBGb3JtYXRWYWx1ZS5JTkhFUklUIGFuZCB1aW50cyBmcm9tIDB4MCB0byAweGZmZmZmZmZmLjwvcD4KICAgICAgICAgKiA8cD5EZWZhdWx0IHZhbHVlIGlzIHVuZGVmaW5lZCBpbmRpY2F0aW5nIG5vdCBzZXQuPC9wPgogICAgICAgICAqIDxwPklmIHVuZGVmaW5lZCBkdXJpbmcgdGhlIGNhc2NhZGUgdGhpcyBwcm9wZXJ0eSB3aWxsIGhhdmUgYSB2YWx1ZSBvZiBCYWNrZ3JvdW5kQ29sb3IuVFJBTlNQQVJFTlQuPC9wPgogICAgICAgICAqIAogICAgICAgICAqIEB0aHJvd3MgUmFuZ2VFcnJvciB3aGVuIHNldCB2YWx1ZSBpcyBub3Qgd2l0aGluIHJhbmdlIGZvciB0aGlzIHByb3BlcnR5CiAgICAgICAgICogCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gRmxhc2ggMTAKICAgICAgICAgKiBAcGxheWVydmVyc2lvbiBBSVIgMS41CiAgICAgICAgICogQGxhbmd2ZXJzaW9uIDMuMAogICAgICAgICAqIEBzZWUgZmxhc2h4LnRleHRMYXlvdXQuZm9ybWF0cy5CYWNrZ3JvdW5kQ29sb3IKICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgZnVuY3Rpb24gZ2V0IGJhY2tncm91bmRDb2xvcigpOioKICAgICAgICB7IHJldHVybiBfc3R5bGVzLmJhY2tncm91bmRDb2xvcjsgfQogICAgICAgIHB1YmxpYyBmdW5jdGlvbiBzZXQgYmFja2dyb3VuZENvbG9yKHZhbHVlOiopOnZvaWQKICAgICAgICB7IHNldFN0eWxlQnlQcm9wZXJ0eShUZXh0TGF5b3V0Rm9ybWF0LmJhY2tncm91bmRDb2xvclByb3BlcnR5LHZhbHVlKTsgfQoKICAgICAgICBbSW5zcGVjdGFibGUoZW51bWVyYXRpb249InRydWUsZmFsc2UsaW5oZXJpdCIpXQogICAgICAgIC8qKgogICAgICAgICAqIElmIDxjb2RlPnRydWU8L2NvZGU+LCBhcHBsaWVzIHN0cmlrZXRocm91Z2gsIGEgbGluZSBkcmF3biB0aHJvdWdoIHRoZSBtaWRkbGUgb2YgdGhlIHRleHQuCiAgICAgICAgICogPHA+TGVnYWwgdmFsdWVzIGFyZSB0cnVlLCBmYWxzZSBhbmQgRm9ybWF0VmFsdWUuSU5IRVJJVC48L3A+CiAgICAgICAgICogPHA+RGVmYXVsdCB2YWx1ZSBpcyB1bmRlZmluZWQgaW5kaWNhdGluZyBub3Qgc2V0LjwvcD4KICAgICAgICAgKiA8cD5JZiB1bmRlZmluZWQgZHVyaW5nIHRoZSBjYXNjYWRlIHRoaXMgcHJvcGVydHkgd2lsbCBpbmhlcml0IGl0cyB2YWx1ZSBmcm9tIGFuIGFuY2VzdG9yLiBJZiBubyBhbmNlc3RvciBoYXMgc2V0IHRoaXMgcHJvcGVydHksIGl0IHdpbGwgaGF2ZSBhIHZhbHVlIG9mIGZhbHNlLjwvcD4KICAgICAgICAgKiAKICAgICAgICAgKiBAdGhyb3dzIFJhbmdlRXJyb3Igd2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eQogICAgICAgICAqIAogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQogICAgICAgICAqIEBsYW5ndmVyc2lvbiAzLjAKICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgZnVuY3Rpb24gZ2V0IGxpbmVUaHJvdWdoKCk6KgogICAgICAgIHsgcmV0dXJuIF9zdHlsZXMubGluZVRocm91Z2g7IH0KICAgICAgICBwdWJsaWMgZnVuY3Rpb24gc2V0IGxpbmVUaHJvdWdoKHZhbHVlOiopOnZvaWQKICAgICAgICB7IHNldFN0eWxlQnlQcm9wZXJ0eShUZXh0TGF5b3V0Rm9ybWF0LmxpbmVUaHJvdWdoUHJvcGVydHksdmFsdWUpOyB9CgogICAgICAgIC8qKgogICAgICAgICAqIEFscGhhICh0cmFuc3BhcmVuY3kpIHZhbHVlIGZvciB0aGUgdGV4dC4gQSB2YWx1ZSBvZiAwIGlzIGZ1bGx5IHRyYW5zcGFyZW50LCBhbmQgYSB2YWx1ZSBvZiAxIGlzIGZ1bGx5IG9wYXF1ZS4gRGlzcGxheSBvYmplY3RzIHdpdGggPGNvZGU+dGV4dEFscGhhPC9jb2RlPiBzZXQgdG8gMCBhcmUgYWN0aXZlLCBldmVuIHRob3VnaCB0aGV5IGFyZSBpbnZpc2libGUuCiAgICAgICAgICogPHA+TGVnYWwgdmFsdWVzIGFyZSBudW1iZXJzIGZyb20gMCB0byAxIGFuZCBGb3JtYXRWYWx1ZS5JTkhFUklULjwvcD4KICAgICAgICAgKiA8cD5EZWZhdWx0IHZhbHVlIGlzIHVuZGVmaW5lZCBpbmRpY2F0aW5nIG5vdCBzZXQuPC9wPgogICAgICAgICAqIDxwPklmIHVuZGVmaW5lZCBkdXJpbmcgdGhlIGNhc2NhZGUgdGhpcyBwcm9wZXJ0eSB3aWxsIGluaGVyaXQgaXRzIHZhbHVlIGZyb20gYW4gYW5jZXN0b3IuIElmIG5vIGFuY2VzdG9yIGhhcyBzZXQgdGhpcyBwcm9wZXJ0eSwgaXQgd2lsbCBoYXZlIGEgdmFsdWUgb2YgMS48L3A+CiAgICAgICAgICogCiAgICAgICAgICogQHRocm93cyBSYW5nZUVycm9yIHdoZW4gc2V0IHZhbHVlIGlzIG5vdCB3aXRoaW4gcmFuZ2UgZm9yIHRoaXMgcHJvcGVydHkKICAgICAgICAgKiAKICAgICAgICAgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKICAgICAgICAgKiBAbGFuZ3ZlcnNpb24gMy4wCiAgICAgICAgICovCiAgICAgICAgcHVibGljIGZ1bmN0aW9uIGdldCB0ZXh0QWxwaGEoKToqCiAgICAgICAgeyByZXR1cm4gX3N0eWxlcy50ZXh0QWxwaGE7IH0KICAgICAgICBwdWJsaWMgZnVuY3Rpb24gc2V0IHRleHRBbHBoYSh2YWx1ZToqKTp2b2lkCiAgICAgICAgeyBzZXRTdHlsZUJ5UHJvcGVydHkoVGV4dExheW91dEZvcm1hdC50ZXh0QWxwaGFQcm9wZXJ0eSx2YWx1ZSk7IH0KCiAgICAgICAgLyoqCiAgICAgICAgICogQWxwaGEgKHRyYW5zcGFyZW5jeSkgdmFsdWUgZm9yIHRoZSBiYWNrZ3JvdW5kIChhZG9wdHMgZGVmYXVsdCB2YWx1ZSBpZiB1bmRlZmluZWQgZHVyaW5nIGNhc2NhZGUpLiBBIHZhbHVlIG9mIDAgaXMgZnVsbHkgdHJhbnNwYXJlbnQsIGFuZCBhIHZhbHVlIG9mIDEgaXMgZnVsbHkgb3BhcXVlLiBEaXNwbGF5IG9iamVjdHMgd2l0aCBhbHBoYSBzZXQgdG8gMCBhcmUgYWN0aXZlLCBldmVuIHRob3VnaCB0aGV5IGFyZSBpbnZpc2libGUuCiAgICAgICAgICogPHA+TGVnYWwgdmFsdWVzIGFyZSBudW1iZXJzIGZyb20gMCB0byAxIGFuZCBGb3JtYXRWYWx1ZS5JTkhFUklULjwvcD4KICAgICAgICAgKiA8cD5EZWZhdWx0IHZhbHVlIGlzIHVuZGVmaW5lZCBpbmRpY2F0aW5nIG5vdCBzZXQuPC9wPgogICAgICAgICAqIDxwPklmIHVuZGVmaW5lZCBkdXJpbmcgdGhlIGNhc2NhZGUgdGhpcyBwcm9wZXJ0eSB3aWxsIGhhdmUgYSB2YWx1ZSBvZiAxLjwvcD4KICAgICAgICAgKiAKICAgICAgICAgKiBAdGhyb3dzIFJhbmdlRXJyb3Igd2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eQogICAgICAgICAqIAogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQogICAgICAgICAqIEBsYW5ndmVyc2lvbiAzLjAKICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgZnVuY3Rpb24gZ2V0IGJhY2tncm91bmRBbHBoYSgpOioKICAgICAgICB7IHJldHVybiBfc3R5bGVzLmJhY2tncm91bmRBbHBoYTsgfQogICAgICAgIHB1YmxpYyBmdW5jdGlvbiBzZXQgYmFja2dyb3VuZEFscGhhKHZhbHVlOiopOnZvaWQKICAgICAgICB7IHNldFN0eWxlQnlQcm9wZXJ0eShUZXh0TGF5b3V0Rm9ybWF0LmJhY2tncm91bmRBbHBoYVByb3BlcnR5LHZhbHVlKTsgfQoKICAgICAgICAvKioKICAgICAgICAgKiBUaGUgc2l6ZSBvZiB0aGUgdGV4dCBpbiBwaXhlbHMuCiAgICAgICAgICogPHA+TGVnYWwgdmFsdWVzIGFyZSBudW1iZXJzIGZyb20gMSB0byA3MjAgYW5kIEZvcm1hdFZhbHVlLklOSEVSSVQuPC9wPgogICAgICAgICAqIDxwPkRlZmF1bHQgdmFsdWUgaXMgdW5kZWZpbmVkIGluZGljYXRpbmcgbm90IHNldC48L3A+CiAgICAgICAgICogPHA+SWYgdW5kZWZpbmVkIGR1cmluZyB0aGUgY2FzY2FkZSB0aGlzIHByb3BlcnR5IHdpbGwgaW5oZXJpdCBpdHMgdmFsdWUgZnJvbSBhbiBhbmNlc3Rvci4gSWYgbm8gYW5jZXN0b3IgaGFzIHNldCB0aGlzIHByb3BlcnR5LCBpdCB3aWxsIGhhdmUgYSB2YWx1ZSBvZiAxMi48L3A+CiAgICAgICAgICogCiAgICAgICAgICogQHRocm93cyBSYW5nZUVycm9yIHdoZW4gc2V0IHZhbHVlIGlzIG5vdCB3aXRoaW4gcmFuZ2UgZm9yIHRoaXMgcHJvcGVydHkKICAgICAgICAgKiAKICAgICAgICAgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKICAgICAgICAgKiBAbGFuZ3ZlcnNpb24gMy4wCiAgICAgICAgICovCiAgICAgICAgcHVibGljIGZ1bmN0aW9uIGdldCBmb250U2l6ZSgpOioKICAgICAgICB7IHJldHVybiBfc3R5bGVzLmZvbnRTaXplOyB9CiAgICAgICAgcHVibGljIGZ1bmN0aW9uIHNldCBmb250U2l6ZSh2YWx1ZToqKTp2b2lkCiAgICAgICAgeyBzZXRTdHlsZUJ5UHJvcGVydHkoVGV4dExheW91dEZvcm1hdC5mb250U2l6ZVByb3BlcnR5LHZhbHVlKTsgfQoKICAgICAgICAvKioKICAgICAgICAgKiBBbW91bnQgdG8gc2hpZnQgdGhlIGJhc2VsaW5lIGZyb20gdGhlIDxjb2RlPmRvbWluYW50QmFzZWxpbmU8L2NvZGU+IHZhbHVlLiBVbml0cyBhcmUgaW4gcGl4ZWxzLCBvciBhIHBlcmNlbnRhZ2Ugb2YgPGNvZGU+Zm9udFNpemU8L2NvZGU+IChpbiB3aGljaCBjYXNlLCBlbnRlciBhIHN0cmluZyB2YWx1ZSwgbGlrZSAxNDAlKS4gIFBvc2l0aXZlIHZhbHVlcyBzaGlmdCB0aGUgbGluZSB1cCBmb3IgaG9yaXpvbnRhbCB0ZXh0IChyaWdodCBmb3IgdmVydGljYWwpIGFuZCBuZWdhdGl2ZSB2YWx1ZXMgc2hpZnQgaXQgZG93biBmb3IgaG9yaXpvbnRhbCAobGVmdCBmb3IgdmVydGljYWwpLiAKICAgICAgICAgKiA8cD5MZWdhbCB2YWx1ZXMgYXJlIEJhc2VsaW5lU2hpZnQuU1VQRVJTQ1JJUFQsIEJhc2VsaW5lU2hpZnQuU1VCU0NSSVBULCBGb3JtYXRWYWx1ZS5JTkhFUklULjwvcD4KICAgICAgICAgKiA8cD5MZWdhbCB2YWx1ZXMgYXMgYSBudW1iZXIgYXJlIGZyb20gLTEwMDAgdG8gMTAwMC48L3A+CiAgICAgICAgICogPHA+TGVnYWwgdmFsdWVzIGFzIGEgcGVyY2VudCBhcmUgbnVtYmVycyBmcm9tIC0xMDAwIHRvIDEwMDAuPC9wPgogICAgICAgICAqIDxwPkRlZmF1bHQgdmFsdWUgaXMgdW5kZWZpbmVkIGluZGljYXRpbmcgbm90IHNldC48L3A+CiAgICAgICAgICogPHA+SWYgdW5kZWZpbmVkIGR1cmluZyB0aGUgY2FzY2FkZSB0aGlzIHByb3BlcnR5IHdpbGwgaW5oZXJpdCBpdHMgdmFsdWUgZnJvbSBhbiBhbmNlc3Rvci4gSWYgbm8gYW5jZXN0b3IgaGFzIHNldCB0aGlzIHByb3BlcnR5LCBpdCB3aWxsIGhhdmUgYSB2YWx1ZSBvZiAwLjAuPC9wPgogICAgICAgICAqIAogICAgICAgICAqIEB0aHJvd3MgUmFuZ2VFcnJvciB3aGVuIHNldCB2YWx1ZSBpcyBub3Qgd2l0aGluIHJhbmdlIGZvciB0aGlzIHByb3BlcnR5CiAgICAgICAgICogCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gRmxhc2ggMTAKICAgICAgICAgKiBAcGxheWVydmVyc2lvbiBBSVIgMS41CiAgICAgICAgICogQGxhbmd2ZXJzaW9uIDMuMAogICAgICAgICAqIEBzZWUgZmxhc2h4LnRleHRMYXlvdXQuZm9ybWF0cy5CYXNlbGluZVNoaWZ0CiAgICAgICAgICovCiAgICAgICAgcHVibGljIGZ1bmN0aW9uIGdldCBiYXNlbGluZVNoaWZ0KCk6KgogICAgICAgIHsgcmV0dXJuIF9zdHlsZXMuYmFzZWxpbmVTaGlmdDsgfQogICAgICAgIHB1YmxpYyBmdW5jdGlvbiBzZXQgYmFzZWxpbmVTaGlmdCh2YWx1ZToqKTp2b2lkCiAgICAgICAgeyBzZXRTdHlsZUJ5UHJvcGVydHkoVGV4dExheW91dEZvcm1hdC5iYXNlbGluZVNoaWZ0UHJvcGVydHksdmFsdWUpOyB9CgogICAgICAgIC8qKgogICAgICAgICAqIE51bWJlciBpbiBwaXhlbHMgKG9yIHBlcmNlbnQgb2YgPGNvZGU+Zm9udFNpemU8L2NvZGU+LCBsaWtlIDEyMCUpIGluZGljYXRpbmcgdGhlIGFtb3VudCBvZiB0cmFja2luZyAobWFudWFsIGtlcm5pbmcpIHRvIGJlIGFwcGxpZWQgdG8gdGhlIGxlZnQgb2YgZWFjaCBjaGFyYWN0ZXIuIElmIGtlcm5pbmcgaXMgZW5hYmxlZCwgdGhlIDxjb2RlPnRyYWNraW5nTGVmdDwvY29kZT4gdmFsdWUgaXMgYWRkZWQgdG8gdGhlIHZhbHVlcyBpbiB0aGUga2VybmluZyB0YWJsZSBmb3IgdGhlIGZvbnQuIElmIGtlcm5pbmcgaXMgZGlzYWJsZWQsIHRoZSA8Y29kZT50cmFja2luZ0xlZnQ8L2NvZGU+IHZhbHVlIGlzIHVzZWQgYXMgYSBtYW51YWwga2VybmluZyB2YWx1ZS4gU3VwcG9ydHMgYm90aCBwb3NpdGl2ZSBhbmQgbmVnYXRpdmUgdmFsdWVzLiAKICAgICAgICAgKiA8cD5MZWdhbCB2YWx1ZXMgYXMgYSBudW1iZXIgYXJlIGZyb20gLTEwMDAgdG8gMTAwMC48L3A+CiAgICAgICAgICogPHA+TGVnYWwgdmFsdWVzIGFzIGEgcGVyY2VudCBhcmUgbnVtYmVycyBmcm9tIC0xMDAwJSB0byAxMDAwJS48L3A+CiAgICAgICAgICogPHA+TGVnYWwgdmFsdWVzIGluY2x1ZGUgRm9ybWF0VmFsdWUuSU5IRVJJVC48L3A+CiAgICAgICAgICogPHA+RGVmYXVsdCB2YWx1ZSBpcyB1bmRlZmluZWQgaW5kaWNhdGluZyBub3Qgc2V0LjwvcD4KICAgICAgICAgKiA8cD5JZiB1bmRlZmluZWQgZHVyaW5nIHRoZSBjYXNjYWRlIHRoaXMgcHJvcGVydHkgd2lsbCBpbmhlcml0IGl0cyB2YWx1ZSBmcm9tIGFuIGFuY2VzdG9yLiBJZiBubyBhbmNlc3RvciBoYXMgc2V0IHRoaXMgcHJvcGVydHksIGl0IHdpbGwgaGF2ZSBhIHZhbHVlIG9mIDAuPC9wPgogICAgICAgICAqIAogICAgICAgICAqIEB0aHJvd3MgUmFuZ2VFcnJvciB3aGVuIHNldCB2YWx1ZSBpcyBub3Qgd2l0aGluIHJhbmdlIGZvciB0aGlzIHByb3BlcnR5CiAgICAgICAgICogCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gRmxhc2ggMTAKICAgICAgICAgKiBAcGxheWVydmVyc2lvbiBBSVIgMS41CiAgICAgICAgICogQGxhbmd2ZXJzaW9uIDMuMAogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBmdW5jdGlvbiBnZXQgdHJhY2tpbmdMZWZ0KCk6KgogICAgICAgIHsgcmV0dXJuIF9zdHlsZXMudHJhY2tpbmdMZWZ0OyB9CiAgICAgICAgcHVibGljIGZ1bmN0aW9uIHNldCB0cmFja2luZ0xlZnQodmFsdWU6Kik6dm9pZAogICAgICAgIHsgc2V0U3R5bGVCeVByb3BlcnR5KFRleHRMYXlvdXRGb3JtYXQudHJhY2tpbmdMZWZ0UHJvcGVydHksdmFsdWUpOyB9CgogICAgICAgIC8qKgogICAgICAgICAqIE51bWJlciBpbiBwaXhlbHMgKG9yIHBlcmNlbnQgb2YgPGNvZGU+Zm9udFNpemU8L2NvZGU+LCBsaWtlIDEyMCUpIGluZGljYXRpbmcgdGhlIGFtb3VudCBvZiB0cmFja2luZyAobWFudWFsIGtlcm5pbmcpIHRvIGJlIGFwcGxpZWQgdG8gdGhlIHJpZ2h0IG9mIGVhY2ggY2hhcmFjdGVyLiAgSWYga2VybmluZyBpcyBlbmFibGVkLCB0aGUgPGNvZGU+dHJhY2tpbmdSaWdodDwvY29kZT4gdmFsdWUgaXMgYWRkZWQgdG8gdGhlIHZhbHVlcyBpbiB0aGUga2VybmluZyB0YWJsZSBmb3IgdGhlIGZvbnQuIElmIGtlcm5pbmcgaXMgZGlzYWJsZWQsIHRoZSA8Y29kZT50cmFja2luZ1JpZ2h0PC9jb2RlPiB2YWx1ZSBpcyB1c2VkIGFzIGEgbWFudWFsIGtlcm5pbmcgdmFsdWUuIFN1cHBvcnRzIGJvdGggcG9zaXRpdmUgYW5kIG5lZ2F0aXZlIHZhbHVlcy4gCiAgICAgICAgICogPHA+TGVnYWwgdmFsdWVzIGFzIGEgbnVtYmVyIGFyZSBmcm9tIC0xMDAwIHRvIDEwMDAuPC9wPgogICAgICAgICAqIDxwPkxlZ2FsIHZhbHVlcyBhcyBhIHBlcmNlbnQgYXJlIG51bWJlcnMgZnJvbSAtMTAwMCUgdG8gMTAwMCUuPC9wPgogICAgICAgICAqIDxwPkxlZ2FsIHZhbHVlcyBpbmNsdWRlIEZvcm1hdFZhbHVlLklOSEVSSVQuPC9wPgogICAgICAgICAqIDxwPkRlZmF1bHQgdmFsdWUgaXMgdW5kZWZpbmVkIGluZGljYXRpbmcgbm90IHNldC48L3A+CiAgICAgICAgICogPHA+SWYgdW5kZWZpbmVkIGR1cmluZyB0aGUgY2FzY2FkZSB0aGlzIHByb3BlcnR5IHdpbGwgaW5oZXJpdCBpdHMgdmFsdWUgZnJvbSBhbiBhbmNlc3Rvci4gSWYgbm8gYW5jZXN0b3IgaGFzIHNldCB0aGlzIHByb3BlcnR5LCBpdCB3aWxsIGhhdmUgYSB2YWx1ZSBvZiAwLjwvcD4KICAgICAgICAgKiAKICAgICAgICAgKiBAdGhyb3dzIFJhbmdlRXJyb3Igd2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eQogICAgICAgICAqIAogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQogICAgICAgICAqIEBsYW5ndmVyc2lvbiAzLjAKICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgZnVuY3Rpb24gZ2V0IHRyYWNraW5nUmlnaHQoKToqCiAgICAgICAgeyByZXR1cm4gX3N0eWxlcy50cmFja2luZ1JpZ2h0OyB9CiAgICAgICAgcHVibGljIGZ1bmN0aW9uIHNldCB0cmFja2luZ1JpZ2h0KHZhbHVlOiopOnZvaWQKICAgICAgICB7IHNldFN0eWxlQnlQcm9wZXJ0eShUZXh0TGF5b3V0Rm9ybWF0LnRyYWNraW5nUmlnaHRQcm9wZXJ0eSx2YWx1ZSk7IH0KCiAgICAgICAgLyoqCiAgICAgICAgICogTGVhZGluZyBjb250cm9scyBmb3IgdGhlIHRleHQuIFRoZSBkaXN0YW5jZSBmcm9tIHRoZSBiYXNlbGluZSBvZiB0aGUgcHJldmlvdXMgb3IgdGhlIG5leHQgbGluZSAoYmFzZWQgb24gPGNvZGU+TGVhZGluZ01vZGVsPC9jb2RlPikgdG8gdGhlIGJhc2VsaW5lIG9mIHRoZSBjdXJyZW50IGxpbmUgaXMgZXF1YWwgdG8gdGhlIG1heGltdW0gYW1vdW50IG9mIHRoZSBsZWFkaW5nIGFwcGxpZWQgdG8gYW55IGNoYXJhY3RlciBpbiB0aGUgbGluZS4gVGhpcyBpcyBlaXRoZXIgYSBudW1iZXIgb3IgYSBwZXJjZW50LiAgSWYgc3BlY2lmeWluZyBhIHBlcmNlbnQsIGVudGVyIGEgc3RyaW5nIHZhbHVlLCBsaWtlIDE0MCUuPHA+PGltZyBzcmM9Jy4uLy4uLy4uL2ltYWdlcy90ZXh0TGF5b3V0X2xpbmVIZWlnaHQxLmpwZycgYWx0PSdsaW5lSGVpZ2h0MScgLz48aW1nIHNyYz0nLi4vLi4vLi4vaW1hZ2VzL3RleHRMYXlvdXRfbGluZUhlaWdodDIuanBnJyBhbHQ9J2xpbmVIZWlnaHQyJyAvPjwvcD4KICAgICAgICAgKiA8cD5MZWdhbCB2YWx1ZXMgYXMgYSBudW1iZXIgYXJlIGZyb20gLTcyMCB0byA3MjAuPC9wPgogICAgICAgICAqIDxwPkxlZ2FsIHZhbHVlcyBhcyBhIHBlcmNlbnQgYXJlIG51bWJlcnMgZnJvbSAtMTAwMCUgdG8gMTAwMCUuPC9wPgogICAgICAgICAqIDxwPkxlZ2FsIHZhbHVlcyBpbmNsdWRlIEZvcm1hdFZhbHVlLklOSEVSSVQuPC9wPgogICAgICAgICAqIDxwPkRlZmF1bHQgdmFsdWUgaXMgdW5kZWZpbmVkIGluZGljYXRpbmcgbm90IHNldC48L3A+CiAgICAgICAgICogPHA+SWYgdW5kZWZpbmVkIGR1cmluZyB0aGUgY2FzY2FkZSB0aGlzIHByb3BlcnR5IHdpbGwgaW5oZXJpdCBpdHMgdmFsdWUgZnJvbSBhbiBhbmNlc3Rvci4gSWYgbm8gYW5jZXN0b3IgaGFzIHNldCB0aGlzIHByb3BlcnR5LCBpdCB3aWxsIGhhdmUgYSB2YWx1ZSBvZiAxMjAlLjwvcD4KICAgICAgICAgKiAKICAgICAgICAgKiBAdGhyb3dzIFJhbmdlRXJyb3Igd2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eQogICAgICAgICAqIAogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQogICAgICAgICAqIEBsYW5ndmVyc2lvbiAzLjAKICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgZnVuY3Rpb24gZ2V0IGxpbmVIZWlnaHQoKToqCiAgICAgICAgeyByZXR1cm4gX3N0eWxlcy5saW5lSGVpZ2h0OyB9CiAgICAgICAgcHVibGljIGZ1bmN0aW9uIHNldCBsaW5lSGVpZ2h0KHZhbHVlOiopOnZvaWQKICAgICAgICB7IHNldFN0eWxlQnlQcm9wZXJ0eShUZXh0TGF5b3V0Rm9ybWF0LmxpbmVIZWlnaHRQcm9wZXJ0eSx2YWx1ZSk7IH0KCiAgICAgICAgW0luc3BlY3RhYmxlKGVudW1lcmF0aW9uPSJhbGwsYW55LGF1dG8sbm9uZSxpbmhlcml0IildCiAgICAgICAgLyoqCiAgICAgICAgICogQ29udHJvbHMgd2hlcmUgbGluZXMgYXJlIGFsbG93ZWQgdG8gYnJlYWsgd2hlbiBicmVha2luZyB3cmFwcGluZyB0ZXh0IGludG8gbXVsdGlwbGUgbGluZXMuIFNldCB0byA8Y29kZT5CcmVha09wcG9ydHVuaXR5LkFVVE88L2NvZGU+IHRvIGJyZWFrIHRleHQgbm9ybWFsbHkuIFNldCB0byA8Y29kZT5CcmVha09wcG9ydHVuaXR5Lk5PTkU8L2NvZGU+IHRvIDxlbT5ub3Q8L2VtPiBicmVhayB0aGUgdGV4dCB1bmxlc3MgdGhlIHRleHQgd291bGQgb3ZlcnJ1biB0aGUgbWVhc3VyZSBhbmQgdGhlcmUgYXJlIG5vIG90aGVyIHBsYWNlcyB0byBicmVhayB0aGUgbGluZS4gU2V0IHRvIDxjb2RlPkJyZWFrT3Bwb3J0dW5pdHkuQU5ZPC9jb2RlPiB0byBhbGxvdyB0aGUgbGluZSB0byBicmVhayBhbnl3aGVyZSwgcmF0aGVyIHRoYW4ganVzdCBiZXR3ZWVuIHdvcmRzLiBTZXQgdG8gPGNvZGU+QnJlYWtPcHBvcnR1bml0eS5BTEw8L2NvZGU+IHRvIGhhdmUgZWFjaCB0eXBvZ3JhcGhpYyBjbHVzdGVyIHB1dCBvbiBhIHNlcGFyYXRlIGxpbmUgKHVzZWZ1bCBmb3IgdGV4dCBvbiBhIHBhdGgpLgogICAgICAgICAqIDxwPkxlZ2FsIHZhbHVlcyBhcmUgQnJlYWtPcHBvcnR1bml0eS5BTEwsIEJyZWFrT3Bwb3J0dW5pdHkuQU5ZLCBCcmVha09wcG9ydHVuaXR5LkFVVE8sIEJyZWFrT3Bwb3J0dW5pdHkuTk9ORSwgRm9ybWF0VmFsdWUuSU5IRVJJVC48L3A+CiAgICAgICAgICogPHA+RGVmYXVsdCB2YWx1ZSBpcyB1bmRlZmluZWQgaW5kaWNhdGluZyBub3Qgc2V0LjwvcD4KICAgICAgICAgKiA8cD5JZiB1bmRlZmluZWQgZHVyaW5nIHRoZSBjYXNjYWRlIHRoaXMgcHJvcGVydHkgd2lsbCBpbmhlcml0IGl0cyB2YWx1ZSBmcm9tIGFuIGFuY2VzdG9yLiBJZiBubyBhbmNlc3RvciBoYXMgc2V0IHRoaXMgcHJvcGVydHksIGl0IHdpbGwgaGF2ZSBhIHZhbHVlIG9mIEJyZWFrT3Bwb3J0dW5pdHkuQVVUTy48L3A+CiAgICAgICAgICogCiAgICAgICAgICogQHRocm93cyBSYW5nZUVycm9yIHdoZW4gc2V0IHZhbHVlIGlzIG5vdCB3aXRoaW4gcmFuZ2UgZm9yIHRoaXMgcHJvcGVydHkKICAgICAgICAgKiAKICAgICAgICAgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKICAgICAgICAgKiBAbGFuZ3ZlcnNpb24gMy4wCiAgICAgICAgICogQHNlZSBmbGFzaC50ZXh0LmVuZ2luZS5CcmVha09wcG9ydHVuaXR5CiAgICAgICAgICovCiAgICAgICAgcHVibGljIGZ1bmN0aW9uIGdldCBicmVha09wcG9ydHVuaXR5KCk6KgogICAgICAgIHsgcmV0dXJuIF9zdHlsZXMuYnJlYWtPcHBvcnR1bml0eTsgfQogICAgICAgIHB1YmxpYyBmdW5jdGlvbiBzZXQgYnJlYWtPcHBvcnR1bml0eSh2YWx1ZToqKTp2b2lkCiAgICAgICAgeyBzZXRTdHlsZUJ5UHJvcGVydHkoVGV4dExheW91dEZvcm1hdC5icmVha09wcG9ydHVuaXR5UHJvcGVydHksdmFsdWUpOyB9CgogICAgICAgIFtJbnNwZWN0YWJsZShlbnVtZXJhdGlvbj0iZGVmYXVsdCxsaW5pbmcsb2xkU3R5bGUsaW5oZXJpdCIpXQogICAgICAgIC8qKgogICAgICAgICAqIFRoZSB0eXBlIG9mIGRpZ2l0IGNhc2UgdXNlZCBmb3IgdGhpcyB0ZXh0LiBTZXR0aW5nIHRoZSB2YWx1ZSB0byA8Y29kZT5EaWdpdENhc2UuT0xEX1NUWUxFPC9jb2RlPiBhcHByb3hpbWF0ZXMgbG93ZXJjYXNlIGxldHRlcmZvcm1zIHdpdGggdmFyeWluZyBhc2NlbmRlcnMgYW5kIGRlc2NlbmRlcnMuIFRoZSBmaWd1cmVzIGFyZSBwcm9wb3J0aW9uYWxseSBzcGFjZWQuIFRoaXMgc3R5bGUgaXMgb25seSBhdmFpbGFibGUgaW4gc2VsZWN0ZWQgdHlwZWZhY2VzLCBtb3N0IGNvbW1vbmx5IGluIGEgc3VwcGxlbWVudGFsIG9yIGV4cGVydCBmb250LiBUaGUgPGNvZGU+RGlnaXRDYXNlLkxJTklORzwvY29kZT4gc2V0dGluZyBoYXMgYWxsLWNhcCBoZWlnaHQgYW5kIGlzIHR5cGljYWxseSBtb25vc3BhY2VkIHRvIGxpbmUgdXAgaW4gY2hhcnRzLjxwPjxpbWcgc3JjPScuLi8uLi8uLi9pbWFnZXMvdGV4dExheW91dF9kaWdpdGNhc2UuZ2lmJyBhbHQ9J2RpZ2l0Q2FzZScgLz48L3A+CiAgICAgICAgICogPHA+TGVnYWwgdmFsdWVzIGFyZSBEaWdpdENhc2UuREVGQVVMVCwgRGlnaXRDYXNlLkxJTklORywgRGlnaXRDYXNlLk9MRF9TVFlMRSwgRm9ybWF0VmFsdWUuSU5IRVJJVC48L3A+CiAgICAgICAgICogPHA+RGVmYXVsdCB2YWx1ZSBpcyB1bmRlZmluZWQgaW5kaWNhdGluZyBub3Qgc2V0LjwvcD4KICAgICAgICAgKiA8cD5JZiB1bmRlZmluZWQgZHVyaW5nIHRoZSBjYXNjYWRlIHRoaXMgcHJvcGVydHkgd2lsbCBpbmhlcml0IGl0cyB2YWx1ZSBmcm9tIGFuIGFuY2VzdG9yLiBJZiBubyBhbmNlc3RvciBoYXMgc2V0IHRoaXMgcHJvcGVydHksIGl0IHdpbGwgaGF2ZSBhIHZhbHVlIG9mIERpZ2l0Q2FzZS5ERUZBVUxULjwvcD4KICAgICAgICAgKiAKICAgICAgICAgKiBAdGhyb3dzIFJhbmdlRXJyb3Igd2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eQogICAgICAgICAqIAogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQogICAgICAgICAqIEBsYW5ndmVyc2lvbiAzLjAKICAgICAgICAgKiBAc2VlIGZsYXNoLnRleHQuZW5naW5lLkRpZ2l0Q2FzZQogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBmdW5jdGlvbiBnZXQgZGlnaXRDYXNlKCk6KgogICAgICAgIHsgcmV0dXJuIF9zdHlsZXMuZGlnaXRDYXNlOyB9CiAgICAgICAgcHVibGljIGZ1bmN0aW9uIHNldCBkaWdpdENhc2UodmFsdWU6Kik6dm9pZAogICAgICAgIHsgc2V0U3R5bGVCeVByb3BlcnR5KFRleHRMYXlvdXRGb3JtYXQuZGlnaXRDYXNlUHJvcGVydHksdmFsdWUpOyB9CgogICAgICAgIFtJbnNwZWN0YWJsZShlbnVtZXJhdGlvbj0iZGVmYXVsdCxwcm9wb3J0aW9uYWwsdGFidWxhcixpbmhlcml0IildCiAgICAgICAgLyoqCiAgICAgICAgICogVHlwZSBvZiBkaWdpdCB3aWR0aCB1c2VkIGZvciB0aGlzIHRleHQuIFRoaXMgY2FuIGJlIDxjb2RlPkRpZ2l0V2lkdGguUFJPUE9SVElPTkFMPC9jb2RlPiwgd2hpY2ggbG9va3MgYmVzdCBmb3IgaW5kaXZpZHVhbCBudW1iZXJzLCBvciA8Y29kZT5EaWdpdFdpZHRoLlRBQlVMQVI8L2NvZGU+LCB3aGljaCB3b3JrcyBiZXN0IGZvciBudW1iZXJzIGluIHRhYmxlcywgY2hhcnRzLCBhbmQgdmVydGljYWwgcm93cy48cD48aW1nIHNyYz0nLi4vLi4vLi4vaW1hZ2VzL3RleHRMYXlvdXRfZGlnaXR3aWR0aC5naWYnIGFsdD0nZGlnaXRXaWR0aCcgLz48L3A+CiAgICAgICAgICogPHA+TGVnYWwgdmFsdWVzIGFyZSBEaWdpdFdpZHRoLkRFRkFVTFQsIERpZ2l0V2lkdGguUFJPUE9SVElPTkFMLCBEaWdpdFdpZHRoLlRBQlVMQVIsIEZvcm1hdFZhbHVlLklOSEVSSVQuPC9wPgogICAgICAgICAqIDxwPkRlZmF1bHQgdmFsdWUgaXMgdW5kZWZpbmVkIGluZGljYXRpbmcgbm90IHNldC48L3A+CiAgICAgICAgICogPHA+SWYgdW5kZWZpbmVkIGR1cmluZyB0aGUgY2FzY2FkZSB0aGlzIHByb3BlcnR5IHdpbGwgaW5oZXJpdCBpdHMgdmFsdWUgZnJvbSBhbiBhbmNlc3Rvci4gSWYgbm8gYW5jZXN0b3IgaGFzIHNldCB0aGlzIHByb3BlcnR5LCBpdCB3aWxsIGhhdmUgYSB2YWx1ZSBvZiBEaWdpdFdpZHRoLkRFRkFVTFQuPC9wPgogICAgICAgICAqIAogICAgICAgICAqIEB0aHJvd3MgUmFuZ2VFcnJvciB3aGVuIHNldCB2YWx1ZSBpcyBub3Qgd2l0aGluIHJhbmdlIGZvciB0aGlzIHByb3BlcnR5CiAgICAgICAgICogCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gRmxhc2ggMTAKICAgICAgICAgKiBAcGxheWVydmVyc2lvbiBBSVIgMS41CiAgICAgICAgICogQGxhbmd2ZXJzaW9uIDMuMAogICAgICAgICAqIEBzZWUgZmxhc2gudGV4dC5lbmdpbmUuRGlnaXRXaWR0aAogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBmdW5jdGlvbiBnZXQgZGlnaXRXaWR0aCgpOioKICAgICAgICB7IHJldHVybiBfc3R5bGVzLmRpZ2l0V2lkdGg7IH0KICAgICAgICBwdWJsaWMgZnVuY3Rpb24gc2V0IGRpZ2l0V2lkdGgodmFsdWU6Kik6dm9pZAogICAgICAgIHsgc2V0U3R5bGVCeVByb3BlcnR5KFRleHRMYXlvdXRGb3JtYXQuZGlnaXRXaWR0aFByb3BlcnR5LHZhbHVlKTsgfQoKICAgICAgICBbSW5zcGVjdGFibGUoZW51bWVyYXRpb249ImF1dG8scm9tYW4sYXNjZW50LGRlc2NlbnQsaWRlb2dyYXBoaWNUb3AsaWRlb2dyYXBoaWNDZW50ZXIsaWRlb2dyYXBoaWNCb3R0b20saW5oZXJpdCIpXQogICAgICAgIC8qKgogICAgICAgICAqIFNwZWNpZmllcyB3aGljaCBlbGVtZW50IGJhc2VsaW5lIHNuYXBzIHRvIHRoZSA8Y29kZT5hbGlnbm1lbnRCYXNlbGluZTwvY29kZT4gdG8gZGV0ZXJtaW5lIHRoZSB2ZXJ0aWNhbCBwb3NpdGlvbiBvZiB0aGUgZWxlbWVudCBvbiB0aGUgbGluZS4gQSB2YWx1ZSBvZiA8Y29kZT5UZXh0QmFzZWxpbmUuQVVUTzwvY29kZT4gc2VsZWN0cyB0aGUgZG9taW5hbnQgYmFzZWxpbmUgYmFzZWQgb24gdGhlIDxjb2RlPmxvY2FsZTwvY29kZT4gcHJvcGVydHkgb2YgdGhlIHBhcmVudCBwYXJhZ3JhcGguICBGb3IgSmFwYW5lc2UgYW5kIENoaW5lc2UsIHRoZSBzZWxlY3RlZCBiYXNlbGluZSB2YWx1ZSBpcyA8Y29kZT5UZXh0QmFzZWxpbmUuSURFT0dSQVBISUNfQ0VOVEVSPC9jb2RlPjsgZm9yIGFsbCBvdGhlcnMgaXQgaXMgPGNvZGU+VGV4dEJhc2VsaW5lLlJPTUFOPC9jb2RlPi4gVGhlc2UgYmFzZWxpbmUgY2hvaWNlcyBhcmUgZGV0ZXJtaW5lZCBieSB0aGUgY2hvaWNlIG9mIGZvbnQgYW5kIHRoZSBmb250IHNpemUuPHA+PGltZyBzcmM9Jy4uLy4uLy4uL2ltYWdlcy90ZXh0TGF5b3V0X2Jhc2VsaW5lcy5qcGcnIGFsdD0nYmFzZWxpbmVzJyAvPjwvcD4KICAgICAgICAgKiA8cD5MZWdhbCB2YWx1ZXMgYXJlIEZvcm1hdFZhbHVlLkFVVE8sIFRleHRCYXNlbGluZS5ST01BTiwgVGV4dEJhc2VsaW5lLkFTQ0VOVCwgVGV4dEJhc2VsaW5lLkRFU0NFTlQsIFRleHRCYXNlbGluZS5JREVPR1JBUEhJQ19UT1AsIFRleHRCYXNlbGluZS5JREVPR1JBUEhJQ19DRU5URVIsIFRleHRCYXNlbGluZS5JREVPR1JBUEhJQ19CT1RUT00sIEZvcm1hdFZhbHVlLklOSEVSSVQuPC9wPgogICAgICAgICAqIDxwPkRlZmF1bHQgdmFsdWUgaXMgdW5kZWZpbmVkIGluZGljYXRpbmcgbm90IHNldC48L3A+CiAgICAgICAgICogPHA+SWYgdW5kZWZpbmVkIGR1cmluZyB0aGUgY2FzY2FkZSB0aGlzIHByb3BlcnR5IHdpbGwgaW5oZXJpdCBpdHMgdmFsdWUgZnJvbSBhbiBhbmNlc3Rvci4gSWYgbm8gYW5jZXN0b3IgaGFzIHNldCB0aGlzIHByb3BlcnR5LCBpdCB3aWxsIGhhdmUgYSB2YWx1ZSBvZiBGb3JtYXRWYWx1ZS5BVVRPLjwvcD4KICAgICAgICAgKiAKICAgICAgICAgKiBAdGhyb3dzIFJhbmdlRXJyb3Igd2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eQogICAgICAgICAqIAogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQogICAgICAgICAqIEBsYW5ndmVyc2lvbiAzLjAKICAgICAgICAgKiBAc2VlIGZsYXNoLnRleHQuZW5naW5lLlRleHRCYXNlbGluZQogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBmdW5jdGlvbiBnZXQgZG9taW5hbnRCYXNlbGluZSgpOioKICAgICAgICB7IHJldHVybiBfc3R5bGVzLmRvbWluYW50QmFzZWxpbmU7IH0KICAgICAgICBwdWJsaWMgZnVuY3Rpb24gc2V0IGRvbWluYW50QmFzZWxpbmUodmFsdWU6Kik6dm9pZAogICAgICAgIHsgc2V0U3R5bGVCeVByb3BlcnR5KFRleHRMYXlvdXRGb3JtYXQuZG9taW5hbnRCYXNlbGluZVByb3BlcnR5LHZhbHVlKTsgfQoKICAgICAgICBbSW5zcGVjdGFibGUoZW51bWVyYXRpb249Im9uLG9mZixhdXRvLGluaGVyaXQiKV0KICAgICAgICAvKioKICAgICAgICAgKiBLZXJuaW5nIGFkanVzdHMgdGhlIHBpeGVscyBiZXR3ZWVuIGNlcnRhaW4gY2hhcmFjdGVyIHBhaXJzIHRvIGltcHJvdmUgcmVhZGFiaWxpdHkuIEtlcm5pbmcgaXMgc3VwcG9ydGVkIGZvciBhbGwgZm9udHMgd2l0aCBrZXJuaW5nIHRhYmxlcy4KICAgICAgICAgKiA8cD5MZWdhbCB2YWx1ZXMgYXJlIEtlcm5pbmcuT04sIEtlcm5pbmcuT0ZGLCBLZXJuaW5nLkFVVE8sIEZvcm1hdFZhbHVlLklOSEVSSVQuPC9wPgogICAgICAgICAqIDxwPkRlZmF1bHQgdmFsdWUgaXMgdW5kZWZpbmVkIGluZGljYXRpbmcgbm90IHNldC48L3A+CiAgICAgICAgICogPHA+SWYgdW5kZWZpbmVkIGR1cmluZyB0aGUgY2FzY2FkZSB0aGlzIHByb3BlcnR5IHdpbGwgaW5oZXJpdCBpdHMgdmFsdWUgZnJvbSBhbiBhbmNlc3Rvci4gSWYgbm8gYW5jZXN0b3IgaGFzIHNldCB0aGlzIHByb3BlcnR5LCBpdCB3aWxsIGhhdmUgYSB2YWx1ZSBvZiBLZXJuaW5nLkFVVE8uPC9wPgogICAgICAgICAqIAogICAgICAgICAqIEB0aHJvd3MgUmFuZ2VFcnJvciB3aGVuIHNldCB2YWx1ZSBpcyBub3Qgd2l0aGluIHJhbmdlIGZvciB0aGlzIHByb3BlcnR5CiAgICAgICAgICogCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gRmxhc2ggMTAKICAgICAgICAgKiBAcGxheWVydmVyc2lvbiBBSVIgMS41CiAgICAgICAgICogQGxhbmd2ZXJzaW9uIDMuMAogICAgICAgICAqIEBzZWUgZmxhc2gudGV4dC5lbmdpbmUuS2VybmluZwogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBmdW5jdGlvbiBnZXQga2VybmluZygpOioKICAgICAgICB7IHJldHVybiBfc3R5bGVzLmtlcm5pbmc7IH0KICAgICAgICBwdWJsaWMgZnVuY3Rpb24gc2V0IGtlcm5pbmcodmFsdWU6Kik6dm9pZAogICAgICAgIHsgc2V0U3R5bGVCeVByb3BlcnR5KFRleHRMYXlvdXRGb3JtYXQua2VybmluZ1Byb3BlcnR5LHZhbHVlKTsgfQoKICAgICAgICBbSW5zcGVjdGFibGUoZW51bWVyYXRpb249Im1pbmltdW0sY29tbW9uLHVuY29tbW9uLGV4b3RpYyxpbmhlcml0IildCiAgICAgICAgLyoqCiAgICAgICAgICogQ29udHJvbHMgd2hpY2ggb2YgdGhlIGxpZ2F0dXJlcyB0aGF0IGFyZSBkZWZpbmVkIGluIHRoZSBmb250IG1heSBiZSB1c2VkIGluIHRoZSB0ZXh0LiBUaGUgbGlnYXR1cmVzIHRoYXQgYXBwZWFyIGZvciBlYWNoIG9mIHRoZXNlIHNldHRpbmdzIGlzIGRlcGVuZGVudCBvbiB0aGUgZm9udC4gQSBsaWdhdHVyZSBvY2N1cnMgd2hlcmUgdHdvIG9yIG1vcmUgbGV0dGVyLWZvcm1zIGFyZSBqb2luZWQgYXMgYSBzaW5nbGUgZ2x5cGguIExpZ2F0dXJlcyB1c3VhbGx5IHJlcGxhY2UgY29uc2VjdXRpdmUgY2hhcmFjdGVycyBzaGFyaW5nIGNvbW1vbiBjb21wb25lbnRzLCBzdWNoIGFzIHRoZSBsZXR0ZXIgcGFpcnMgJ2ZpJywgJ2ZsJywgb3IgJ2FlJy4gVGhleSBhcmUgdXNlZCB3aXRoIGJvdGggTGF0aW4gYW5kIE5vbi1MYXRpbiBjaGFyYWN0ZXIgc2V0cy4gVGhlIGxpZ2F0dXJlcyBlbmFibGVkIGJ5IHRoZSB2YWx1ZXMgb2YgdGhlIExpZ2F0dXJlTGV2ZWwgY2xhc3MgLSA8Y29kZT5NSU5JTVVNPC9jb2RlPiwgPGNvZGU+Q09NTU9OPC9jb2RlPiwgPGNvZGU+VU5DT01NT048L2NvZGU+LCBhbmQgPGNvZGU+RVhPVElDPC9jb2RlPiAtIGFyZSBhZGRpdGl2ZS4gRWFjaCB2YWx1ZSBlbmFibGVzIGEgbmV3IHNldCBvZiBsaWdhdHVyZXMsIGJ1dCBhbHNvIGluY2x1ZGVzIHRob3NlIG9mIHRoZSBwcmV2aW91cyB0eXBlcy48cD48Yj5Ob3RlOiA8L2I+V2hlbiB3b3JraW5nIHdpdGggQXJhYmljIG9yIFN5cmlhYyBmb250cywgPGNvZGU+bGlnYXR1cmVMZXZlbDwvY29kZT4gbXVzdCBiZSBzZXQgdG8gTUlOSU1VTSBvciBhYm92ZS48L3A+PHA+PGltZyBzcmM9Jy4uLy4uLy4uL2ltYWdlcy90ZXh0TGF5b3V0X2xpZ2F0dXJlcy5wbmcnIGFsdD0nbGlnYXR1cmVMZXZlbCcgLz48L3A+CiAgICAgICAgICogPHA+TGVnYWwgdmFsdWVzIGFyZSBMaWdhdHVyZUxldmVsLk1JTklNVU0sIExpZ2F0dXJlTGV2ZWwuQ09NTU9OLCBMaWdhdHVyZUxldmVsLlVOQ09NTU9OLCBMaWdhdHVyZUxldmVsLkVYT1RJQywgRm9ybWF0VmFsdWUuSU5IRVJJVC48L3A+CiAgICAgICAgICogPHA+RGVmYXVsdCB2YWx1ZSBpcyB1bmRlZmluZWQgaW5kaWNhdGluZyBub3Qgc2V0LjwvcD4KICAgICAgICAgKiA8cD5JZiB1bmRlZmluZWQgZHVyaW5nIHRoZSBjYXNjYWRlIHRoaXMgcHJvcGVydHkgd2lsbCBpbmhlcml0IGl0cyB2YWx1ZSBmcm9tIGFuIGFuY2VzdG9yLiBJZiBubyBhbmNlc3RvciBoYXMgc2V0IHRoaXMgcHJvcGVydHksIGl0IHdpbGwgaGF2ZSBhIHZhbHVlIG9mIExpZ2F0dXJlTGV2ZWwuQ09NTU9OLjwvcD4KICAgICAgICAgKiAKICAgICAgICAgKiBAdGhyb3dzIFJhbmdlRXJyb3Igd2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eQogICAgICAgICAqIAogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQogICAgICAgICAqIEBsYW5ndmVyc2lvbiAzLjAKICAgICAgICAgKiBAc2VlIGZsYXNoLnRleHQuZW5naW5lLkxpZ2F0dXJlTGV2ZWwKICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgZnVuY3Rpb24gZ2V0IGxpZ2F0dXJlTGV2ZWwoKToqCiAgICAgICAgeyByZXR1cm4gX3N0eWxlcy5saWdhdHVyZUxldmVsOyB9CiAgICAgICAgcHVibGljIGZ1bmN0aW9uIHNldCBsaWdhdHVyZUxldmVsKHZhbHVlOiopOnZvaWQKICAgICAgICB7IHNldFN0eWxlQnlQcm9wZXJ0eShUZXh0TGF5b3V0Rm9ybWF0LmxpZ2F0dXJlTGV2ZWxQcm9wZXJ0eSx2YWx1ZSk7IH0KCiAgICAgICAgW0luc3BlY3RhYmxlKGVudW1lcmF0aW9uPSJyb21hbixhc2NlbnQsZGVzY2VudCxpZGVvZ3JhcGhpY1RvcCxpZGVvZ3JhcGhpY0NlbnRlcixpZGVvZ3JhcGhpY0JvdHRvbSx1c2VEb21pbmFudEJhc2VsaW5lLGluaGVyaXQiKV0KICAgICAgICAvKioKICAgICAgICAgKiBTcGVjaWZpZXMgdGhlIGJhc2VsaW5lIHRvIHdoaWNoIHRoZSBkb21pbmFudCBiYXNlbGluZSBhbGlnbnMuIEZvciBleGFtcGxlLCBpZiB5b3Ugc2V0IDxjb2RlPmRvbWluYW50QmFzZWxpbmU8L2NvZGU+IHRvIEFTQ0VOVCwgc2V0dGluZyA8Y29kZT5hbGlnbm1lbnRCYXNlbGluZTwvY29kZT4gdG8gREVTQ0VOVCBhbGlnbnMgdGhlIHRvcCBvZiB0aGUgdGV4dCB3aXRoIHRoZSBERVNDRU5UIGJhc2VsaW5lLCBvciBiZWxvdyB0aGUgbGluZS4gIFRoZSBsYXJnZXN0IGVsZW1lbnQgaW4gdGhlIGxpbmUgZ2VuZXJhbGx5IGRldGVybWluZXMgdGhlIGJhc2VsaW5lcy48cD48aW1nIHNyYz0nLi4vLi4vLi4vaW1hZ2VzL3RleHRMYXlvdXRfYmFzZWxpbmVzLmpwZycgYWx0PSdiYXNlbGluZXMnIC8+PC9wPgogICAgICAgICAqIDxwPkxlZ2FsIHZhbHVlcyBhcmUgVGV4dEJhc2VsaW5lLlJPTUFOLCBUZXh0QmFzZWxpbmUuQVNDRU5ULCBUZXh0QmFzZWxpbmUuREVTQ0VOVCwgVGV4dEJhc2VsaW5lLklERU9HUkFQSElDX1RPUCwgVGV4dEJhc2VsaW5lLklERU9HUkFQSElDX0NFTlRFUiwgVGV4dEJhc2VsaW5lLklERU9HUkFQSElDX0JPVFRPTSwgVGV4dEJhc2VsaW5lLlVTRV9ET01JTkFOVF9CQVNFTElORSwgRm9ybWF0VmFsdWUuSU5IRVJJVC48L3A+CiAgICAgICAgICogPHA+RGVmYXVsdCB2YWx1ZSBpcyB1bmRlZmluZWQgaW5kaWNhdGluZyBub3Qgc2V0LjwvcD4KICAgICAgICAgKiA8cD5JZiB1bmRlZmluZWQgZHVyaW5nIHRoZSBjYXNjYWRlIHRoaXMgcHJvcGVydHkgd2lsbCBpbmhlcml0IGl0cyB2YWx1ZSBmcm9tIGFuIGFuY2VzdG9yLiBJZiBubyBhbmNlc3RvciBoYXMgc2V0IHRoaXMgcHJvcGVydHksIGl0IHdpbGwgaGF2ZSBhIHZhbHVlIG9mIFRleHRCYXNlbGluZS5VU0VfRE9NSU5BTlRfQkFTRUxJTkUuPC9wPgogICAgICAgICAqIEBpbmNsdWRlRXhhbXBsZSBleGFtcGxlc1xUZXh0TGF5b3V0Rm9ybWF0X2FsaWdubWVudEJhc2VsaW5lRXhhbXBsZS5hcyAtbm9zd2YKICAgICAgICAgKiAKICAgICAgICAgKiBAdGhyb3dzIFJhbmdlRXJyb3Igd2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eQogICAgICAgICAqIAogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQogICAgICAgICAqIEBsYW5ndmVyc2lvbiAzLjAKICAgICAgICAgKiBAc2VlIGZsYXNoLnRleHQuZW5naW5lLlRleHRCYXNlbGluZQogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBmdW5jdGlvbiBnZXQgYWxpZ25tZW50QmFzZWxpbmUoKToqCiAgICAgICAgeyByZXR1cm4gX3N0eWxlcy5hbGlnbm1lbnRCYXNlbGluZTsgfQogICAgICAgIHB1YmxpYyBmdW5jdGlvbiBzZXQgYWxpZ25tZW50QmFzZWxpbmUodmFsdWU6Kik6dm9pZAogICAgICAgIHsgc2V0U3R5bGVCeVByb3BlcnR5KFRleHRMYXlvdXRGb3JtYXQuYWxpZ25tZW50QmFzZWxpbmVQcm9wZXJ0eSx2YWx1ZSk7IH0KCiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIGxvY2FsZSBvZiB0aGUgdGV4dC4gQ29udHJvbHMgY2FzZSB0cmFuc2Zvcm1hdGlvbnMgYW5kIHNoYXBpbmcuIFN0YW5kYXJkIGxvY2FsZSBpZGVudGlmaWVycyBhcyBkZXNjcmliZWQgaW4gVW5pY29kZSBUZWNobmljYWwgU3RhbmRhcmQgIzM1IGFyZSB1c2VkLiBGb3IgZXhhbXBsZSBlbiwgZW5fVVMgYW5kIGVuLVVTIGFyZSBhbGwgRW5nbGlzaCwgamEgaXMgSmFwYW5lc2UuIAogICAgICAgICAqIDxwPkRlZmF1bHQgdmFsdWUgaXMgdW5kZWZpbmVkIGluZGljYXRpbmcgbm90IHNldC48L3A+CiAgICAgICAgICogPHA+SWYgdW5kZWZpbmVkIGR1cmluZyB0aGUgY2FzY2FkZSB0aGlzIHByb3BlcnR5IHdpbGwgaW5oZXJpdCBpdHMgdmFsdWUgZnJvbSBhbiBhbmNlc3Rvci4gSWYgbm8gYW5jZXN0b3IgaGFzIHNldCB0aGlzIHByb3BlcnR5LCBpdCB3aWxsIGhhdmUgYSB2YWx1ZSBvZiBlbi48L3A+CiAgICAgICAgICogCiAgICAgICAgICogQHRocm93cyBSYW5nZUVycm9yIHdoZW4gc2V0IHZhbHVlIGlzIG5vdCB3aXRoaW4gcmFuZ2UgZm9yIHRoaXMgcHJvcGVydHkKICAgICAgICAgKiAKICAgICAgICAgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKICAgICAgICAgKiBAbGFuZ3ZlcnNpb24gMy4wCiAgICAgICAgICovCiAgICAgICAgcHVibGljIGZ1bmN0aW9uIGdldCBsb2NhbGUoKToqCiAgICAgICAgeyByZXR1cm4gX3N0eWxlcy5sb2NhbGU7IH0KICAgICAgICBwdWJsaWMgZnVuY3Rpb24gc2V0IGxvY2FsZSh2YWx1ZToqKTp2b2lkCiAgICAgICAgeyBzZXRTdHlsZUJ5UHJvcGVydHkoVGV4dExheW91dEZvcm1hdC5sb2NhbGVQcm9wZXJ0eSx2YWx1ZSk7IH0KCiAgICAgICAgW0luc3BlY3RhYmxlKGVudW1lcmF0aW9uPSJkZWZhdWx0LGNhcHNUb1NtYWxsQ2Fwcyx1cHBlcmNhc2UsbG93ZXJjYXNlLGxvd2VyY2FzZVRvU21hbGxDYXBzLGluaGVyaXQiKV0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgdHlwZSBvZiB0eXBvZ3JhcGhpYyBjYXNlIHVzZWQgZm9yIHRoaXMgdGV4dC4gSGVyZSBhcmUgc29tZSBleGFtcGxlczo8cD48aW1nIHNyYz0nLi4vLi4vLi4vaW1hZ2VzL3RleHRMYXlvdXRfdHlwb2dyYXBoaWNjYXNlLnBuZycgYWx0PSd0eXBvZ3JhcGhpY0Nhc2UnIC8+PC9wPgogICAgICAgICAqIDxwPkxlZ2FsIHZhbHVlcyBhcmUgVExGVHlwb2dyYXBoaWNDYXNlLkRFRkFVTFQsIFRMRlR5cG9ncmFwaGljQ2FzZS5DQVBTX1RPX1NNQUxMX0NBUFMsIFRMRlR5cG9ncmFwaGljQ2FzZS5VUFBFUkNBU0UsIFRMRlR5cG9ncmFwaGljQ2FzZS5MT1dFUkNBU0UsIFRMRlR5cG9ncmFwaGljQ2FzZS5MT1dFUkNBU0VfVE9fU01BTExfQ0FQUywgRm9ybWF0VmFsdWUuSU5IRVJJVC48L3A+CiAgICAgICAgICogPHA+RGVmYXVsdCB2YWx1ZSBpcyB1bmRlZmluZWQgaW5kaWNhdGluZyBub3Qgc2V0LjwvcD4KICAgICAgICAgKiA8cD5JZiB1bmRlZmluZWQgZHVyaW5nIHRoZSBjYXNjYWRlIHRoaXMgcHJvcGVydHkgd2lsbCBpbmhlcml0IGl0cyB2YWx1ZSBmcm9tIGFuIGFuY2VzdG9yLiBJZiBubyBhbmNlc3RvciBoYXMgc2V0IHRoaXMgcHJvcGVydHksIGl0IHdpbGwgaGF2ZSBhIHZhbHVlIG9mIFRMRlR5cG9ncmFwaGljQ2FzZS5ERUZBVUxULjwvcD4KICAgICAgICAgKiAKICAgICAgICAgKiBAdGhyb3dzIFJhbmdlRXJyb3Igd2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eQogICAgICAgICAqIAogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQogICAgICAgICAqIEBsYW5ndmVyc2lvbiAzLjAKICAgICAgICAgKiBAc2VlIGZsYXNoeC50ZXh0TGF5b3V0LmZvcm1hdHMuVExGVHlwb2dyYXBoaWNDYXNlCiAgICAgICAgICovCiAgICAgICAgcHVibGljIGZ1bmN0aW9uIGdldCB0eXBvZ3JhcGhpY0Nhc2UoKToqCiAgICAgICAgeyByZXR1cm4gX3N0eWxlcy50eXBvZ3JhcGhpY0Nhc2U7IH0KICAgICAgICBwdWJsaWMgZnVuY3Rpb24gc2V0IHR5cG9ncmFwaGljQ2FzZSh2YWx1ZToqKTp2b2lkCiAgICAgICAgeyBzZXRTdHlsZUJ5UHJvcGVydHkoVGV4dExheW91dEZvcm1hdC50eXBvZ3JhcGhpY0Nhc2VQcm9wZXJ0eSx2YWx1ZSk7IH0KCiAgICAgICAgLyoqCiAgICAgICAgICogIFRoZSBuYW1lIG9mIHRoZSBmb250IHRvIHVzZSwgb3IgYSBjb21tYS1zZXBhcmF0ZWQgbGlzdCBvZiBmb250IG5hbWVzLiBUaGUgRmxhc2ggcnVudGltZSByZW5kZXJzIHRoZSBlbGVtZW50IHdpdGggdGhlIGZpcnN0IGF2YWlsYWJsZSBmb250IGluIHRoZSBsaXN0LiBGb3IgZXhhbXBsZSBBcmlhbCwgSGVsdmV0aWNhLCBfc2FucyBjYXVzZXMgdGhlIHBsYXllciB0byBzZWFyY2ggZm9yIEFyaWFsLCB0aGVuIEhlbHZldGljYSBpZiBBcmlhbCBpcyBub3QgZm91bmQsIHRoZW4gX3NhbnMgaWYgbmVpdGhlciBpcyBmb3VuZC4KICAgICAgICAgKiA8cD5EZWZhdWx0IHZhbHVlIGlzIHVuZGVmaW5lZCBpbmRpY2F0aW5nIG5vdCBzZXQuPC9wPgogICAgICAgICAqIDxwPklmIHVuZGVmaW5lZCBkdXJpbmcgdGhlIGNhc2NhZGUgdGhpcyBwcm9wZXJ0eSB3aWxsIGluaGVyaXQgaXRzIHZhbHVlIGZyb20gYW4gYW5jZXN0b3IuIElmIG5vIGFuY2VzdG9yIGhhcyBzZXQgdGhpcyBwcm9wZXJ0eSwgaXQgd2lsbCBoYXZlIGEgdmFsdWUgb2YgQXJpYWwuPC9wPgogICAgICAgICAqIAogICAgICAgICAqIEB0aHJvd3MgUmFuZ2VFcnJvciB3aGVuIHNldCB2YWx1ZSBpcyBub3Qgd2l0aGluIHJhbmdlIGZvciB0aGlzIHByb3BlcnR5CiAgICAgICAgICogCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gRmxhc2ggMTAKICAgICAgICAgKiBAcGxheWVydmVyc2lvbiBBSVIgMS41CiAgICAgICAgICogQGxhbmd2ZXJzaW9uIDMuMAogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBmdW5jdGlvbiBnZXQgZm9udEZhbWlseSgpOioKICAgICAgICB7IHJldHVybiBfc3R5bGVzLmZvbnRGYW1pbHk7IH0KICAgICAgICBwdWJsaWMgZnVuY3Rpb24gc2V0IGZvbnRGYW1pbHkodmFsdWU6Kik6dm9pZAogICAgICAgIHsgc2V0U3R5bGVCeVByb3BlcnR5KFRleHRMYXlvdXRGb3JtYXQuZm9udEZhbWlseVByb3BlcnR5LHZhbHVlKTsgfQoKICAgICAgICBbSW5zcGVjdGFibGUoZW51bWVyYXRpb249Im5vbmUsdW5kZXJsaW5lLGluaGVyaXQiKV0KICAgICAgICAvKioKICAgICAgICAgKiBEZWNvcmF0aW9uIG9uIHRleHQuIFVzZSB0byBhcHBseSB1bmRlcmxpbmluZzsgZGVmYXVsdCBpcyBub25lLgogICAgICAgICAqIDxwPkxlZ2FsIHZhbHVlcyBhcmUgVGV4dERlY29yYXRpb24uTk9ORSwgVGV4dERlY29yYXRpb24uVU5ERVJMSU5FLCBGb3JtYXRWYWx1ZS5JTkhFUklULjwvcD4KICAgICAgICAgKiA8cD5EZWZhdWx0IHZhbHVlIGlzIHVuZGVmaW5lZCBpbmRpY2F0aW5nIG5vdCBzZXQuPC9wPgogICAgICAgICAqIDxwPklmIHVuZGVmaW5lZCBkdXJpbmcgdGhlIGNhc2NhZGUgdGhpcyBwcm9wZXJ0eSB3aWxsIGluaGVyaXQgaXRzIHZhbHVlIGZyb20gYW4gYW5jZXN0b3IuIElmIG5vIGFuY2VzdG9yIGhhcyBzZXQgdGhpcyBwcm9wZXJ0eSwgaXQgd2lsbCBoYXZlIGEgdmFsdWUgb2YgVGV4dERlY29yYXRpb24uTk9ORS48L3A+CiAgICAgICAgICogCiAgICAgICAgICogQHRocm93cyBSYW5nZUVycm9yIHdoZW4gc2V0IHZhbHVlIGlzIG5vdCB3aXRoaW4gcmFuZ2UgZm9yIHRoaXMgcHJvcGVydHkKICAgICAgICAgKiAKICAgICAgICAgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKICAgICAgICAgKiBAbGFuZ3ZlcnNpb24gMy4wCiAgICAgICAgICogQHNlZSBmbGFzaHgudGV4dExheW91dC5mb3JtYXRzLlRleHREZWNvcmF0aW9uCiAgICAgICAgICovCiAgICAgICAgcHVibGljIGZ1bmN0aW9uIGdldCB0ZXh0RGVjb3JhdGlvbigpOioKICAgICAgICB7IHJldHVybiBfc3R5bGVzLnRleHREZWNvcmF0aW9uOyB9CiAgICAgICAgcHVibGljIGZ1bmN0aW9uIHNldCB0ZXh0RGVjb3JhdGlvbih2YWx1ZToqKTp2b2lkCiAgICAgICAgeyBzZXRTdHlsZUJ5UHJvcGVydHkoVGV4dExheW91dEZvcm1hdC50ZXh0RGVjb3JhdGlvblByb3BlcnR5LHZhbHVlKTsgfQoKICAgICAgICBbSW5zcGVjdGFibGUoZW51bWVyYXRpb249Im5vcm1hbCxib2xkLGluaGVyaXQiKV0KICAgICAgICAvKioKICAgICAgICAgKiBXZWlnaHQgb2YgdGV4dC4gTWF5IGJlIDxjb2RlPkZvbnRXZWlnaHQuTk9STUFMPC9jb2RlPiBmb3IgdXNlIGluIHBsYWluIHRleHQsIG9yIDxjb2RlPkZvbnRXZWlnaHQuQk9MRDwvY29kZT4uIEFwcGxpZXMgb25seSB0byBkZXZpY2UgZm9udHMgKDxjb2RlPmZvbnRMb29rdXA8L2NvZGU+IHByb3BlcnR5IGlzIHNldCB0byBmbGFzaC50ZXh0LmVuZ2luZS5Gb250TG9va3VwLkRFVklDRSkuCiAgICAgICAgICogPHA+TGVnYWwgdmFsdWVzIGFyZSBGb250V2VpZ2h0Lk5PUk1BTCwgRm9udFdlaWdodC5CT0xELCBGb3JtYXRWYWx1ZS5JTkhFUklULjwvcD4KICAgICAgICAgKiA8cD5EZWZhdWx0IHZhbHVlIGlzIHVuZGVmaW5lZCBpbmRpY2F0aW5nIG5vdCBzZXQuPC9wPgogICAgICAgICAqIDxwPklmIHVuZGVmaW5lZCBkdXJpbmcgdGhlIGNhc2NhZGUgdGhpcyBwcm9wZXJ0eSB3aWxsIGluaGVyaXQgaXRzIHZhbHVlIGZyb20gYW4gYW5jZXN0b3IuIElmIG5vIGFuY2VzdG9yIGhhcyBzZXQgdGhpcyBwcm9wZXJ0eSwgaXQgd2lsbCBoYXZlIGEgdmFsdWUgb2YgRm9udFdlaWdodC5OT1JNQUwuPC9wPgogICAgICAgICAqIAogICAgICAgICAqIEB0aHJvd3MgUmFuZ2VFcnJvciB3aGVuIHNldCB2YWx1ZSBpcyBub3Qgd2l0aGluIHJhbmdlIGZvciB0aGlzIHByb3BlcnR5CiAgICAgICAgICogCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gRmxhc2ggMTAKICAgICAgICAgKiBAcGxheWVydmVyc2lvbiBBSVIgMS41CiAgICAgICAgICogQGxhbmd2ZXJzaW9uIDMuMAogICAgICAgICAqIEBzZWUgZmxhc2gudGV4dC5lbmdpbmUuRm9udFdlaWdodAogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBmdW5jdGlvbiBnZXQgZm9udFdlaWdodCgpOioKICAgICAgICB7IHJldHVybiBfc3R5bGVzLmZvbnRXZWlnaHQ7IH0KICAgICAgICBwdWJsaWMgZnVuY3Rpb24gc2V0IGZvbnRXZWlnaHQodmFsdWU6Kik6dm9pZAogICAgICAgIHsgc2V0U3R5bGVCeVByb3BlcnR5KFRleHRMYXlvdXRGb3JtYXQuZm9udFdlaWdodFByb3BlcnR5LHZhbHVlKTsgfQoKICAgICAgICBbSW5zcGVjdGFibGUoZW51bWVyYXRpb249Im5vcm1hbCxpdGFsaWMsaW5oZXJpdCIpXQogICAgICAgIC8qKgogICAgICAgICAqIFN0eWxlIG9mIHRleHQuIE1heSBiZSA8Y29kZT5Gb250UG9zdHVyZS5OT1JNQUw8L2NvZGU+LCBmb3IgdXNlIGluIHBsYWluIHRleHQsIG9yIDxjb2RlPkZvbnRQb3N0dXJlLklUQUxJQzwvY29kZT4gZm9yIGl0YWxpYy4gVGhpcyBwcm9wZXJ0eSBhcHBsaWVzIG9ubHkgdG8gZGV2aWNlIGZvbnRzICg8Y29kZT5mb250TG9va3VwPC9jb2RlPiBwcm9wZXJ0eSBpcyBzZXQgdG8gZmxhc2gudGV4dC5lbmdpbmUuRm9udExvb2t1cC5ERVZJQ0UpLgogICAgICAgICAqIDxwPkxlZ2FsIHZhbHVlcyBhcmUgRm9udFBvc3R1cmUuTk9STUFMLCBGb250UG9zdHVyZS5JVEFMSUMsIEZvcm1hdFZhbHVlLklOSEVSSVQuPC9wPgogICAgICAgICAqIDxwPkRlZmF1bHQgdmFsdWUgaXMgdW5kZWZpbmVkIGluZGljYXRpbmcgbm90IHNldC48L3A+CiAgICAgICAgICogPHA+SWYgdW5kZWZpbmVkIGR1cmluZyB0aGUgY2FzY2FkZSB0aGlzIHByb3BlcnR5IHdpbGwgaW5oZXJpdCBpdHMgdmFsdWUgZnJvbSBhbiBhbmNlc3Rvci4gSWYgbm8gYW5jZXN0b3IgaGFzIHNldCB0aGlzIHByb3BlcnR5LCBpdCB3aWxsIGhhdmUgYSB2YWx1ZSBvZiBGb250UG9zdHVyZS5OT1JNQUwuPC9wPgogICAgICAgICAqIAogICAgICAgICAqIEB0aHJvd3MgUmFuZ2VFcnJvciB3aGVuIHNldCB2YWx1ZSBpcyBub3Qgd2l0aGluIHJhbmdlIGZvciB0aGlzIHByb3BlcnR5CiAgICAgICAgICogCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gRmxhc2ggMTAKICAgICAgICAgKiBAcGxheWVydmVyc2lvbiBBSVIgMS41CiAgICAgICAgICogQGxhbmd2ZXJzaW9uIDMuMAogICAgICAgICAqIEBzZWUgZmxhc2gudGV4dC5lbmdpbmUuRm9udFBvc3R1cmUKICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgZnVuY3Rpb24gZ2V0IGZvbnRTdHlsZSgpOioKICAgICAgICB7IHJldHVybiBfc3R5bGVzLmZvbnRTdHlsZTsgfQogICAgICAgIHB1YmxpYyBmdW5jdGlvbiBzZXQgZm9udFN0eWxlKHZhbHVlOiopOnZvaWQKICAgICAgICB7IHNldFN0eWxlQnlQcm9wZXJ0eShUZXh0TGF5b3V0Rm9ybWF0LmZvbnRTdHlsZVByb3BlcnR5LHZhbHVlKTsgfQoKICAgICAgICBbSW5zcGVjdGFibGUoZW51bWVyYXRpb249InByZXNlcnZlLGNvbGxhcHNlLGluaGVyaXQiKV0KICAgICAgICAvKioKICAgICAgICAgKiBDb2xsYXBzZXMgb3IgcHJlc2VydmVzIHdoaXRlc3BhY2Ugd2hlbiBpbXBvcnRpbmcgdGV4dCBpbnRvIGEgVGV4dEZsb3cuIDxjb2RlPldoaXRlU3BhY2VDb2xsYXBzZS5QUkVTRVJWRTwvY29kZT4gcmV0YWlucyBhbGwgd2hpdGVzcGFjZSBjaGFyYWN0ZXJzLiA8Y29kZT5XaGl0ZVNwYWNlQ29sbGFwc2UuQ09MTEFQU0U8L2NvZGU+IHJlbW92ZXMgbmV3bGluZXMsIHRhYnMsIGFuZCBsZWFkaW5nIG9yIHRyYWlsaW5nIHNwYWNlcyB3aXRoaW4gYSBibG9jayBvZiBpbXBvcnRlZCB0ZXh0LiBMaW5lIGJyZWFrIHRhZ3MgKDxici8+KSBhbmQgVW5pY29kZSBsaW5lIHNlcGFyYXRvciBjaGFyYWN0ZXJzIGFyZSByZXRhaW5lZC4KICAgICAgICAgKiA8cD5MZWdhbCB2YWx1ZXMgYXJlIFdoaXRlU3BhY2VDb2xsYXBzZS5QUkVTRVJWRSwgV2hpdGVTcGFjZUNvbGxhcHNlLkNPTExBUFNFLCBGb3JtYXRWYWx1ZS5JTkhFUklULjwvcD4KICAgICAgICAgKiA8cD5EZWZhdWx0IHZhbHVlIGlzIHVuZGVmaW5lZCBpbmRpY2F0aW5nIG5vdCBzZXQuPC9wPgogICAgICAgICAqIDxwPklmIHVuZGVmaW5lZCBkdXJpbmcgdGhlIGNhc2NhZGUgdGhpcyBwcm9wZXJ0eSB3aWxsIGluaGVyaXQgaXRzIHZhbHVlIGZyb20gYW4gYW5jZXN0b3IuIElmIG5vIGFuY2VzdG9yIGhhcyBzZXQgdGhpcyBwcm9wZXJ0eSwgaXQgd2lsbCBoYXZlIGEgdmFsdWUgb2YgV2hpdGVTcGFjZUNvbGxhcHNlLkNPTExBUFNFLjwvcD4KICAgICAgICAgKiAKICAgICAgICAgKiBAdGhyb3dzIFJhbmdlRXJyb3Igd2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eQogICAgICAgICAqIAogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQogICAgICAgICAqIEBsYW5ndmVyc2lvbiAzLjAKICAgICAgICAgKiBAc2VlIGZsYXNoeC50ZXh0TGF5b3V0LmZvcm1hdHMuV2hpdGVTcGFjZUNvbGxhcHNlCiAgICAgICAgICovCiAgICAgICAgcHVibGljIGZ1bmN0aW9uIGdldCB3aGl0ZVNwYWNlQ29sbGFwc2UoKToqCiAgICAgICAgeyByZXR1cm4gX3N0eWxlcy53aGl0ZVNwYWNlQ29sbGFwc2U7IH0KICAgICAgICBwdWJsaWMgZnVuY3Rpb24gc2V0IHdoaXRlU3BhY2VDb2xsYXBzZSh2YWx1ZToqKTp2b2lkCiAgICAgICAgeyBzZXRTdHlsZUJ5UHJvcGVydHkoVGV4dExheW91dEZvcm1hdC53aGl0ZVNwYWNlQ29sbGFwc2VQcm9wZXJ0eSx2YWx1ZSk7IH0KCiAgICAgICAgW0luc3BlY3RhYmxlKGVudW1lcmF0aW9uPSJub3JtYWwsY2ZmLGluaGVyaXQiKV0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgcmVuZGVyaW5nIG1vZGUgdXNlZCBmb3IgdGhpcyB0ZXh0LiAgQXBwbGllcyBvbmx5IHRvIGVtYmVkZGVkIGZvbnRzICg8Y29kZT5mb250TG9va3VwPC9jb2RlPiBwcm9wZXJ0eSBpcyBzZXQgdG8gPGNvZGU+Rm9udExvb2t1cC5FTUJFRERFRF9DRkY8L2NvZGU+KS4KICAgICAgICAgKiA8cD5MZWdhbCB2YWx1ZXMgYXJlIFJlbmRlcmluZ01vZGUuTk9STUFMLCBSZW5kZXJpbmdNb2RlLkNGRiwgRm9ybWF0VmFsdWUuSU5IRVJJVC48L3A+CiAgICAgICAgICogPHA+RGVmYXVsdCB2YWx1ZSBpcyB1bmRlZmluZWQgaW5kaWNhdGluZyBub3Qgc2V0LjwvcD4KICAgICAgICAgKiA8cD5JZiB1bmRlZmluZWQgZHVyaW5nIHRoZSBjYXNjYWRlIHRoaXMgcHJvcGVydHkgd2lsbCBpbmhlcml0IGl0cyB2YWx1ZSBmcm9tIGFuIGFuY2VzdG9yLiBJZiBubyBhbmNlc3RvciBoYXMgc2V0IHRoaXMgcHJvcGVydHksIGl0IHdpbGwgaGF2ZSBhIHZhbHVlIG9mIFJlbmRlcmluZ01vZGUuQ0ZGLjwvcD4KICAgICAgICAgKiAKICAgICAgICAgKiBAdGhyb3dzIFJhbmdlRXJyb3Igd2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eQogICAgICAgICAqIAogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQogICAgICAgICAqIEBsYW5ndmVyc2lvbiAzLjAKICAgICAgICAgKiBAc2VlIGZsYXNoLnRleHQuZW5naW5lLlJlbmRlcmluZ01vZGUKICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgZnVuY3Rpb24gZ2V0IHJlbmRlcmluZ01vZGUoKToqCiAgICAgICAgeyByZXR1cm4gX3N0eWxlcy5yZW5kZXJpbmdNb2RlOyB9CiAgICAgICAgcHVibGljIGZ1bmN0aW9uIHNldCByZW5kZXJpbmdNb2RlKHZhbHVlOiopOnZvaWQKICAgICAgICB7IHNldFN0eWxlQnlQcm9wZXJ0eShUZXh0TGF5b3V0Rm9ybWF0LnJlbmRlcmluZ01vZGVQcm9wZXJ0eSx2YWx1ZSk7IH0KCiAgICAgICAgW0luc3BlY3RhYmxlKGVudW1lcmF0aW9uPSJub25lLGhvcml6b250YWxTdGVtLGluaGVyaXQiKV0KICAgICAgICAvKioKICAgICAgICAgKiBUaGUgdHlwZSBvZiBDRkYgaGludGluZyB1c2VkIGZvciB0aGlzIHRleHQuIENGRiBoaW50aW5nIGRldGVybWluZXMgd2hldGhlciB0aGUgRmxhc2ggcnVudGltZSBmb3JjZXMgc3Ryb25nIGhvcml6b250YWwgc3RlbXMgdG8gZml0IHRvIGEgc3ViIHBpeGVsIGdyaWQgb3Igbm90LiBUaGlzIHByb3BlcnR5IGFwcGxpZXMgb25seSBpZiB0aGUgPGNvZGU+cmVuZGVyaW5nTW9kZTwvY29kZT4gcHJvcGVydHkgaXMgc2V0IHRvIDxjb2RlPlJlbmRlcmluZ01vZGUuQ0ZGPC9jb2RlPiwgYW5kIHRoZSBmb250IGlzIGVtYmVkZGVkICg8Y29kZT5mb250TG9va3VwPC9jb2RlPiBwcm9wZXJ0eSBpcyBzZXQgdG8gPGNvZGU+Rm9udExvb2t1cC5FTUJFRERFRF9DRkY8L2NvZGU+KS4gQXQgc21hbGwgc2NyZWVuIHNpemVzLCBoaW50aW5nIHByb2R1Y2VzIGEgY2xlYXIsIGxlZ2libGUgdGV4dCBmb3IgaHVtYW4gcmVhZGVycy4KICAgICAgICAgKiA8cD5MZWdhbCB2YWx1ZXMgYXJlIENGRkhpbnRpbmcuTk9ORSwgQ0ZGSGludGluZy5IT1JJWk9OVEFMX1NURU0sIEZvcm1hdFZhbHVlLklOSEVSSVQuPC9wPgogICAgICAgICAqIDxwPkRlZmF1bHQgdmFsdWUgaXMgdW5kZWZpbmVkIGluZGljYXRpbmcgbm90IHNldC48L3A+CiAgICAgICAgICogPHA+SWYgdW5kZWZpbmVkIGR1cmluZyB0aGUgY2FzY2FkZSB0aGlzIHByb3BlcnR5IHdpbGwgaW5oZXJpdCBpdHMgdmFsdWUgZnJvbSBhbiBhbmNlc3Rvci4gSWYgbm8gYW5jZXN0b3IgaGFzIHNldCB0aGlzIHByb3BlcnR5LCBpdCB3aWxsIGhhdmUgYSB2YWx1ZSBvZiBDRkZIaW50aW5nLkhPUklaT05UQUxfU1RFTS48L3A+CiAgICAgICAgICogCiAgICAgICAgICogQHRocm93cyBSYW5nZUVycm9yIHdoZW4gc2V0IHZhbHVlIGlzIG5vdCB3aXRoaW4gcmFuZ2UgZm9yIHRoaXMgcHJvcGVydHkKICAgICAgICAgKiAKICAgICAgICAgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKICAgICAgICAgKiBAbGFuZ3ZlcnNpb24gMy4wCiAgICAgICAgICogQHNlZSBmbGFzaC50ZXh0LmVuZ2luZS5DRkZIaW50aW5nCiAgICAgICAgICovCiAgICAgICAgcHVibGljIGZ1bmN0aW9uIGdldCBjZmZIaW50aW5nKCk6KgogICAgICAgIHsgcmV0dXJuIF9zdHlsZXMuY2ZmSGludGluZzsgfQogICAgICAgIHB1YmxpYyBmdW5jdGlvbiBzZXQgY2ZmSGludGluZyh2YWx1ZToqKTp2b2lkCiAgICAgICAgeyBzZXRTdHlsZUJ5UHJvcGVydHkoVGV4dExheW91dEZvcm1hdC5jZmZIaW50aW5nUHJvcGVydHksdmFsdWUpOyB9CgogICAgICAgIFtJbnNwZWN0YWJsZShlbnVtZXJhdGlvbj0iZGV2aWNlLGVtYmVkZGVkQ0ZGLGluaGVyaXQiKV0KICAgICAgICAvKioKICAgICAgICAgKiBGb250IGxvb2t1cCB0byB1c2UuIFNwZWNpZnlpbmcgPGNvZGU+Rm9udExvb2t1cC5ERVZJQ0U8L2NvZGU+IHVzZXMgdGhlIGZvbnRzIGluc3RhbGxlZCBvbiB0aGUgc3lzdGVtIHRoYXQgaXMgcnVubmluZyB0aGUgU1dGIGZpbGUuIERldmljZSBmb250cyByZXN1bHQgaW4gYSBzbWFsbGVyIG1vdmllIHNpemUsIGJ1dCB0ZXh0IGlzIG5vdCBhbHdheXMgcmVuZGVyZWQgdGhlIHNhbWUgYWNyb3NzIGRpZmZlcmVudCBzeXN0ZW1zIGFuZCBwbGF0Zm9ybXMuIFNwZWNpZnlpbmcgPGNvZGU+Rm9udExvb2t1cC5FTUJFRERFRF9DRkY8L2NvZGU+IHVzZXMgZm9udCBvdXRsaW5lcyBlbWJlZGRlZCBpbiB0aGUgcHVibGlzaGVkIFNXRiBmaWxlLiBFbWJlZGRlZCBmb250cyBpbmNyZWFzZSB0aGUgc2l6ZSBvZiB0aGUgU1dGIGZpbGUgKHNvbWV0aW1lcyBkcmFtYXRpY2FsbHkpLCBidXQgdGV4dCBpcyBjb25zaXN0ZW50bHkgZGlzcGxheWVkIGluIHRoZSBjaG9zZW4gZm9udC4KICAgICAgICAgKiA8cD5MZWdhbCB2YWx1ZXMgYXJlIEZvbnRMb29rdXAuREVWSUNFLCBGb250TG9va3VwLkVNQkVEREVEX0NGRiwgRm9ybWF0VmFsdWUuSU5IRVJJVC48L3A+CiAgICAgICAgICogPHA+RGVmYXVsdCB2YWx1ZSBpcyB1bmRlZmluZWQgaW5kaWNhdGluZyBub3Qgc2V0LjwvcD4KICAgICAgICAgKiA8cD5JZiB1bmRlZmluZWQgZHVyaW5nIHRoZSBjYXNjYWRlIHRoaXMgcHJvcGVydHkgd2lsbCBpbmhlcml0IGl0cyB2YWx1ZSBmcm9tIGFuIGFuY2VzdG9yLiBJZiBubyBhbmNlc3RvciBoYXMgc2V0IHRoaXMgcHJvcGVydHksIGl0IHdpbGwgaGF2ZSBhIHZhbHVlIG9mIEZvbnRMb29rdXAuREVWSUNFLjwvcD4KICAgICAgICAgKiAKICAgICAgICAgKiBAdGhyb3dzIFJhbmdlRXJyb3Igd2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eQogICAgICAgICAqIAogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQogICAgICAgICAqIEBsYW5ndmVyc2lvbiAzLjAKICAgICAgICAgKiBAc2VlIGZsYXNoLnRleHQuZW5naW5lLkZvbnRMb29rdXAKICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgZnVuY3Rpb24gZ2V0IGZvbnRMb29rdXAoKToqCiAgICAgICAgeyByZXR1cm4gX3N0eWxlcy5mb250TG9va3VwOyB9CiAgICAgICAgcHVibGljIGZ1bmN0aW9uIHNldCBmb250TG9va3VwKHZhbHVlOiopOnZvaWQKICAgICAgICB7IHNldFN0eWxlQnlQcm9wZXJ0eShUZXh0TGF5b3V0Rm9ybWF0LmZvbnRMb29rdXBQcm9wZXJ0eSx2YWx1ZSk7IH0KCiAgICAgICAgW0luc3BlY3RhYmxlKGVudW1lcmF0aW9uPSJyb3RhdGUwLHJvdGF0ZTE4MCxyb3RhdGUyNzAscm90YXRlOTAsYXV0byxpbmhlcml0IildCiAgICAgICAgLyoqCiAgICAgICAgICogRGV0ZXJtaW5lcyB0aGUgbnVtYmVyIG9mIGRlZ3JlZXMgdG8gcm90YXRlIHRoaXMgdGV4dC4KICAgICAgICAgKiA8cD5MZWdhbCB2YWx1ZXMgYXJlIFRleHRSb3RhdGlvbi5ST1RBVEVfMCwgVGV4dFJvdGF0aW9uLlJPVEFURV8xODAsIFRleHRSb3RhdGlvbi5ST1RBVEVfMjcwLCBUZXh0Um90YXRpb24uUk9UQVRFXzkwLCBUZXh0Um90YXRpb24uQVVUTywgRm9ybWF0VmFsdWUuSU5IRVJJVC48L3A+CiAgICAgICAgICogPHA+RGVmYXVsdCB2YWx1ZSBpcyB1bmRlZmluZWQgaW5kaWNhdGluZyBub3Qgc2V0LjwvcD4KICAgICAgICAgKiA8cD5JZiB1bmRlZmluZWQgZHVyaW5nIHRoZSBjYXNjYWRlIHRoaXMgcHJvcGVydHkgd2lsbCBpbmhlcml0IGl0cyB2YWx1ZSBmcm9tIGFuIGFuY2VzdG9yLiBJZiBubyBhbmNlc3RvciBoYXMgc2V0IHRoaXMgcHJvcGVydHksIGl0IHdpbGwgaGF2ZSBhIHZhbHVlIG9mIFRleHRSb3RhdGlvbi5BVVRPLjwvcD4KICAgICAgICAgKiAKICAgICAgICAgKiBAdGhyb3dzIFJhbmdlRXJyb3Igd2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eQogICAgICAgICAqIAogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQogICAgICAgICAqIEBsYW5ndmVyc2lvbiAzLjAKICAgICAgICAgKiBAc2VlIGZsYXNoLnRleHQuZW5naW5lLlRleHRSb3RhdGlvbgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBmdW5jdGlvbiBnZXQgdGV4dFJvdGF0aW9uKCk6KgogICAgICAgIHsgcmV0dXJuIF9zdHlsZXMudGV4dFJvdGF0aW9uOyB9CiAgICAgICAgcHVibGljIGZ1bmN0aW9uIHNldCB0ZXh0Um90YXRpb24odmFsdWU6Kik6dm9pZAogICAgICAgIHsgc2V0U3R5bGVCeVByb3BlcnR5KFRleHRMYXlvdXRGb3JtYXQudGV4dFJvdGF0aW9uUHJvcGVydHksdmFsdWUpOyB9CgogICAgICAgIC8qKgogICAgICAgICAqIEEgTnVtYmVyIHRoYXQgc3BlY2lmaWVzLCBpbiBwaXhlbHMsIHRoZSBhbW91bnQgdG8gaW5kZW50IHRoZSBmaXJzdCBsaW5lIG9mIHRoZSBwYXJhZ3JhcGguCiAgICAgICAgICogQSBuZWdhdGl2ZSBpbmRlbnQgd2lsbCBwdXNoIHRoZSBsaW5lIGludG8gdGhlIG1hcmdpbiwgYW5kIHBvc3NpYmx5IG91dCBvZiB0aGUgY29udGFpbmVyLgogICAgICAgICAqIDxwPkxlZ2FsIHZhbHVlcyBhcmUgbnVtYmVycyBmcm9tIC04MDAwIHRvIDgwMDAgYW5kIEZvcm1hdFZhbHVlLklOSEVSSVQuPC9wPgogICAgICAgICAqIDxwPkRlZmF1bHQgdmFsdWUgaXMgdW5kZWZpbmVkIGluZGljYXRpbmcgbm90IHNldC48L3A+CiAgICAgICAgICogPHA+SWYgdW5kZWZpbmVkIGR1cmluZyB0aGUgY2FzY2FkZSB0aGlzIHByb3BlcnR5IHdpbGwgaW5oZXJpdCBpdHMgdmFsdWUgZnJvbSBhbiBhbmNlc3Rvci4gSWYgbm8gYW5jZXN0b3IgaGFzIHNldCB0aGlzIHByb3BlcnR5LCBpdCB3aWxsIGhhdmUgYSB2YWx1ZSBvZiAwLjwvcD4KICAgICAgICAgKiAKICAgICAgICAgKiBAdGhyb3dzIFJhbmdlRXJyb3Igd2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eQogICAgICAgICAqIAogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQogICAgICAgICAqIEBsYW5ndmVyc2lvbiAzLjAKICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgZnVuY3Rpb24gZ2V0IHRleHRJbmRlbnQoKToqCiAgICAgICAgeyByZXR1cm4gX3N0eWxlcy50ZXh0SW5kZW50OyB9CiAgICAgICAgcHVibGljIGZ1bmN0aW9uIHNldCB0ZXh0SW5kZW50KHZhbHVlOiopOnZvaWQKICAgICAgICB7IHNldFN0eWxlQnlQcm9wZXJ0eShUZXh0TGF5b3V0Rm9ybWF0LnRleHRJbmRlbnRQcm9wZXJ0eSx2YWx1ZSk7IH0KCiAgICAgICAgLyoqCiAgICAgICAgICogQSBOdW1iZXIgdGhhdCBzcGVjaWZpZXMsIGluIHBpeGVscywgdGhlIGFtb3VudCB0byBpbmRlbnQgdGhlIHBhcmFncmFwaCdzIHN0YXJ0IGVkZ2UuIFJlZmVycyB0byB0aGUgbGVmdCBlZGdlIGluIGxlZnQtdG8tcmlnaHQgdGV4dCBhbmQgdGhlIHJpZ2h0IGVkZ2UgaW4gcmlnaHQtdG8tbGVmdCB0ZXh0LiAKICAgICAgICAgKiA8cD5MZWdhbCB2YWx1ZXMgYXJlIG51bWJlcnMgZnJvbSAwIHRvIDgwMDAgYW5kIEZvcm1hdFZhbHVlLklOSEVSSVQuPC9wPgogICAgICAgICAqIDxwPkRlZmF1bHQgdmFsdWUgaXMgdW5kZWZpbmVkIGluZGljYXRpbmcgbm90IHNldC48L3A+CiAgICAgICAgICogPHA+SWYgdW5kZWZpbmVkIGR1cmluZyB0aGUgY2FzY2FkZSB0aGlzIHByb3BlcnR5IHdpbGwgaW5oZXJpdCBpdHMgdmFsdWUgZnJvbSBhbiBhbmNlc3Rvci4gSWYgbm8gYW5jZXN0b3IgaGFzIHNldCB0aGlzIHByb3BlcnR5LCBpdCB3aWxsIGhhdmUgYSB2YWx1ZSBvZiAwLjwvcD4KICAgICAgICAgKiAKICAgICAgICAgKiBAdGhyb3dzIFJhbmdlRXJyb3Igd2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eQogICAgICAgICAqIAogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQogICAgICAgICAqIEBsYW5ndmVyc2lvbiAzLjAKICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgZnVuY3Rpb24gZ2V0IHBhcmFncmFwaFN0YXJ0SW5kZW50KCk6KgogICAgICAgIHsgcmV0dXJuIF9zdHlsZXMucGFyYWdyYXBoU3RhcnRJbmRlbnQ7IH0KICAgICAgICBwdWJsaWMgZnVuY3Rpb24gc2V0IHBhcmFncmFwaFN0YXJ0SW5kZW50KHZhbHVlOiopOnZvaWQKICAgICAgICB7IHNldFN0eWxlQnlQcm9wZXJ0eShUZXh0TGF5b3V0Rm9ybWF0LnBhcmFncmFwaFN0YXJ0SW5kZW50UHJvcGVydHksdmFsdWUpOyB9CgogICAgICAgIC8qKgogICAgICAgICAqIEEgTnVtYmVyIHRoYXQgc3BlY2lmaWVzLCBpbiBwaXhlbHMsIHRoZSBhbW91bnQgdG8gaW5kZW50IHRoZSBwYXJhZ3JhcGgncyBlbmQgZWRnZS4gUmVmZXJzIHRvIHRoZSByaWdodCBlZGdlIGluIGxlZnQtdG8tcmlnaHQgdGV4dCBhbmQgdGhlIGxlZnQgZWRnZSBpbiByaWdodC10by1sZWZ0IHRleHQuIAogICAgICAgICAqIDxwPkxlZ2FsIHZhbHVlcyBhcmUgbnVtYmVycyBmcm9tIDAgdG8gODAwMCBhbmQgRm9ybWF0VmFsdWUuSU5IRVJJVC48L3A+CiAgICAgICAgICogPHA+RGVmYXVsdCB2YWx1ZSBpcyB1bmRlZmluZWQgaW5kaWNhdGluZyBub3Qgc2V0LjwvcD4KICAgICAgICAgKiA8cD5JZiB1bmRlZmluZWQgZHVyaW5nIHRoZSBjYXNjYWRlIHRoaXMgcHJvcGVydHkgd2lsbCBpbmhlcml0IGl0cyB2YWx1ZSBmcm9tIGFuIGFuY2VzdG9yLiBJZiBubyBhbmNlc3RvciBoYXMgc2V0IHRoaXMgcHJvcGVydHksIGl0IHdpbGwgaGF2ZSBhIHZhbHVlIG9mIDAuPC9wPgogICAgICAgICAqIAogICAgICAgICAqIEB0aHJvd3MgUmFuZ2VFcnJvciB3aGVuIHNldCB2YWx1ZSBpcyBub3Qgd2l0aGluIHJhbmdlIGZvciB0aGlzIHByb3BlcnR5CiAgICAgICAgICogCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gRmxhc2ggMTAKICAgICAgICAgKiBAcGxheWVydmVyc2lvbiBBSVIgMS41CiAgICAgICAgICogQGxhbmd2ZXJzaW9uIDMuMAogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBmdW5jdGlvbiBnZXQgcGFyYWdyYXBoRW5kSW5kZW50KCk6KgogICAgICAgIHsgcmV0dXJuIF9zdHlsZXMucGFyYWdyYXBoRW5kSW5kZW50OyB9CiAgICAgICAgcHVibGljIGZ1bmN0aW9uIHNldCBwYXJhZ3JhcGhFbmRJbmRlbnQodmFsdWU6Kik6dm9pZAogICAgICAgIHsgc2V0U3R5bGVCeVByb3BlcnR5KFRleHRMYXlvdXRGb3JtYXQucGFyYWdyYXBoRW5kSW5kZW50UHJvcGVydHksdmFsdWUpOyB9CgogICAgICAgIC8qKgogICAgICAgICAqIEEgTnVtYmVyIHRoYXQgc3BlY2lmaWVzIHRoZSBhbW91bnQgb2Ygc3BhY2UsIGluIHBpeGVscywgdG8gbGVhdmUgYmVmb3JlIHRoZSBwYXJhZ3JhcGguIAogICAgICAgICAqIENvbGxhcHNlcyBpbiB0YW5kZW0gd2l0aCA8Y29kZT5wYXJhZ3JhcGhTcGFjZUFmdGVyPC9jb2RlPi4KICAgICAgICAgKiA8cD5MZWdhbCB2YWx1ZXMgYXJlIG51bWJlcnMgZnJvbSAwIHRvIDgwMDAgYW5kIEZvcm1hdFZhbHVlLklOSEVSSVQuPC9wPgogICAgICAgICAqIDxwPkRlZmF1bHQgdmFsdWUgaXMgdW5kZWZpbmVkIGluZGljYXRpbmcgbm90IHNldC48L3A+CiAgICAgICAgICogPHA+SWYgdW5kZWZpbmVkIGR1cmluZyB0aGUgY2FzY2FkZSB0aGlzIHByb3BlcnR5IHdpbGwgaW5oZXJpdCBpdHMgdmFsdWUgZnJvbSBhbiBhbmNlc3Rvci4gSWYgbm8gYW5jZXN0b3IgaGFzIHNldCB0aGlzIHByb3BlcnR5LCBpdCB3aWxsIGhhdmUgYSB2YWx1ZSBvZiAwLjwvcD4KICAgICAgICAgKiAKICAgICAgICAgKiBAdGhyb3dzIFJhbmdlRXJyb3Igd2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eQogICAgICAgICAqIAogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQogICAgICAgICAqIEBsYW5ndmVyc2lvbiAzLjAKICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgZnVuY3Rpb24gZ2V0IHBhcmFncmFwaFNwYWNlQmVmb3JlKCk6KgogICAgICAgIHsgcmV0dXJuIF9zdHlsZXMucGFyYWdyYXBoU3BhY2VCZWZvcmU7IH0KICAgICAgICBwdWJsaWMgZnVuY3Rpb24gc2V0IHBhcmFncmFwaFNwYWNlQmVmb3JlKHZhbHVlOiopOnZvaWQKICAgICAgICB7IHNldFN0eWxlQnlQcm9wZXJ0eShUZXh0TGF5b3V0Rm9ybWF0LnBhcmFncmFwaFNwYWNlQmVmb3JlUHJvcGVydHksdmFsdWUpOyB9CgogICAgICAgIC8qKgogICAgICAgICAqIEEgTnVtYmVyIHRoYXQgc3BlY2lmaWVzIHRoZSBhbW91bnQgb2Ygc3BhY2UsIGluIHBpeGVscywgdG8gbGVhdmUgYWZ0ZXIgdGhlIHBhcmFncmFwaC4KICAgICAgICAgKiBDb2xsYXBzZXMgaW4gdGFuZGVtIHdpdGggIDxjb2RlPnBhcmFncmFwaFNwYWNlQmVmb3JlPC9jb2RlPi4KICAgICAgICAgKiA8cD5MZWdhbCB2YWx1ZXMgYXJlIG51bWJlcnMgZnJvbSAwIHRvIDgwMDAgYW5kIEZvcm1hdFZhbHVlLklOSEVSSVQuPC9wPgogICAgICAgICAqIDxwPkRlZmF1bHQgdmFsdWUgaXMgdW5kZWZpbmVkIGluZGljYXRpbmcgbm90IHNldC48L3A+CiAgICAgICAgICogPHA+SWYgdW5kZWZpbmVkIGR1cmluZyB0aGUgY2FzY2FkZSB0aGlzIHByb3BlcnR5IHdpbGwgaW5oZXJpdCBpdHMgdmFsdWUgZnJvbSBhbiBhbmNlc3Rvci4gSWYgbm8gYW5jZXN0b3IgaGFzIHNldCB0aGlzIHByb3BlcnR5LCBpdCB3aWxsIGhhdmUgYSB2YWx1ZSBvZiAwLjwvcD4KICAgICAgICAgKiAKICAgICAgICAgKiBAdGhyb3dzIFJhbmdlRXJyb3Igd2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eQogICAgICAgICAqIAogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQogICAgICAgICAqIEBsYW5ndmVyc2lvbiAzLjAKICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgZnVuY3Rpb24gZ2V0IHBhcmFncmFwaFNwYWNlQWZ0ZXIoKToqCiAgICAgICAgeyByZXR1cm4gX3N0eWxlcy5wYXJhZ3JhcGhTcGFjZUFmdGVyOyB9CiAgICAgICAgcHVibGljIGZ1bmN0aW9uIHNldCBwYXJhZ3JhcGhTcGFjZUFmdGVyKHZhbHVlOiopOnZvaWQKICAgICAgICB7IHNldFN0eWxlQnlQcm9wZXJ0eShUZXh0TGF5b3V0Rm9ybWF0LnBhcmFncmFwaFNwYWNlQWZ0ZXJQcm9wZXJ0eSx2YWx1ZSk7IH0KCiAgICAgICAgW0luc3BlY3RhYmxlKGVudW1lcmF0aW9uPSJsZWZ0LHJpZ2h0LGNlbnRlcixqdXN0aWZ5LHN0YXJ0LGVuZCxpbmhlcml0IildCiAgICAgICAgLyoqCiAgICAgICAgICogQWxpZ25tZW50IG9mIGxpbmVzIGluIHRoZSBwYXJhZ3JhcGggcmVsYXRpdmUgdG8gdGhlIGNvbnRhaW5lci4KICAgICAgICAgKiA8Y29kZT5UZXh0QWxpZ24uTEVGVDwvY29kZT4gYWxpZ25zIGxpbmVzIGFsb25nIHRoZSBsZWZ0IGVkZ2Ugb2YgdGhlIGNvbnRhaW5lci4gPGNvZGU+VGV4dEFsaWduLlJJR0hUPC9jb2RlPiBhbGlnbnMgb24gdGhlIHJpZ2h0IGVkZ2UuIDxjb2RlPlRleHRBbGlnbi5DRU5URVI8L2NvZGU+IHBvc2l0aW9ucyB0aGUgbGluZSBlcXVpZGlzdGFudCBmcm9tIHRoZSBsZWZ0IGFuZCByaWdodCBlZGdlcy4gPGNvZGU+VGV4dEFsaWduLkpVU1RJRlk8L2NvZGU+IHNwcmVhZHMgdGhlIGxpbmVzIG91dCBzbyB0aGV5IGZpbGwgdGhlIHNwYWNlLiA8Y29kZT5UZXh0QWxpZ24uU1RBUlQ8L2NvZGU+IGlzIGVxdWl2YWxlbnQgdG8gc2V0dGluZyBsZWZ0IGluIGxlZnQtdG8tcmlnaHQgdGV4dCwgb3IgcmlnaHQgaW4gcmlnaHQtdG8tbGVmdCB0ZXh0LiA8Y29kZT5UZXh0QWxpZ24uRU5EPC9jb2RlPiBpcyBlcXVpdmFsZW50IHRvIHNldHRpbmcgcmlnaHQgaW4gbGVmdC10by1yaWdodCB0ZXh0LCBvciBsZWZ0IGluIHJpZ2h0LXRvLWxlZnQgdGV4dC4KICAgICAgICAgKiA8cD5MZWdhbCB2YWx1ZXMgYXJlIFRleHRBbGlnbi5MRUZULCBUZXh0QWxpZ24uUklHSFQsIFRleHRBbGlnbi5DRU5URVIsIFRleHRBbGlnbi5KVVNUSUZZLCBUZXh0QWxpZ24uU1RBUlQsIFRleHRBbGlnbi5FTkQsIEZvcm1hdFZhbHVlLklOSEVSSVQuPC9wPgogICAgICAgICAqIDxwPkRlZmF1bHQgdmFsdWUgaXMgdW5kZWZpbmVkIGluZGljYXRpbmcgbm90IHNldC48L3A+CiAgICAgICAgICogPHA+SWYgdW5kZWZpbmVkIGR1cmluZyB0aGUgY2FzY2FkZSB0aGlzIHByb3BlcnR5IHdpbGwgaW5oZXJpdCBpdHMgdmFsdWUgZnJvbSBhbiBhbmNlc3Rvci4gSWYgbm8gYW5jZXN0b3IgaGFzIHNldCB0aGlzIHByb3BlcnR5LCBpdCB3aWxsIGhhdmUgYSB2YWx1ZSBvZiBUZXh0QWxpZ24uU1RBUlQuPC9wPgogICAgICAgICAqIAogICAgICAgICAqIEB0aHJvd3MgUmFuZ2VFcnJvciB3aGVuIHNldCB2YWx1ZSBpcyBub3Qgd2l0aGluIHJhbmdlIGZvciB0aGlzIHByb3BlcnR5CiAgICAgICAgICogCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gRmxhc2ggMTAKICAgICAgICAgKiBAcGxheWVydmVyc2lvbiBBSVIgMS41CiAgICAgICAgICogQGxhbmd2ZXJzaW9uIDMuMAogICAgICAgICAqIEBzZWUgZmxhc2h4LnRleHRMYXlvdXQuZm9ybWF0cy5UZXh0QWxpZ24KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgZnVuY3Rpb24gZ2V0IHRleHRBbGlnbigpOioKICAgICAgICB7IHJldHVybiBfc3R5bGVzLnRleHRBbGlnbjsgfQogICAgICAgIHB1YmxpYyBmdW5jdGlvbiBzZXQgdGV4dEFsaWduKHZhbHVlOiopOnZvaWQKICAgICAgICB7IHNldFN0eWxlQnlQcm9wZXJ0eShUZXh0TGF5b3V0Rm9ybWF0LnRleHRBbGlnblByb3BlcnR5LHZhbHVlKTsgfQoKICAgICAgICBbSW5zcGVjdGFibGUoZW51bWVyYXRpb249ImxlZnQscmlnaHQsY2VudGVyLGp1c3RpZnksc3RhcnQsZW5kLGluaGVyaXQiKV0KICAgICAgICAvKioKICAgICAgICAgKiBBbGlnbm1lbnQgb2YgdGhlIGxhc3QgKG9yIG9ubHkpIGxpbmUgaW4gdGhlIHBhcmFncmFwaCByZWxhdGl2ZSB0byB0aGUgY29udGFpbmVyIGluIGp1c3RpZmllZCB0ZXh0LgogICAgICAgICAqIElmIDxjb2RlPnRleHRBbGlnbjwvY29kZT4gaXMgc2V0IHRvIDxjb2RlPlRleHRBbGlnbi5KVVNUSUZZPC9jb2RlPiwgPGNvZGU+dGV4dEFsaWduTGFzdDwvY29kZT4gc3BlY2lmaWVzIGhvdyB0aGUgbGFzdCBsaW5lIChvciBvbmx5IGxpbmUsIGlmIHRoaXMgaXMgYSBvbmUgbGluZSBibG9jaykgaXMgYWxpZ25lZC4gVmFsdWVzIGFyZSBzaW1pbGFyIHRvIDxjb2RlPnRleHRBbGlnbjwvY29kZT4uCiAgICAgICAgICogPHA+TGVnYWwgdmFsdWVzIGFyZSBUZXh0QWxpZ24uTEVGVCwgVGV4dEFsaWduLlJJR0hULCBUZXh0QWxpZ24uQ0VOVEVSLCBUZXh0QWxpZ24uSlVTVElGWSwgVGV4dEFsaWduLlNUQVJULCBUZXh0QWxpZ24uRU5ELCBGb3JtYXRWYWx1ZS5JTkhFUklULjwvcD4KICAgICAgICAgKiA8cD5EZWZhdWx0IHZhbHVlIGlzIHVuZGVmaW5lZCBpbmRpY2F0aW5nIG5vdCBzZXQuPC9wPgogICAgICAgICAqIDxwPklmIHVuZGVmaW5lZCBkdXJpbmcgdGhlIGNhc2NhZGUgdGhpcyBwcm9wZXJ0eSB3aWxsIGluaGVyaXQgaXRzIHZhbHVlIGZyb20gYW4gYW5jZXN0b3IuIElmIG5vIGFuY2VzdG9yIGhhcyBzZXQgdGhpcyBwcm9wZXJ0eSwgaXQgd2lsbCBoYXZlIGEgdmFsdWUgb2YgVGV4dEFsaWduLlNUQVJULjwvcD4KICAgICAgICAgKiAKICAgICAgICAgKiBAdGhyb3dzIFJhbmdlRXJyb3Igd2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eQogICAgICAgICAqIAogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQogICAgICAgICAqIEBsYW5ndmVyc2lvbiAzLjAKICAgICAgICAgKiBAc2VlIGZsYXNoeC50ZXh0TGF5b3V0LmZvcm1hdHMuVGV4dEFsaWduCiAgICAgICAgICovCiAgICAgICAgcHVibGljIGZ1bmN0aW9uIGdldCB0ZXh0QWxpZ25MYXN0KCk6KgogICAgICAgIHsgcmV0dXJuIF9zdHlsZXMudGV4dEFsaWduTGFzdDsgfQogICAgICAgIHB1YmxpYyBmdW5jdGlvbiBzZXQgdGV4dEFsaWduTGFzdCh2YWx1ZToqKTp2b2lkCiAgICAgICAgeyBzZXRTdHlsZUJ5UHJvcGVydHkoVGV4dExheW91dEZvcm1hdC50ZXh0QWxpZ25MYXN0UHJvcGVydHksdmFsdWUpOyB9CgogICAgICAgIFtJbnNwZWN0YWJsZShlbnVtZXJhdGlvbj0iaW50ZXJXb3JkLGRpc3RyaWJ1dGUsaW5oZXJpdCIpXQogICAgICAgIC8qKgogICAgICAgICAqIFNwZWNpZmllcyBvcHRpb25zIGZvciBqdXN0aWZ5aW5nIHRleHQuCiAgICAgICAgICogRGVmYXVsdCB2YWx1ZSBpcyA8Y29kZT5UZXh0SnVzdGlmeS5JTlRFUl9XT1JEPC9jb2RlPiwgbWVhbmluZyB0aGF0IGV4dHJhIHNwYWNlIGlzIGFkZGVkIHRvIHRoZSBzcGFjZSBjaGFyYWN0ZXJzLiA8Y29kZT5UZXh0SnVzdGlmeS5ESVNUUklCVVRFPC9jb2RlPiBhZGRzIGV4dHJhIHNwYWNlIHRvIHNwYWNlIGNoYXJhY3RlcnMgYW5kIGJldHdlZW4gaW5kaXZpZHVhbCBsZXR0ZXJzLiBVc2VkIG9ubHkgaW4gY29uanVuY3Rpb24gd2l0aCBhIDxjb2RlPmp1c3RpZmljYXRpb25SdWxlPC9jb2RlPiB2YWx1ZSBvZiA8Y29kZT5KdXN0aWZpY2F0aW9uUnVsZS5TUEFDRTwvY29kZT4uCiAgICAgICAgICogPHA+TGVnYWwgdmFsdWVzIGFyZSBUZXh0SnVzdGlmeS5JTlRFUl9XT1JELCBUZXh0SnVzdGlmeS5ESVNUUklCVVRFLCBGb3JtYXRWYWx1ZS5JTkhFUklULjwvcD4KICAgICAgICAgKiA8cD5EZWZhdWx0IHZhbHVlIGlzIHVuZGVmaW5lZCBpbmRpY2F0aW5nIG5vdCBzZXQuPC9wPgogICAgICAgICAqIDxwPklmIHVuZGVmaW5lZCBkdXJpbmcgdGhlIGNhc2NhZGUsIHRoaXMgcHJvcGVydHkgaW5oZXJpdHMgaXRzIHZhbHVlIGZyb20gYW4gYW5jZXN0b3IuIElmIG5vIGFuY2VzdG9yIGhhcyBzZXQgdGhpcyBwcm9wZXJ0eSwgaXQgd2lsbCBoYXZlIGEgdmFsdWUgb2YgVGV4dEp1c3RpZnkuSU5URVJfV09SRC48L3A+CiAgICAgICAgICogCiAgICAgICAgICogQHRocm93cyBSYW5nZUVycm9yIHdoZW4gc2V0IHZhbHVlIGlzIG5vdCB3aXRoaW4gcmFuZ2UgZm9yIHRoaXMgcHJvcGVydHkKICAgICAgICAgKiAKICAgICAgICAgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKICAgICAgICAgKiBAbGFuZ3ZlcnNpb24gMy4wCiAgICAgICAgICogQHNlZSBmbGFzaHgudGV4dExheW91dC5mb3JtYXRzLlRleHRKdXN0aWZ5CiAgICAgICAgICovCiAgICAgICAgcHVibGljIGZ1bmN0aW9uIGdldCB0ZXh0SnVzdGlmeSgpOioKICAgICAgICB7IHJldHVybiBfc3R5bGVzLnRleHRKdXN0aWZ5OyB9CiAgICAgICAgcHVibGljIGZ1bmN0aW9uIHNldCB0ZXh0SnVzdGlmeSh2YWx1ZToqKTp2b2lkCiAgICAgICAgeyBzZXRTdHlsZUJ5UHJvcGVydHkoVGV4dExheW91dEZvcm1hdC50ZXh0SnVzdGlmeVByb3BlcnR5LHZhbHVlKTsgfQoKICAgICAgICBbSW5zcGVjdGFibGUoZW51bWVyYXRpb249ImVhc3RBc2lhbixzcGFjZSxhdXRvLGluaGVyaXQiKV0KICAgICAgICAvKioKICAgICAgICAgKiBSdWxlIHVzZWQgdG8ganVzdGlmeSB0ZXh0IGluIGEgcGFyYWdyYXBoLgogICAgICAgICAqIERlZmF1bHQgdmFsdWUgaXMgPGNvZGU+Rm9ybWF0VmFsdWUuQVVUTzwvY29kZT4sIHdoaWNoIGp1c3RpZmllcyB0ZXh0IGJhc2VkIG9uIHRoZSBwYXJhZ3JhcGgncyA8Y29kZT5sb2NhbGU8L2NvZGU+IHByb3BlcnR5LiBGb3IgYWxsIGxhbmd1YWdlcyBleGNlcHQgSmFwYW5lc2UgYW5kIENoaW5lc2UsIDxjb2RlPkZvcm1hdFZhbHVlLkFVVE88L2NvZGU+IGJlY29tZXMgPGNvZGU+SnVzdGlmaWNhdGlvblJ1bGUuU1BBQ0U8L2NvZGU+LCB3aGljaCBhZGRzIGV4dHJhIHNwYWNlIHRvIHRoZSBzcGFjZSBjaGFyYWN0ZXJzLiAgRm9yIEphcGFuZXNlIGFuZCBDaGluZXNlLCA8Y29kZT5Gb3JtYXRWYWx1ZS5BVVRPPC9jb2RlPiBiZWNvbWVzIDxjb2RlPkp1c3RmaWNhdGlvblJ1bGUuRUFTVF9BU0lBTjwvY29kZT4uIEluIHBhcnQsIGp1c3RpZmljYXRpb24gY2hhbmdlcyB0aGUgc3BhY2luZyBvZiBwdW5jdHVhdGlvbi4gSW4gUm9tYW4gdGV4dCB0aGUgY29tbWEgYW5kIEphcGFuZXNlIHBlcmlvZHMgdGFrZSBhIGZ1bGwgY2hhcmFjdGVyJ3Mgd2lkdGggYnV0IGluIEVhc3QgQXNpYW4gdGV4dCBvbmx5IGhhbGYgb2YgYSBjaGFyYWN0ZXIncyB3aWR0aC4gQWxzbywgaW4gdGhlIEVhc3QgQXNpYW4gdGV4dCB0aGUgc3BhY2luZyBiZXR3ZWVuIHNlcXVlbnRpYWwgcHVuY3R1YXRpb24gbWFya3MgYmVjb21lcyB0aWdodGVyLCBvYmV5aW5nIHRyYWRpdGlvbmFsIEVhc3QgQXNpYW4gdHlwb2dyYXBoaWMgY29udmVudGlvbnMuIE5vdGUsIHRvbywgaW4gdGhlIGV4YW1wbGUgYmVsb3cgdGhlIGxlYWRpbmcgdGhhdCBpcyBhcHBsaWVkIHRvIHRoZSBzZWNvbmQgbGluZSBvZiB0aGUgcGFyYWdyYXBocy4gSW4gdGhlIEVhc3QgQXNpYW4gdmVyc2lvbiwgdGhlIGxhc3QgdHdvIGxpbmVzIHB1c2ggbGVmdC4gSW4gdGhlIFJvbWFuIHZlcnNpb24sIHRoZSBzZWNvbmQgYW5kIGZvbGxvd2luZyBsaW5lcyBwdXNoIGxlZnQuPHA+PGltZyBzcmM9Jy4uLy4uLy4uL2ltYWdlcy90ZXh0TGF5b3V0X2p1c3RpZmljYXRpb25ydWxlLnBuZycgYWx0PSdqdXN0aWZpY2F0aW9uUnVsZScgLz48L3A+CiAgICAgICAgICogPHA+TGVnYWwgdmFsdWVzIGFyZSBKdXN0aWZpY2F0aW9uUnVsZS5FQVNUX0FTSUFOLCBKdXN0aWZpY2F0aW9uUnVsZS5TUEFDRSwgRm9ybWF0VmFsdWUuQVVUTywgRm9ybWF0VmFsdWUuSU5IRVJJVC48L3A+CiAgICAgICAgICogPHA+RGVmYXVsdCB2YWx1ZSBpcyB1bmRlZmluZWQgaW5kaWNhdGluZyBub3Qgc2V0LjwvcD4KICAgICAgICAgKiA8cD5JZiB1bmRlZmluZWQgZHVyaW5nIHRoZSBjYXNjYWRlLCB0aGlzIHByb3BlcnR5IGluaGVyaXRzIGl0cyB2YWx1ZSBmcm9tIGFuIGFuY2VzdG9yLiBJZiBubyBhbmNlc3RvciBoYXMgc2V0IHRoaXMgcHJvcGVydHksIGl0IHdpbGwgaGF2ZSBhIHZhbHVlIG9mIEZvcm1hdFZhbHVlLkFVVE8uPC9wPgogICAgICAgICAqIAogICAgICAgICAqIEB0aHJvd3MgUmFuZ2VFcnJvciB3aGVuIHNldCB2YWx1ZSBpcyBub3Qgd2l0aGluIHJhbmdlIGZvciB0aGlzIHByb3BlcnR5CiAgICAgICAgICogCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gRmxhc2ggMTAKICAgICAgICAgKiBAcGxheWVydmVyc2lvbiBBSVIgMS41CiAgICAgICAgICogQGxhbmd2ZXJzaW9uIDMuMAogICAgICAgICAqIEBzZWUgZmxhc2h4LnRleHRMYXlvdXQuZm9ybWF0cy5KdXN0aWZpY2F0aW9uUnVsZQogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBmdW5jdGlvbiBnZXQganVzdGlmaWNhdGlvblJ1bGUoKToqCiAgICAgICAgeyByZXR1cm4gX3N0eWxlcy5qdXN0aWZpY2F0aW9uUnVsZTsgfQogICAgICAgIHB1YmxpYyBmdW5jdGlvbiBzZXQganVzdGlmaWNhdGlvblJ1bGUodmFsdWU6Kik6dm9pZAogICAgICAgIHsgc2V0U3R5bGVCeVByb3BlcnR5KFRleHRMYXlvdXRGb3JtYXQuanVzdGlmaWNhdGlvblJ1bGVQcm9wZXJ0eSx2YWx1ZSk7IH0KCiAgICAgICAgW0luc3BlY3RhYmxlKGVudW1lcmF0aW9uPSJwcmlvcml0aXplTGVhc3RBZGp1c3RtZW50LHB1c2hJbktpbnNva3UscHVzaE91dE9ubHksYXV0byxpbmhlcml0IildCiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIHN0eWxlIHVzZWQgZm9yIGp1c3RpZmljYXRpb24gb2YgdGhlIHBhcmFncmFwaC4gVXNlZCBvbmx5IGluIGNvbmp1bmN0aW9uIHdpdGggYSA8Y29kZT5qdXN0aWZpY2F0aW9uUnVsZTwvY29kZT4gc2V0dGluZyBvZiA8Y29kZT5KdXN0aWZpY2F0aW9uUnVsZS5FQVNUX0FTSUFOPC9jb2RlPi4KICAgICAgICAgKiBEZWZhdWx0IHZhbHVlIG9mIDxjb2RlPkZvcm1hdFZhbHVlLkFVVE88L2NvZGU+IGlzIHJlc29sdmVkIHRvIDxjb2RlPkp1c3RpZmljYXRpb25TdHlsZS5QVVNIX0lOX0tJTlNPS1U8L2NvZGU+IGZvciBhbGwgbG9jYWxlcy4gIFRoZSBjb25zdGFudHMgZGVmaW5lZCBieSB0aGUgSnVzdGlmaWNhdGlvblN0eWxlIGNsYXNzIHNwZWNpZnkgb3B0aW9ucyBmb3IgaGFuZGxpbmcga2luc29rdSBjaGFyYWN0ZXJzLCB3aGljaCBhcmUgSmFwYW5lc2UgY2hhcmFjdGVycyB0aGF0IGNhbm5vdCBhcHBlYXIgYXQgZWl0aGVyIHRoZSBiZWdpbm5pbmcgb3IgZW5kIG9mIGEgbGluZS4gSWYgeW91IHdhbnQgbG9vc2VyIHRleHQsIHNwZWNpZnkgPGNvZGU+SnVzdGlmaWNhdGlvblN0eWxlLlBVU0gtT1VULU9OTFk8L2NvZGU+LiBJZiB5b3Ugd2FudCBiZWhhdmlvciB0aGF0IGlzIGxpa2Ugd2hhdCB5b3UgZ2V0IHdpdGggdGhlICA8Y29kZT5qdXN0aWZpY2F0aW9uUnVsZTwvY29kZT4gb2YgPGNvZGU+SnVzdGlmaWNhdGlvblJ1bGUuU1BBQ0U8L2NvZGU+LCB1c2UgPGNvZGU+SnVzdGlmaWNhdGlvblN0eWxlLlBSSU9SSVRJWkUtTEVBU1QtQURKVVNUTUVOVDwvY29kZT4uCiAgICAgICAgICogPHA+TGVnYWwgdmFsdWVzIGFyZSBKdXN0aWZpY2F0aW9uU3R5bGUuUFJJT1JJVElaRV9MRUFTVF9BREpVU1RNRU5ULCBKdXN0aWZpY2F0aW9uU3R5bGUuUFVTSF9JTl9LSU5TT0tVLCBKdXN0aWZpY2F0aW9uU3R5bGUuUFVTSF9PVVRfT05MWSwgRm9ybWF0VmFsdWUuQVVUTywgRm9ybWF0VmFsdWUuSU5IRVJJVC48L3A+CiAgICAgICAgICogPHA+RGVmYXVsdCB2YWx1ZSBpcyB1bmRlZmluZWQgaW5kaWNhdGluZyBub3Qgc2V0LjwvcD4KICAgICAgICAgKiA8cD5JZiB1bmRlZmluZWQgZHVyaW5nIHRoZSBjYXNjYWRlLCB0aGlzIHByb3BlcnR5IGluaGVyaXRzIGl0cyB2YWx1ZSBmcm9tIGFuIGFuY2VzdG9yLiBJZiBubyBhbmNlc3RvciBoYXMgc2V0IHRoaXMgcHJvcGVydHksIGl0IHdpbGwgaGF2ZSBhIHZhbHVlIG9mIEZvcm1hdFZhbHVlLkFVVE8uPC9wPgogICAgICAgICAqIAogICAgICAgICAqIEB0aHJvd3MgUmFuZ2VFcnJvciB3aGVuIHNldCB2YWx1ZSBpcyBub3Qgd2l0aGluIHJhbmdlIGZvciB0aGlzIHByb3BlcnR5CiAgICAgICAgICogCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gRmxhc2ggMTAKICAgICAgICAgKiBAcGxheWVydmVyc2lvbiBBSVIgMS41CiAgICAgICAgICogQGxhbmd2ZXJzaW9uIDMuMAogICAgICAgICAqIEBzZWUgZmxhc2gudGV4dC5lbmdpbmUuSnVzdGlmaWNhdGlvblN0eWxlCiAgICAgICAgICovCiAgICAgICAgcHVibGljIGZ1bmN0aW9uIGdldCBqdXN0aWZpY2F0aW9uU3R5bGUoKToqCiAgICAgICAgeyByZXR1cm4gX3N0eWxlcy5qdXN0aWZpY2F0aW9uU3R5bGU7IH0KICAgICAgICBwdWJsaWMgZnVuY3Rpb24gc2V0IGp1c3RpZmljYXRpb25TdHlsZSh2YWx1ZToqKTp2b2lkCiAgICAgICAgeyBzZXRTdHlsZUJ5UHJvcGVydHkoVGV4dExheW91dEZvcm1hdC5qdXN0aWZpY2F0aW9uU3R5bGVQcm9wZXJ0eSx2YWx1ZSk7IH0KCiAgICAgICAgW0luc3BlY3RhYmxlKGVudW1lcmF0aW9uPSJsdHIscnRsLGluaGVyaXQiKV0KICAgICAgICAvKioKICAgICAgICAgKiBTcGVjaWZpZXMgdGhlIGRlZmF1bHQgYmlkaXJlY3Rpb25hbCBlbWJlZGRpbmcgbGV2ZWwgb2YgdGhlIHRleHQgaW4gdGhlIHRleHQgYmxvY2suIAogICAgICAgICAqIExlZnQtdG8tcmlnaHQgcmVhZGluZyBvcmRlciwgYXMgaW4gTGF0aW4tc3R5bGUgc2NyaXB0cywgb3IgcmlnaHQtdG8tbGVmdCByZWFkaW5nIG9yZGVyLCBhcyBpbiBBcmFiaWMgb3IgSGVicmV3LiBUaGlzIHByb3BlcnR5IGFsc28gYWZmZWN0cyBjb2x1bW4gZGlyZWN0aW9uIHdoZW4gaXQgaXMgYXBwbGllZCBhdCB0aGUgY29udGFpbmVyIGxldmVsLiBDb2x1bW5zIGNhbiBiZSBlaXRoZXIgbGVmdC10by1yaWdodCBvciByaWdodC10by1sZWZ0LCBqdXN0IGxpa2UgdGV4dC4gQmVsb3cgYXJlIHNvbWUgZXhhbXBsZXM6PHA+PGltZyBzcmM9Jy4uLy4uLy4uL2ltYWdlcy90ZXh0TGF5b3V0X2RpcmVjdGlvbi5naWYnIGFsdD0nZGlyZWN0aW9uJyAvPjwvcD4KICAgICAgICAgKiA8cD5MZWdhbCB2YWx1ZXMgYXJlIERpcmVjdGlvbi5MVFIsIERpcmVjdGlvbi5SVEwsIEZvcm1hdFZhbHVlLklOSEVSSVQuPC9wPgogICAgICAgICAqIDxwPkRlZmF1bHQgdmFsdWUgaXMgdW5kZWZpbmVkIGluZGljYXRpbmcgbm90IHNldC48L3A+CiAgICAgICAgICogPHA+SWYgdW5kZWZpbmVkIGR1cmluZyB0aGUgY2FzY2FkZSwgdGhpcyBwcm9wZXJ0eSBpbmhlcml0cyBpdHMgdmFsdWUgZnJvbSBhbiBhbmNlc3Rvci4gSWYgbm8gYW5jZXN0b3IgaGFzIHNldCB0aGlzIHByb3BlcnR5LCBpdCB3aWxsIGhhdmUgYSB2YWx1ZSBvZiBEaXJlY3Rpb24uTFRSLjwvcD4KICAgICAgICAgKiAKICAgICAgICAgKiBAdGhyb3dzIFJhbmdlRXJyb3Igd2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eQogICAgICAgICAqIAogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQogICAgICAgICAqIEBsYW5ndmVyc2lvbiAzLjAKICAgICAgICAgKiBAc2VlIGZsYXNoeC50ZXh0TGF5b3V0LmZvcm1hdHMuRGlyZWN0aW9uCiAgICAgICAgICovCiAgICAgICAgcHVibGljIGZ1bmN0aW9uIGdldCBkaXJlY3Rpb24oKToqCiAgICAgICAgeyByZXR1cm4gX3N0eWxlcy5kaXJlY3Rpb247IH0KICAgICAgICBwdWJsaWMgZnVuY3Rpb24gc2V0IGRpcmVjdGlvbih2YWx1ZToqKTp2b2lkCiAgICAgICAgeyBzZXRTdHlsZUJ5UHJvcGVydHkoVGV4dExheW91dEZvcm1hdC5kaXJlY3Rpb25Qcm9wZXJ0eSx2YWx1ZSk7IH0KCiAgICAgICAgLyoqCiAgICAgICAgICogU3BlY2lmaWVzIHRoZSBvcHRpbXVtLCBtaW5pbXVtLCBhbmQgbWF4aW11bSBzcGFjaW5nIChhcyBhIG11bHRpcGxpZXIgb2YgdGhlIHdpZHRoIG9mIGEgbm9ybWFsIHNwYWNlKSBiZXR3ZWVuIHdvcmRzIHRvIHVzZSBkdXJpbmcganVzdGlmaWNhdGlvbi4KICAgICAgICAgKiBUaGUgb3B0aW11bSBzcGFjZSBpcyB1c2VkIHRvIGluZGljYXRlIHRoZSBkZXNpcmVkIHNpemUgb2YgYSBzcGFjZSwgYXMgYSBmcmFjdGlvbiBvZiB0aGUgdmFsdWUgZGVmaW5lZCBpbiB0aGUgZm9udC4gVGhlIG1pbmltdW0gYW5kIG1heGltdW0gdmFsdWVzIGFyZSB0aGUgdXNlZCB3aGVuIHRleHRKdXN0aWZ5IGlzIGRpc3RyaWJ1dGUgdG8gZGV0ZXJtaW5lIGhvdyB3aWRlIG9yIG5hcnJvdyB0aGUgc3BhY2VzIGJldHdlZW4gdGhlIHdvcmRzIG1heSBncm93IGJlZm9yZSBsZXR0ZXIgc3BhY2luZyBpcyB1c2VkIHRvIGp1c3RpZnkgdGhlIGxpbmUuCiAgICAgICAgICogPHA+TGVnYWwgdmFsdWVzIGFzIGEgcGVyY2VudCBhcmUgbnVtYmVycyBmcm9tIC0xMDAwJSB0byAxMDAwJS48L3A+CiAgICAgICAgICogPHA+TGVnYWwgdmFsdWVzIGluY2x1ZGUgRm9ybWF0VmFsdWUuSU5IRVJJVC48L3A+CiAgICAgICAgICogPHA+RGVmYXVsdCB2YWx1ZSBpcyB1bmRlZmluZWQgaW5kaWNhdGluZyBub3Qgc2V0LjwvcD4KICAgICAgICAgKiA8cD5JZiB1bmRlZmluZWQgZHVyaW5nIHRoZSBjYXNjYWRlLCB0aGlzIHByb3BlcnR5IGluaGVyaXRzIGl0cyB2YWx1ZSBmcm9tIGFuIGFuY2VzdG9yLiBJZiBubyBhbmNlc3RvciBoYXMgc2V0IHRoaXMgcHJvcGVydHksIGl0IHdpbGwgaGF2ZSBhIHZhbHVlIG9mIDEwMCUsIDUwJSwgMTUwJS48L3A+CiAgICAgICAgICogCiAgICAgICAgICogQHRocm93cyBSYW5nZUVycm9yIHdoZW4gc2V0IHZhbHVlIGlzIG5vdCB3aXRoaW4gcmFuZ2UgZm9yIHRoaXMgcHJvcGVydHkKICAgICAgICAgKiAKICAgICAgICAgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKICAgICAgICAgKiBAbGFuZ3ZlcnNpb24gMy4wCiAgICAgICAgICovCiAgICAgICAgcHVibGljIGZ1bmN0aW9uIGdldCB3b3JkU3BhY2luZygpOioKICAgICAgICB7IHJldHVybiBfc3R5bGVzLndvcmRTcGFjaW5nOyB9CiAgICAgICAgcHVibGljIGZ1bmN0aW9uIHNldCB3b3JkU3BhY2luZyh2YWx1ZToqKTp2b2lkCiAgICAgICAgeyBzZXRTdHlsZUJ5UHJvcGVydHkoVGV4dExheW91dEZvcm1hdC53b3JkU3BhY2luZ1Byb3BlcnR5LHZhbHVlKTsgfQoKICAgICAgICAvKioKICAgICAgICAgKiBTcGVjaWZpZXMgdGhlIHRhYiBzdG9wcyBhc3NvY2lhdGVkIHdpdGggdGhlIHBhcmFncmFwaC4KICAgICAgICAgKiBTZXR0ZXJzIGNhbiB0YWtlIGFuIGFycmF5IG9mIFRhYlN0b3BGb3JtYXQsIGEgY29uZGVuc2VkIHN0cmluZyByZXByZXNlbnRhdGlvbiwgdW5kZWZpbmVkLCBvciA8Y29kZT5Gb3JtYXRWYWx1ZS5JTkhFUklUPC9jb2RlPi4gVGhlIGNvbmRlbnNlZCBzdHJpbmcgcmVwcmVzZW50YXRpb24gaXMgYWx3YXlzIGNvbnZlcnRlZCBpbnRvIGFuIGFycmF5IG9mIFRhYlN0b3BGb3JtYXQuIDxwPlRoZSBzdHJpbmctYmFzZWQgZm9ybWF0IGlzIGEgbGlzdCBvZiB0YWIgc3RvcHMsIHdoZXJlIGVhY2ggdGFiIHN0b3AgaXMgZGVsaW1pdGVkIGJ5IG9uZSBvciBtb3JlIHNwYWNlcy48L3A+PHA+QSB0YWIgc3RvcCB0YWtlcyB0aGUgZm9sbG93aW5nIGZvcm06ICZsdDthbGlnbm1lbnQgdHlwZSZndDsmbHQ7YWxpZ25tZW50IHBvc2l0aW9uJmd0O3wmbHQ7YWxpZ25tZW50IHRva2VuJmd0Oy48L3A+PHA+VGhlIGFsaWdubWVudCB0eXBlIGlzIGEgc2luZ2xlIGNoYXJhY3RlciwgYW5kIGNhbiBiZSBTLCBFLCBDLCBvciBEIChvciBsb3dlci1jYXNlIGVxdWl2YWxlbnRzKS4gUyBvciBzIGZvciBzdGFydCwgRSBvciBlIGZvciBlbmQsIEMgb3IgYyBmb3IgY2VudGVyLCBEIG9yIGQgZm9yIGRlY2ltYWwuIFRoZSBhbGlnbm1lbnQgdHlwZSBpcyBvcHRpb25hbCwgYW5kIGlmIGl0cyBub3Qgc3BlY2lmaWVkIHdpbGwgZGVmYXVsdCB0byBTLjwvcD48cD5UaGUgYWxpZ25tZW50IHBvc2l0aW9uIGlzIGEgTnVtYmVyLCBhbmQgaXMgc3BlY2lmaWVkIGFjY29yZGluZyB0byBGWEcgc3BlYyBmb3IgTnVtYmVycyAoZGVjaW1hbCBvciBzY2llbnRpZmljIG5vdGF0aW9uKS4gVGhlIGFsaWdubWVudCBwb3NpdGlvbiBpcyByZXF1aXJlZC48L3A+PHA+VGhlIHZlcnRpY2FsIGJhciBpcyB1c2VkIHRvIHNlcGFyYXRlIHRoZSBhbGlnbm1lbnQgcG9zaXRpb24gZnJvbSB0aGUgYWxpZ25tZW50IHRva2VuLCBhbmQgc2hvdWxkIG9ubHkgYmUgcHJlc2VudCBpZiB0aGUgYWxpZ25tZW50IHRva2VuIGlzIHByZXNlbnQuPC9wPjxwPiBUaGUgYWxpZ25tZW50IHRva2VuIGlzIG9wdGlvbmFsIGlmIHRoZSBhbGlnbm1lbnQgdHlwZSBpcyBELCBhbmQgc2hvdWxkIG5vdCBiZSBwcmVzZW50IGlmIHRoZSBhbGlnbm1lbnQgdHlwZSBpcyBhbnl0aGluZyBvdGhlciB0aGFuIEQuIFRoZSBhbGlnbm1lbnQgdG9rZW4gbWF5IGJlIGFueSBzZXF1ZW5jZSBvZiBjaGFyYWN0ZXJzIHRlcm1pbmF0ZWQgYnkgdGhlIHNwYWNlIHRoYXQgZW5kcyB0aGUgdGFiIHN0b3AgKGZvciB0aGUgbGFzdCB0YWIgc3RvcCwgdGhlIHRlcm1pbmF0aW5nIHNwYWNlIGlzIG9wdGlvbmFsOyBlbmQgb2YgYWxpZ25tZW50IHRva2VuIGlzIGltcGxpZWQpLiBBIHNwYWNlIG1heSBiZSBwYXJ0IG9mIHRoZSBhbGlnbm1lbnQgdG9rZW4gaWYgaXQgaXMgZXNjYXBlZCB3aXRoIGEgYmFja3NsYXNoIChcICkuIEEgYmFja3NsYXNoIG1heSBiZSBwYXJ0IG9mIHRoZSBhbGlnbm1lbnQgdG9rZW4gaWYgaXQgaXMgZXNjYXBlZCB3aXRoIGFub3RoZXIgYmFja3NsYXNoIChcXCkuIElmIHRoZSBhbGlnbm1lbnQgdHlwZSBpcyBELCBhbmQgdGhlIGFsaWdubWVudCB0b2tlbiBpcyBub3Qgc3BlY2lmaWVkLCBpdCB3aWxsIHRha2Ugb24gdGhlIGRlZmF1bHQgdmFsdWUgb2YgbnVsbC48L3A+CiAgICAgICAgICogPHA+RGVmYXVsdCB2YWx1ZSBpcyB1bmRlZmluZWQgaW5kaWNhdGluZyBub3Qgc2V0LjwvcD4KICAgICAgICAgKiA8cD5JZiB1bmRlZmluZWQgZHVyaW5nIHRoZSBjYXNjYWRlLCB0aGlzIHByb3BlcnR5IGluaGVyaXRzIGl0cyB2YWx1ZSBmcm9tIGFuIGFuY2VzdG9yLiBJZiBubyBhbmNlc3RvciBoYXMgc2V0IHRoaXMgcHJvcGVydHksIGl0IHdpbGwgaGF2ZSBhIHZhbHVlIG9mIG51bGwuPC9wPgogICAgICAgICAqIEBzZWUgZmxhc2h4LnRleHRMYXlvdXQuZm9ybWF0cy5UYWJTdG9wRm9ybWF0CiAgICAgICAgICogCiAgICAgICAgICogQHRocm93cyBSYW5nZUVycm9yIHdoZW4gc2V0IHZhbHVlIGlzIG5vdCB3aXRoaW4gcmFuZ2UgZm9yIHRoaXMgcHJvcGVydHkKICAgICAgICAgKiAKICAgICAgICAgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKICAgICAgICAgKiBAbGFuZ3ZlcnNpb24gMy4wCiAgICAgICAgICovCiAgICAgICAgcHVibGljIGZ1bmN0aW9uIGdldCB0YWJTdG9wcygpOioKICAgICAgICB7IHJldHVybiBfc3R5bGVzLnRhYlN0b3BzOyB9CiAgICAgICAgcHVibGljIGZ1bmN0aW9uIHNldCB0YWJTdG9wcyh2YWx1ZToqKTp2b2lkCiAgICAgICAgeyBzZXRTdHlsZUJ5UHJvcGVydHkoVGV4dExheW91dEZvcm1hdC50YWJTdG9wc1Byb3BlcnR5LHZhbHVlKTsgfQoKICAgICAgICBbSW5zcGVjdGFibGUoZW51bWVyYXRpb249InJvbWFuVXAsaWRlb2dyYXBoaWNUb3BVcCxpZGVvZ3JhcGhpY0NlbnRlclVwLGlkZW9ncmFwaGljVG9wRG93bixpZGVvZ3JhcGhpY0NlbnRlckRvd24sYXBwcm94aW1hdGVUZXh0RmllbGQsYXNjZW50RGVzY2VudFVwLGJveCxhdXRvLGluaGVyaXQiKV0KICAgICAgICAvKioKICAgICAgICAgKiBTcGVjaWZpZXMgdGhlIGxlYWRpbmcgbW9kZWwsIHdoaWNoIGlzIGEgY29tYmluYXRpb24gb2YgbGVhZGluZyBiYXNpcyBhbmQgbGVhZGluZyBkaXJlY3Rpb24uCiAgICAgICAgICogTGVhZGluZyBiYXNpcyBpcyB0aGUgYmFzZWxpbmUgdG8gd2hpY2ggdGhlIDxjb2RlPmxpbmVIZWlnaHQ8L2NvZGU+IHByb3BlcnR5IHJlZmVycy4gTGVhZGluZyBkaXJlY3Rpb24gZGV0ZXJtaW5lcyB3aGV0aGVyIHRoZSA8Y29kZT5saW5lSGVpZ2h0PC9jb2RlPiBwcm9wZXJ0eSByZWZlcnMgdG8gdGhlIGRpc3RhbmNlIG9mIGEgbGluZSdzIGJhc2VsaW5lIGZyb20gdGhhdCBvZiB0aGUgbGluZSBiZWZvcmUgaXQgb3IgdGhlIGxpbmUgYWZ0ZXIgaXQuIFRoZSBkZWZhdWx0IHZhbHVlIG9mIDxjb2RlPkZvcm1hdFZhbHVlLkFVVE88L2NvZGU+IGlzIHJlc29sdmVkIGJhc2VkIG9uIHRoZSBwYXJhZ3JhcGgncyA8Y29kZT5sb2NhbGU8L2NvZGU+IHByb3BlcnR5LiAgRm9yIEphcGFuZXNlIGFuZCBDaGluZXNlLCBpdCBpcyA8Y29kZT5MZWFkaW5nTW9kZWwuSURFT0dSQVBISUNfVE9QX0RPV048L2NvZGU+IGFuZCBmb3IgYWxsIG90aGVycyBpdCBpcyA8Y29kZT5MZWFkaW5nTW9kZWwuUk9NQU5fVVA8L2NvZGU+LjxwPjxzdHJvbmc+TGVhZGluZyBCYXNpczo8L3N0cm9uZz48L3A+PHA+PGltZyBzcmM9Jy4uLy4uLy4uL2ltYWdlcy90ZXh0TGF5b3V0X0xCMS5wbmcnIGFsdD0nbGVhZGluZ0Jhc2lzMScgLz4gICAgPGltZyBzcmM9Jy4uLy4uLy4uL2ltYWdlcy90ZXh0TGF5b3V0X0xCMi5wbmcnIGFsdD0nbGVhZGluZ0Jhc2lzMicgLz4gICAgPGltZyBzcmM9Jy4uLy4uLy4uL2ltYWdlcy90ZXh0TGF5b3V0X0xCMy5wbmcnIGFsdD0nbGVhZGluZ0Jhc2lzMycgLz48L3A+PHA+PHN0cm9uZz5MZWFkaW5nIERpcmVjdGlvbjo8L3N0cm9uZz48L3A+PHA+PGltZyBzcmM9Jy4uLy4uLy4uL2ltYWdlcy90ZXh0TGF5b3V0X0xEMS5wbmcnIGFsdD0nbGVhZGluZ0RpcmVjdGlvbjEnIC8+ICAgIDxpbWcgc3JjPScuLi8uLi8uLi9pbWFnZXMvdGV4dExheW91dF9MRDIucG5nJyBhbHQ9J2xlYWRpbmdEaXJlY3Rpb24yJyAvPiAgICA8aW1nIHNyYz0nLi4vLi4vLi4vaW1hZ2VzL3RleHRMYXlvdXRfTEQzLnBuZycgYWx0PSdsZWFkaW5nRGlyZWN0aW9uMycgLz48L3A+CiAgICAgICAgICogPHA+TGVnYWwgdmFsdWVzIGFyZSBMZWFkaW5nTW9kZWwuUk9NQU5fVVAsIExlYWRpbmdNb2RlbC5JREVPR1JBUEhJQ19UT1BfVVAsIExlYWRpbmdNb2RlbC5JREVPR1JBUEhJQ19DRU5URVJfVVAsIExlYWRpbmdNb2RlbC5JREVPR1JBUEhJQ19UT1BfRE9XTiwgTGVhZGluZ01vZGVsLklERU9HUkFQSElDX0NFTlRFUl9ET1dOLCBMZWFkaW5nTW9kZWwuQVBQUk9YSU1BVEVfVEVYVF9GSUVMRCwgTGVhZGluZ01vZGVsLkFTQ0VOVF9ERVNDRU5UX1VQLCBMZWFkaW5nTW9kZWwuQk9YLCBMZWFkaW5nTW9kZWwuQVVUTywgRm9ybWF0VmFsdWUuSU5IRVJJVC48L3A+CiAgICAgICAgICogPHA+RGVmYXVsdCB2YWx1ZSBpcyB1bmRlZmluZWQgaW5kaWNhdGluZyBub3Qgc2V0LjwvcD4KICAgICAgICAgKiA8cD5JZiB1bmRlZmluZWQgZHVyaW5nIHRoZSBjYXNjYWRlLCB0aGlzIHByb3BlcnR5IGluaGVyaXRzIGl0cyB2YWx1ZSBmcm9tIGFuIGFuY2VzdG9yLiBJZiBubyBhbmNlc3RvciBoYXMgc2V0IHRoaXMgcHJvcGVydHksIGl0IHdpbGwgaGF2ZSBhIHZhbHVlIG9mIExlYWRpbmdNb2RlbC5BVVRPLjwvcD4KICAgICAgICAgKiAKICAgICAgICAgKiBAdGhyb3dzIFJhbmdlRXJyb3Igd2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eQogICAgICAgICAqIAogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQogICAgICAgICAqIEBsYW5ndmVyc2lvbiAzLjAKICAgICAgICAgKiBAc2VlIGZsYXNoeC50ZXh0TGF5b3V0LmZvcm1hdHMuTGVhZGluZ01vZGVsCiAgICAgICAgICovCiAgICAgICAgcHVibGljIGZ1bmN0aW9uIGdldCBsZWFkaW5nTW9kZWwoKToqCiAgICAgICAgeyByZXR1cm4gX3N0eWxlcy5sZWFkaW5nTW9kZWw7IH0KICAgICAgICBwdWJsaWMgZnVuY3Rpb24gc2V0IGxlYWRpbmdNb2RlbCh2YWx1ZToqKTp2b2lkCiAgICAgICAgeyBzZXRTdHlsZUJ5UHJvcGVydHkoVGV4dExheW91dEZvcm1hdC5sZWFkaW5nTW9kZWxQcm9wZXJ0eSx2YWx1ZSk7IH0KCiAgICAgICAgLyoqCiAgICAgICAgICogU3BlY2lmaWVzIHRoZSBhbW91bnQgb2YgZ3V0dGVyIHNwYWNlLCBpbiBwaXhlbHMsIHRvIGxlYXZlIGJldHdlZW4gdGhlIGNvbHVtbnMgKGFkb3B0cyBkZWZhdWx0IHZhbHVlIGlmIHVuZGVmaW5lZCBkdXJpbmcgY2FzY2FkZSkuCiAgICAgICAgICogVmFsdWUgaXMgYSBOdW1iZXIKICAgICAgICAgKiA8cD5MZWdhbCB2YWx1ZXMgYXJlIG51bWJlcnMgZnJvbSAwIHRvIDEwMDAgYW5kIEZvcm1hdFZhbHVlLklOSEVSSVQuPC9wPgogICAgICAgICAqIDxwPkRlZmF1bHQgdmFsdWUgaXMgdW5kZWZpbmVkIGluZGljYXRpbmcgbm90IHNldC48L3A+CiAgICAgICAgICogPHA+SWYgdW5kZWZpbmVkIGR1cmluZyB0aGUgY2FzY2FkZSwgdGhpcyBwcm9wZXJ0eSBoYXMgYSB2YWx1ZSBvZiAyMC48L3A+CiAgICAgICAgICogCiAgICAgICAgICogQHRocm93cyBSYW5nZUVycm9yIHdoZW4gc2V0IHZhbHVlIGlzIG5vdCB3aXRoaW4gcmFuZ2UgZm9yIHRoaXMgcHJvcGVydHkKICAgICAgICAgKiAKICAgICAgICAgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKICAgICAgICAgKiBAbGFuZ3ZlcnNpb24gMy4wCiAgICAgICAgICovCiAgICAgICAgcHVibGljIGZ1bmN0aW9uIGdldCBjb2x1bW5HYXAoKToqCiAgICAgICAgeyByZXR1cm4gX3N0eWxlcy5jb2x1bW5HYXA7IH0KICAgICAgICBwdWJsaWMgZnVuY3Rpb24gc2V0IGNvbHVtbkdhcCh2YWx1ZToqKTp2b2lkCiAgICAgICAgeyBzZXRTdHlsZUJ5UHJvcGVydHkoVGV4dExheW91dEZvcm1hdC5jb2x1bW5HYXBQcm9wZXJ0eSx2YWx1ZSk7IH0KCiAgICAgICAgLyoqCiAgICAgICAgICogTGVmdCBpbnNldCBpbiBwaXhlbHMuICBEZWZhdWx0IG9mIGF1dG8gaXMgemVybyBleGNlcHQgaW4gbGlzdHMgd2hpY2ggZ2V0IGEgc3RhcnQgc2lkZSBwYWRkaW5nIG9mIDQ1LiAoYWRvcHRzIGRlZmF1bHQgdmFsdWUgaWYgdW5kZWZpbmVkIGR1cmluZyBjYXNjYWRlKS4KICAgICAgICAgKiBTcGFjZSBiZXR3ZWVuIHRoZSBsZWZ0IGVkZ2Ugb2YgdGhlIGNvbnRhaW5lciBhbmQgdGhlIHRleHQuICBWYWx1ZSBpcyBhIE51bWJlciBvciBhdXRvLjxwPiBXaXRoIHZlcnRpY2FsIHRleHQsIGluIHNjcm9sbGFibGUgY29udGFpbmVycyB3aXRoIG11bHRpcGxlIGNvbHVtbnMsIHRoZSBmaXJzdCBhbmQgZm9sbG93aW5nIGNvbHVtbnMgd2lsbCBzaG93IHRoZSBwYWRkaW5nIGFzIGJsYW5rIHNwYWNlIGF0IHRoZSBlbmQgb2YgdGhlIGNvbnRhaW5lciwgYnV0IGZvciB0aGUgbGFzdCBjb2x1bW4sIGlmIHRoZSB0ZXh0IGRvZXNuJ3QgYWxsIGZpdCwgeW91IG1heSBoYXZlIHRvIHNjcm9sbCBpbiBvcmRlciB0byBzZWUgdGhlIHBhZGRpbmcuPC9wPgogICAgICAgICAqIDxwPkxlZ2FsIHZhbHVlcyBhcyBhIHN0cmluZyBhcmUgRm9ybWF0VmFsdWUuQVVUTywgRm9ybWF0VmFsdWUuSU5IRVJJVCBhbmQgbnVtYmVycyBmcm9tIC04MDAwIHRvIDgwMDAuPC9wPgogICAgICAgICAqIDxwPkRlZmF1bHQgdmFsdWUgaXMgdW5kZWZpbmVkIGluZGljYXRpbmcgbm90IHNldC48L3A+CiAgICAgICAgICogPHA+SWYgdW5kZWZpbmVkIGR1cmluZyB0aGUgY2FzY2FkZSwgdGhpcyBwcm9wZXJ0eSBoYXMgYSB2YWx1ZSBvZiBGb3JtYXRWYWx1ZS5BVVRPLjwvcD4KICAgICAgICAgKiBAc2VlIGZsYXNoeC50ZXh0TGF5b3V0LmVsZW1lbnRzLkNvbmZpZ3VyYXRpb24jYXV0b0xpc3RFbGVtZW50U3RhcnRQYWRkaW5nCiAgICAgICAgICogCiAgICAgICAgICogQHRocm93cyBSYW5nZUVycm9yIHdoZW4gc2V0IHZhbHVlIGlzIG5vdCB3aXRoaW4gcmFuZ2UgZm9yIHRoaXMgcHJvcGVydHkKICAgICAgICAgKiAKICAgICAgICAgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKICAgICAgICAgKiBAbGFuZ3ZlcnNpb24gMy4wCiAgICAgICAgICogQHNlZSBmbGFzaHgudGV4dExheW91dC5mb3JtYXRzLkZvcm1hdFZhbHVlCiAgICAgICAgICovCiAgICAgICAgcHVibGljIGZ1bmN0aW9uIGdldCBwYWRkaW5nTGVmdCgpOioKICAgICAgICB7IHJldHVybiBfc3R5bGVzLnBhZGRpbmdMZWZ0OyB9CiAgICAgICAgcHVibGljIGZ1bmN0aW9uIHNldCBwYWRkaW5nTGVmdCh2YWx1ZToqKTp2b2lkCiAgICAgICAgeyBzZXRTdHlsZUJ5UHJvcGVydHkoVGV4dExheW91dEZvcm1hdC5wYWRkaW5nTGVmdFByb3BlcnR5LHZhbHVlKTsgfQoKICAgICAgICAvKioKICAgICAgICAgKiBUb3AgaW5zZXQgaW4gcGl4ZWxzLiAgRGVmYXVsdCBvZiBhdXRvIGlzIHplcm8gZXhjZXB0IGluIGxpc3RzIHdoaWNoIGdldCBhIHN0YXJ0IHNpZGUgcGFkZGluZyBvZiA0NS4gKGFkb3B0cyBkZWZhdWx0IHZhbHVlIGlmIHVuZGVmaW5lZCBkdXJpbmcgY2FzY2FkZSkuCiAgICAgICAgICogU3BhY2UgYmV0d2VlbiB0aGUgdG9wIGVkZ2Ugb2YgdGhlIGNvbnRhaW5lciBhbmQgdGhlIHRleHQuICBWYWx1ZSBpcyBhIE51bWJlciBvciBhdXRvLgogICAgICAgICAqIDxwPkxlZ2FsIHZhbHVlcyBhcyBhIHN0cmluZyBhcmUgRm9ybWF0VmFsdWUuQVVUTywgRm9ybWF0VmFsdWUuSU5IRVJJVCBhbmQgbnVtYmVycyBmcm9tIC04MDAwIHRvIDgwMDAuPC9wPgogICAgICAgICAqIDxwPkRlZmF1bHQgdmFsdWUgaXMgdW5kZWZpbmVkIGluZGljYXRpbmcgbm90IHNldC48L3A+CiAgICAgICAgICogPHA+SWYgdW5kZWZpbmVkIGR1cmluZyB0aGUgY2FzY2FkZSwgdGhpcyBwcm9wZXJ0eSBoYXMgYSB2YWx1ZSBvZiBGb3JtYXRWYWx1ZS5BVVRPLjwvcD4KICAgICAgICAgKiBAc2VlIGZsYXNoeC50ZXh0TGF5b3V0LmVsZW1lbnRzLkNvbmZpZ3VyYXRpb24jYXV0b0xpc3RFbGVtZW50U3RhcnRQYWRkaW5nCiAgICAgICAgICogCiAgICAgICAgICogQHRocm93cyBSYW5nZUVycm9yIHdoZW4gc2V0IHZhbHVlIGlzIG5vdCB3aXRoaW4gcmFuZ2UgZm9yIHRoaXMgcHJvcGVydHkKICAgICAgICAgKiAKICAgICAgICAgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKICAgICAgICAgKiBAbGFuZ3ZlcnNpb24gMy4wCiAgICAgICAgICogQHNlZSBmbGFzaHgudGV4dExheW91dC5mb3JtYXRzLkZvcm1hdFZhbHVlCiAgICAgICAgICovCiAgICAgICAgcHVibGljIGZ1bmN0aW9uIGdldCBwYWRkaW5nVG9wKCk6KgogICAgICAgIHsgcmV0dXJuIF9zdHlsZXMucGFkZGluZ1RvcDsgfQogICAgICAgIHB1YmxpYyBmdW5jdGlvbiBzZXQgcGFkZGluZ1RvcCh2YWx1ZToqKTp2b2lkCiAgICAgICAgeyBzZXRTdHlsZUJ5UHJvcGVydHkoVGV4dExheW91dEZvcm1hdC5wYWRkaW5nVG9wUHJvcGVydHksdmFsdWUpOyB9CgogICAgICAgIC8qKgogICAgICAgICAqIFJpZ2h0IGluc2V0IGluIHBpeGVscy4gIERlZmF1bHQgb2YgYXV0byBpcyB6ZXJvIGV4Y2VwdCBpbiBsaXN0cyB3aGljaCBnZXQgYSBzdGFydCBzaWRlIHBhZGRpbmcgb2YgNDUuIChhZG9wdHMgZGVmYXVsdCB2YWx1ZSBpZiB1bmRlZmluZWQgZHVyaW5nIGNhc2NhZGUpLgogICAgICAgICAqIFNwYWNlIGJldHdlZW4gdGhlIHJpZ2h0IGVkZ2Ugb2YgdGhlIGNvbnRhaW5lciBhbmQgdGhlIHRleHQuICBWYWx1ZSBpcyBhIE51bWJlciBvciBhdXRvLiAKICAgICAgICAgKiA8cD5MZWdhbCB2YWx1ZXMgYXMgYSBzdHJpbmcgYXJlIEZvcm1hdFZhbHVlLkFVVE8sIEZvcm1hdFZhbHVlLklOSEVSSVQgYW5kIG51bWJlcnMgZnJvbSAtODAwMCB0byA4MDAwLjwvcD4KICAgICAgICAgKiA8cD5EZWZhdWx0IHZhbHVlIGlzIHVuZGVmaW5lZCBpbmRpY2F0aW5nIG5vdCBzZXQuPC9wPgogICAgICAgICAqIDxwPklmIHVuZGVmaW5lZCBkdXJpbmcgdGhlIGNhc2NhZGUsIHRoaXMgcHJvcGVydHkgaGFzIGEgdmFsdWUgb2YgRm9ybWF0VmFsdWUuQVVUTy48L3A+CiAgICAgICAgICogQHNlZSBmbGFzaHgudGV4dExheW91dC5lbGVtZW50cy5Db25maWd1cmF0aW9uI2F1dG9MaXN0RWxlbWVudFN0YXJ0UGFkZGluZwogICAgICAgICAqIAogICAgICAgICAqIEB0aHJvd3MgUmFuZ2VFcnJvciB3aGVuIHNldCB2YWx1ZSBpcyBub3Qgd2l0aGluIHJhbmdlIGZvciB0aGlzIHByb3BlcnR5CiAgICAgICAgICogCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gRmxhc2ggMTAKICAgICAgICAgKiBAcGxheWVydmVyc2lvbiBBSVIgMS41CiAgICAgICAgICogQGxhbmd2ZXJzaW9uIDMuMAogICAgICAgICAqIEBzZWUgZmxhc2h4LnRleHRMYXlvdXQuZm9ybWF0cy5Gb3JtYXRWYWx1ZQogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBmdW5jdGlvbiBnZXQgcGFkZGluZ1JpZ2h0KCk6KgogICAgICAgIHsgcmV0dXJuIF9zdHlsZXMucGFkZGluZ1JpZ2h0OyB9CiAgICAgICAgcHVibGljIGZ1bmN0aW9uIHNldCBwYWRkaW5nUmlnaHQodmFsdWU6Kik6dm9pZAogICAgICAgIHsgc2V0U3R5bGVCeVByb3BlcnR5KFRleHRMYXlvdXRGb3JtYXQucGFkZGluZ1JpZ2h0UHJvcGVydHksdmFsdWUpOyB9CgogICAgICAgIC8qKgogICAgICAgICAqIEJvdHRvbSBpbnNldCBpbiBwaXhlbHMuICBEZWZhdWx0IG9mIGF1dG8gaXMgemVybyBleGNlcHQgaW4gbGlzdHMgd2hpY2ggZ2V0IGEgc3RhcnQgc2lkZSBwYWRkaW5nIG9mIDQ1LiAgKGFkb3B0cyBkZWZhdWx0IHZhbHVlIGlmIHVuZGVmaW5lZCBkdXJpbmcgY2FzY2FkZSkuCiAgICAgICAgICogU3BhY2UgYmV0d2VlbiB0aGUgYm90dG9tIGVkZ2Ugb2YgdGhlIGNvbnRhaW5lciBhbmQgdGhlIHRleHQuICBWYWx1ZSBpcyBhIE51bWJlciAgb3IgYXV0by4gPHA+IFdpdGggaG9yaXpvbnRhbCB0ZXh0LCBpbiBzY3JvbGxhYmxlIGNvbnRhaW5lcnMgd2l0aCBtdWx0aXBsZSBjb2x1bW5zLCB0aGUgZmlyc3QgYW5kIGZvbGxvd2luZyBjb2x1bW5zIHdpbGwgc2hvdyB0aGUgcGFkZGluZyBhcyBibGFuayBzcGFjZSBhdCB0aGUgYm90dG9tIG9mIHRoZSBjb250YWluZXIsIGJ1dCBmb3IgdGhlIGxhc3QgY29sdW1uLCBpZiB0aGUgdGV4dCBkb2Vzbid0IGFsbCBmaXQsIHlvdSBtYXkgaGF2ZSB0byBzY3JvbGwgaW4gb3JkZXIgdG8gc2VlIHRoZSBwYWRkaW5nLjwvcD4KICAgICAgICAgKiA8cD5MZWdhbCB2YWx1ZXMgYXMgYSBzdHJpbmcgYXJlIEZvcm1hdFZhbHVlLkFVVE8sIEZvcm1hdFZhbHVlLklOSEVSSVQgYW5kIG51bWJlcnMgZnJvbSAtODAwMCB0byA4MDAwLjwvcD4KICAgICAgICAgKiA8cD5EZWZhdWx0IHZhbHVlIGlzIHVuZGVmaW5lZCBpbmRpY2F0aW5nIG5vdCBzZXQuPC9wPgogICAgICAgICAqIDxwPklmIHVuZGVmaW5lZCBkdXJpbmcgdGhlIGNhc2NhZGUsIHRoaXMgcHJvcGVydHkgaGFzIGEgdmFsdWUgb2YgRm9ybWF0VmFsdWUuQVVUTy48L3A+CiAgICAgICAgICogQHNlZSBmbGFzaHgudGV4dExheW91dC5lbGVtZW50cy5Db25maWd1cmF0aW9uI2F1dG9MaXN0RWxlbWVudFN0YXJ0UGFkZGluZwogICAgICAgICAqIAogICAgICAgICAqIEB0aHJvd3MgUmFuZ2VFcnJvciB3aGVuIHNldCB2YWx1ZSBpcyBub3Qgd2l0aGluIHJhbmdlIGZvciB0aGlzIHByb3BlcnR5CiAgICAgICAgICogCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gRmxhc2ggMTAKICAgICAgICAgKiBAcGxheWVydmVyc2lvbiBBSVIgMS41CiAgICAgICAgICogQGxhbmd2ZXJzaW9uIDMuMAogICAgICAgICAqIEBzZWUgZmxhc2h4LnRleHRMYXlvdXQuZm9ybWF0cy5Gb3JtYXRWYWx1ZQogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBmdW5jdGlvbiBnZXQgcGFkZGluZ0JvdHRvbSgpOioKICAgICAgICB7IHJldHVybiBfc3R5bGVzLnBhZGRpbmdCb3R0b207IH0KICAgICAgICBwdWJsaWMgZnVuY3Rpb24gc2V0IHBhZGRpbmdCb3R0b20odmFsdWU6Kik6dm9pZAogICAgICAgIHsgc2V0U3R5bGVCeVByb3BlcnR5KFRleHRMYXlvdXRGb3JtYXQucGFkZGluZ0JvdHRvbVByb3BlcnR5LHZhbHVlKTsgfQoKICAgICAgICAvKioKICAgICAgICAgKiBOdW1iZXIgb2YgdGV4dCBjb2x1bW5zIChhZG9wdHMgZGVmYXVsdCB2YWx1ZSBpZiB1bmRlZmluZWQgZHVyaW5nIGNhc2NhZGUpLgogICAgICAgICAqIFRoZSBjb2x1bW4gbnVtYmVyIG92ZXJyaWRlcyB0aGUgIG90aGVyIGNvbHVtbiBzZXR0aW5ncy4gVmFsdWUgaXMgYW4gaW50ZWdlciwgb3IgPGNvZGU+Rm9ybWF0VmFsdWUuQVVUTzwvY29kZT4gaWYgdW5zcGVjaWZpZWQuIElmIDxjb2RlPmNvbHVtbkNvdW50PC9jb2RlPiBpcyBub3Qgc3BlY2lmaWVkLDxjb2RlPmNvbHVtbldpZHRoPC9jb2RlPiBpcyB1c2VkIHRvIGNyZWF0ZSBhcyBtYW55IGNvbHVtbnMgYXMgY2FuIGZpdCBpbiB0aGUgY29udGFpbmVyLgogICAgICAgICAqIDxwPkxlZ2FsIHZhbHVlcyBhcyBhIHN0cmluZyBhcmUgRm9ybWF0VmFsdWUuQVVUTywgRm9ybWF0VmFsdWUuSU5IRVJJVCBhbmQgZnJvbSBpbnRzIGZyb20gMSB0byA1MC48L3A+CiAgICAgICAgICogPHA+RGVmYXVsdCB2YWx1ZSBpcyB1bmRlZmluZWQgaW5kaWNhdGluZyBub3Qgc2V0LjwvcD4KICAgICAgICAgKiA8cD5JZiB1bmRlZmluZWQgZHVyaW5nIHRoZSBjYXNjYWRlLCB0aGlzIHByb3BlcnR5IGhhcyBhIHZhbHVlIG9mIEZvcm1hdFZhbHVlLkFVVE8uPC9wPgogICAgICAgICAqIAogICAgICAgICAqIEB0aHJvd3MgUmFuZ2VFcnJvciB3aGVuIHNldCB2YWx1ZSBpcyBub3Qgd2l0aGluIHJhbmdlIGZvciB0aGlzIHByb3BlcnR5CiAgICAgICAgICogCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gRmxhc2ggMTAKICAgICAgICAgKiBAcGxheWVydmVyc2lvbiBBSVIgMS41CiAgICAgICAgICogQGxhbmd2ZXJzaW9uIDMuMAogICAgICAgICAqIEBzZWUgZmxhc2h4LnRleHRMYXlvdXQuZm9ybWF0cy5Gb3JtYXRWYWx1ZQogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBmdW5jdGlvbiBnZXQgY29sdW1uQ291bnQoKToqCiAgICAgICAgeyByZXR1cm4gX3N0eWxlcy5jb2x1bW5Db3VudDsgfQogICAgICAgIHB1YmxpYyBmdW5jdGlvbiBzZXQgY29sdW1uQ291bnQodmFsdWU6Kik6dm9pZAogICAgICAgIHsgc2V0U3R5bGVCeVByb3BlcnR5KFRleHRMYXlvdXRGb3JtYXQuY29sdW1uQ291bnRQcm9wZXJ0eSx2YWx1ZSk7IH0KCiAgICAgICAgLyoqCiAgICAgICAgICogQ29sdW1uIHdpZHRoIGluIHBpeGVscyAoYWRvcHRzIGRlZmF1bHQgdmFsdWUgaWYgdW5kZWZpbmVkIGR1cmluZyBjYXNjYWRlKS4KICAgICAgICAgKiBJZiB5b3Ugc3BlY2lmeSB0aGUgd2lkdGggb2YgdGhlIGNvbHVtbnMsIGJ1dCBub3QgdGhlIGNvdW50LCBUZXh0TGF5b3V0IHdpbGwgY3JlYXRlIGFzIG1hbnkgY29sdW1ucyBvZiB0aGF0IHdpZHRoIGFzIHBvc3NpYmxlLCBnaXZlbiB0aGUgIGNvbnRhaW5lciB3aWR0aCBhbmQgPGNvZGU+Y29sdW1uR2FwPC9jb2RlPiBzZXR0aW5ncy4gQW55IHJlbWFpbmRlciBzcGFjZSBpcyBsZWZ0IGFmdGVyIHRoZSBsYXN0IGNvbHVtbi4gVmFsdWUgaXMgYSBOdW1iZXIuCiAgICAgICAgICogPHA+TGVnYWwgdmFsdWVzIGFzIGEgc3RyaW5nIGFyZSBGb3JtYXRWYWx1ZS5BVVRPLCBGb3JtYXRWYWx1ZS5JTkhFUklUIGFuZCBudW1iZXJzIGZyb20gMCB0byA4MDAwLjwvcD4KICAgICAgICAgKiA8cD5EZWZhdWx0IHZhbHVlIGlzIHVuZGVmaW5lZCBpbmRpY2F0aW5nIG5vdCBzZXQuPC9wPgogICAgICAgICAqIDxwPklmIHVuZGVmaW5lZCBkdXJpbmcgdGhlIGNhc2NhZGUsIHRoaXMgcHJvcGVydHkgaGFzIGEgdmFsdWUgb2YgRm9ybWF0VmFsdWUuQVVUTy48L3A+CiAgICAgICAgICogCiAgICAgICAgICogQHRocm93cyBSYW5nZUVycm9yIHdoZW4gc2V0IHZhbHVlIGlzIG5vdCB3aXRoaW4gcmFuZ2UgZm9yIHRoaXMgcHJvcGVydHkKICAgICAgICAgKiAKICAgICAgICAgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKICAgICAgICAgKiBAbGFuZ3ZlcnNpb24gMy4wCiAgICAgICAgICogQHNlZSBmbGFzaHgudGV4dExheW91dC5mb3JtYXRzLkZvcm1hdFZhbHVlCiAgICAgICAgICovCiAgICAgICAgcHVibGljIGZ1bmN0aW9uIGdldCBjb2x1bW5XaWR0aCgpOioKICAgICAgICB7IHJldHVybiBfc3R5bGVzLmNvbHVtbldpZHRoOyB9CiAgICAgICAgcHVibGljIGZ1bmN0aW9uIHNldCBjb2x1bW5XaWR0aCh2YWx1ZToqKTp2b2lkCiAgICAgICAgeyBzZXRTdHlsZUJ5UHJvcGVydHkoVGV4dExheW91dEZvcm1hdC5jb2x1bW5XaWR0aFByb3BlcnR5LHZhbHVlKTsgfQoKICAgICAgICAvKioKICAgICAgICAgKiBTcGVjaWZpZXMgdGhlIGJhc2VsaW5lIHBvc2l0aW9uIG9mIHRoZSBmaXJzdCBsaW5lIGluIHRoZSBjb250YWluZXIuIFdoaWNoIGJhc2VsaW5lIHRoaXMgcHJvcGVydHkgcmVmZXJzIHRvIGRlcGVuZHMgb24gdGhlIGNvbnRhaW5lci1sZXZlbCBsb2NhbGUuICBGb3IgSmFwYW5lc2UgYW5kIENoaW5lc2UsIGl0IGlzIDxjb2RlPlRleHRCYXNlbGluZS5JREVPR1JBUEhJQ19CT1RUT008L2NvZGU+OyBmb3IgYWxsIG90aGVycyBpdCBpcyA8Y29kZT5UZXh0QmFzZWxpbmUuUk9NQU48L2NvZGU+LgogICAgICAgICAqIFRoZSBvZmZzZXQgZnJvbSB0aGUgdG9wIGluc2V0IChvciByaWdodCBpbnNldCBpZiA8Y29kZT5ibG9ja1Byb2dyZXNzaW9uPC9jb2RlPiBpcyBSTCkgb2YgdGhlIGNvbnRhaW5lciB0byB0aGUgYmFzZWxpbmUgb2YgdGhlIGZpcnN0IGxpbmUgY2FuIGJlIGVpdGhlciA8Y29kZT5CYXNlbGluZU9mZnNldC5BU0NFTlQ8L2NvZGU+LCBtZWFuaW5nIGVxdWFsIHRvIHRoZSBhc2NlbnQgb2YgdGhlIGxpbmUsIDxjb2RlPkJhc2VsaW5lT2Zmc2V0LkxJTkVfSEVJR0hUPC9jb2RlPiwgbWVhbmluZyBlcXVhbCB0byB0aGUgaGVpZ2h0IG9mIHRoYXQgZmlyc3QgbGluZSwgb3IgYW55IGZpeGVkLXZhbHVlIG51bWJlciB0byBzcGVjaWZ5IGFuIGFic29sdXRlIGRpc3RhbmNlLiA8Y29kZT5CYXNlbGluZU9mZnNldC5BVVRPPC9jb2RlPiBhbGlnbnMgdGhlIGFzY2VudCBvZiB0aGUgbGluZSB3aXRoIHRoZSBjb250YWluZXIgdG9wIGluc2V0LjxwPjxpbWcgc3JjPScuLi8uLi8uLi9pbWFnZXMvdGV4dExheW91dF9GQk8xLnBuZycgYWx0PSdmaXJzdEJhc2VsaW5lT2Zmc2V0MScgLz48aW1nIHNyYz0nLi4vLi4vLi4vaW1hZ2VzL3RleHRMYXlvdXRfRkJPMi5wbmcnIGFsdD0nZmlyc3RCYXNlbGluZU9mZnNldDInIC8+PGltZyBzcmM9Jy4uLy4uLy4uL2ltYWdlcy90ZXh0TGF5b3V0X0ZCTzMucG5nJyBhbHQ9J2ZpcnN0QmFzZWxpbmVPZmZzZXQzJyAvPjxpbWcgc3JjPScuLi8uLi8uLi9pbWFnZXMvdGV4dExheW91dF9GQk80LnBuZycgYWx0PSdmaXJzdEJhc2VsaW5lT2Zmc2V0NCcgLz48L3A+CiAgICAgICAgICogPHA+TGVnYWwgdmFsdWVzIGFzIGEgc3RyaW5nIGFyZSBCYXNlbGluZU9mZnNldC5BVVRPLCBCYXNlbGluZU9mZnNldC5BU0NFTlQsIEJhc2VsaW5lT2Zmc2V0LkxJTkVfSEVJR0hULCBGb3JtYXRWYWx1ZS5JTkhFUklUIGFuZCBudW1iZXJzIGZyb20gMCB0byAxMDAwLjwvcD4KICAgICAgICAgKiA8cD5EZWZhdWx0IHZhbHVlIGlzIHVuZGVmaW5lZCBpbmRpY2F0aW5nIG5vdCBzZXQuPC9wPgogICAgICAgICAqIDxwPklmIHVuZGVmaW5lZCBkdXJpbmcgdGhlIGNhc2NhZGUsIHRoaXMgcHJvcGVydHkgaW5oZXJpdHMgaXRzIHZhbHVlIGZyb20gYW4gYW5jZXN0b3IuIElmIG5vIGFuY2VzdG9yIGhhcyBzZXQgdGhpcyBwcm9wZXJ0eSwgaXQgd2lsbCBoYXZlIGEgdmFsdWUgb2YgQmFzZWxpbmVPZmZzZXQuQVVUTy48L3A+CiAgICAgICAgICogCiAgICAgICAgICogQHRocm93cyBSYW5nZUVycm9yIHdoZW4gc2V0IHZhbHVlIGlzIG5vdCB3aXRoaW4gcmFuZ2UgZm9yIHRoaXMgcHJvcGVydHkKICAgICAgICAgKiAKICAgICAgICAgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKICAgICAgICAgKiBAbGFuZ3ZlcnNpb24gMy4wCiAgICAgICAgICogQHNlZSBmbGFzaHgudGV4dExheW91dC5mb3JtYXRzLkJhc2VsaW5lT2Zmc2V0CiAgICAgICAgICovCiAgICAgICAgcHVibGljIGZ1bmN0aW9uIGdldCBmaXJzdEJhc2VsaW5lT2Zmc2V0KCk6KgogICAgICAgIHsgcmV0dXJuIF9zdHlsZXMuZmlyc3RCYXNlbGluZU9mZnNldDsgfQogICAgICAgIHB1YmxpYyBmdW5jdGlvbiBzZXQgZmlyc3RCYXNlbGluZU9mZnNldCh2YWx1ZToqKTp2b2lkCiAgICAgICAgeyBzZXRTdHlsZUJ5UHJvcGVydHkoVGV4dExheW91dEZvcm1hdC5maXJzdEJhc2VsaW5lT2Zmc2V0UHJvcGVydHksdmFsdWUpOyB9CgogICAgICAgIFtJbnNwZWN0YWJsZShlbnVtZXJhdGlvbj0idG9wLG1pZGRsZSxib3R0b20sanVzdGlmeSxpbmhlcml0IildCiAgICAgICAgLyoqCiAgICAgICAgICogVmVydGljYWwgYWxpZ25tZW50IG9yIGp1c3RpZmljYXRpb24gKGFkb3B0cyBkZWZhdWx0IHZhbHVlIGlmIHVuZGVmaW5lZCBkdXJpbmcgY2FzY2FkZSkuCiAgICAgICAgICogRGV0ZXJtaW5lcyBob3cgVGV4dEZsb3cgZWxlbWVudHMgYWxpZ24gd2l0aGluIHRoZSBjb250YWluZXIuCiAgICAgICAgICogPHA+TGVnYWwgdmFsdWVzIGFyZSBWZXJ0aWNhbEFsaWduLlRPUCwgVmVydGljYWxBbGlnbi5NSURETEUsIFZlcnRpY2FsQWxpZ24uQk9UVE9NLCBWZXJ0aWNhbEFsaWduLkpVU1RJRlksIEZvcm1hdFZhbHVlLklOSEVSSVQuPC9wPgogICAgICAgICAqIDxwPkRlZmF1bHQgdmFsdWUgaXMgdW5kZWZpbmVkIGluZGljYXRpbmcgbm90IHNldC48L3A+CiAgICAgICAgICogPHA+SWYgdW5kZWZpbmVkIGR1cmluZyB0aGUgY2FzY2FkZSwgdGhpcyBwcm9wZXJ0eSBoYXMgYSB2YWx1ZSBvZiBWZXJ0aWNhbEFsaWduLlRPUC48L3A+CiAgICAgICAgICogCiAgICAgICAgICogQHRocm93cyBSYW5nZUVycm9yIHdoZW4gc2V0IHZhbHVlIGlzIG5vdCB3aXRoaW4gcmFuZ2UgZm9yIHRoaXMgcHJvcGVydHkKICAgICAgICAgKiAKICAgICAgICAgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKICAgICAgICAgKiBAbGFuZ3ZlcnNpb24gMy4wCiAgICAgICAgICogQHNlZSBmbGFzaHgudGV4dExheW91dC5mb3JtYXRzLlZlcnRpY2FsQWxpZ24KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgZnVuY3Rpb24gZ2V0IHZlcnRpY2FsQWxpZ24oKToqCiAgICAgICAgeyByZXR1cm4gX3N0eWxlcy52ZXJ0aWNhbEFsaWduOyB9CiAgICAgICAgcHVibGljIGZ1bmN0aW9uIHNldCB2ZXJ0aWNhbEFsaWduKHZhbHVlOiopOnZvaWQKICAgICAgICB7IHNldFN0eWxlQnlQcm9wZXJ0eShUZXh0TGF5b3V0Rm9ybWF0LnZlcnRpY2FsQWxpZ25Qcm9wZXJ0eSx2YWx1ZSk7IH0KCiAgICAgICAgW0luc3BlY3RhYmxlKGVudW1lcmF0aW9uPSJybCx0Yixpbmhlcml0IildCiAgICAgICAgLyoqCiAgICAgICAgICogU3BlY2lmaWVzIGEgdmVydGljYWwgb3IgaG9yaXpvbnRhbCBwcm9ncmVzc2lvbiBvZiBsaW5lIHBsYWNlbWVudC4KICAgICAgICAgKiBMaW5lcyBhcmUgZWl0aGVyIHBsYWNlZCB0b3AtdG8tYm90dG9tICg8Y29kZT5CbG9ja1Byb2dyZXNzaW9uLlRCPC9jb2RlPiwgdXNlZCBmb3IgaG9yaXpvbnRhbCB0ZXh0KSBvciByaWdodC10by1sZWZ0ICg8Y29kZT5CbG9ja1Byb2dyZXNzaW9uLlJMPC9jb2RlPiwgdXNlZCBmb3IgdmVydGljYWwgdGV4dCkuCiAgICAgICAgICogPHA+TGVnYWwgdmFsdWVzIGFyZSBCbG9ja1Byb2dyZXNzaW9uLlJMLCBCbG9ja1Byb2dyZXNzaW9uLlRCLCBGb3JtYXRWYWx1ZS5JTkhFUklULjwvcD4KICAgICAgICAgKiA8cD5EZWZhdWx0IHZhbHVlIGlzIHVuZGVmaW5lZCBpbmRpY2F0aW5nIG5vdCBzZXQuPC9wPgogICAgICAgICAqIDxwPklmIHVuZGVmaW5lZCBkdXJpbmcgdGhlIGNhc2NhZGUsIHRoaXMgcHJvcGVydHkgaW5oZXJpdHMgaXRzIHZhbHVlIGZyb20gYW4gYW5jZXN0b3IuIElmIG5vIGFuY2VzdG9yIGhhcyBzZXQgdGhpcyBwcm9wZXJ0eSwgaXQgd2lsbCBoYXZlIGEgdmFsdWUgb2YgQmxvY2tQcm9ncmVzc2lvbi5UQi48L3A+CiAgICAgICAgICogCiAgICAgICAgICogQHRocm93cyBSYW5nZUVycm9yIHdoZW4gc2V0IHZhbHVlIGlzIG5vdCB3aXRoaW4gcmFuZ2UgZm9yIHRoaXMgcHJvcGVydHkKICAgICAgICAgKiAKICAgICAgICAgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKICAgICAgICAgKiBAbGFuZ3ZlcnNpb24gMy4wCiAgICAgICAgICogQHNlZSBmbGFzaHgudGV4dExheW91dC5mb3JtYXRzLkJsb2NrUHJvZ3Jlc3Npb24KICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgZnVuY3Rpb24gZ2V0IGJsb2NrUHJvZ3Jlc3Npb24oKToqCiAgICAgICAgeyByZXR1cm4gX3N0eWxlcy5ibG9ja1Byb2dyZXNzaW9uOyB9CiAgICAgICAgcHVibGljIGZ1bmN0aW9uIHNldCBibG9ja1Byb2dyZXNzaW9uKHZhbHVlOiopOnZvaWQKICAgICAgICB7IHNldFN0eWxlQnlQcm9wZXJ0eShUZXh0TGF5b3V0Rm9ybWF0LmJsb2NrUHJvZ3Jlc3Npb25Qcm9wZXJ0eSx2YWx1ZSk7IH0KCiAgICAgICAgW0luc3BlY3RhYmxlKGVudW1lcmF0aW9uPSJleHBsaWNpdCx0b0ZpdCxpbmhlcml0IildCiAgICAgICAgLyoqCiAgICAgICAgICogQ29udHJvbHMgd29yZCB3cmFwcGluZyB3aXRoaW4gdGhlIGNvbnRhaW5lciAoYWRvcHRzIGRlZmF1bHQgdmFsdWUgaWYgdW5kZWZpbmVkIGR1cmluZyBjYXNjYWRlKS4KICAgICAgICAgKiBUZXh0IGluIHRoZSBjb250YWluZXIgbWF5IGJlIHNldCB0byBmaXQgdGhlIHdpZHRoIG9mIHRoZSBjb250YWluZXIgKDxjb2RlPkxpbmVCcmVhay5UT19GSVQ8L2NvZGU+KSwgb3IgY2FuIGJlIHNldCB0byBicmVhayBvbmx5IGF0IGV4cGxpY2l0IHJldHVybiBvciBsaW5lIGZlZWQgY2hhcmFjdGVycyAoPGNvZGU+TGluZUJyZWFrLkVYUExJQ0lUPC9jb2RlPikuCiAgICAgICAgICogPHA+TGVnYWwgdmFsdWVzIGFyZSBMaW5lQnJlYWsuRVhQTElDSVQsIExpbmVCcmVhay5UT19GSVQsIEZvcm1hdFZhbHVlLklOSEVSSVQuPC9wPgogICAgICAgICAqIDxwPkRlZmF1bHQgdmFsdWUgaXMgdW5kZWZpbmVkIGluZGljYXRpbmcgbm90IHNldC48L3A+CiAgICAgICAgICogPHA+SWYgdW5kZWZpbmVkIGR1cmluZyB0aGUgY2FzY2FkZSwgdGhpcyBwcm9wZXJ0eSBoYXMgYSB2YWx1ZSBvZiBMaW5lQnJlYWsuVE9fRklULjwvcD4KICAgICAgICAgKiAKICAgICAgICAgKiBAdGhyb3dzIFJhbmdlRXJyb3Igd2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eQogICAgICAgICAqIAogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQogICAgICAgICAqIEBsYW5ndmVyc2lvbiAzLjAKICAgICAgICAgKiBAc2VlIGZsYXNoeC50ZXh0TGF5b3V0LmZvcm1hdHMuTGluZUJyZWFrCiAgICAgICAgICovCiAgICAgICAgcHVibGljIGZ1bmN0aW9uIGdldCBsaW5lQnJlYWsoKToqCiAgICAgICAgeyByZXR1cm4gX3N0eWxlcy5saW5lQnJlYWs7IH0KICAgICAgICBwdWJsaWMgZnVuY3Rpb24gc2V0IGxpbmVCcmVhayh2YWx1ZToqKTp2b2lkCiAgICAgICAgeyBzZXRTdHlsZUJ5UHJvcGVydHkoVGV4dExheW91dEZvcm1hdC5saW5lQnJlYWtQcm9wZXJ0eSx2YWx1ZSk7IH0KCiAgICAgICAgW0luc3BlY3RhYmxlKGVudW1lcmF0aW9uPSJ1cHBlckFscGhhLGxvd2VyQWxwaGEsdXBwZXJSb21hbixsb3dlclJvbWFuLG5vbmUsZGlzYyxjaXJjbGUsc3F1YXJlLGJveCxjaGVjayxkaWFtb25kLGh5cGhlbixhcmFiaWNJbmRpYyxiZW5nYWxpLGRlY2ltYWwsZGVjaW1hbExlYWRpbmdaZXJvLGRldmFuYWdhcmksZ3VqYXJhdGksZ3VybXVraGksa2FubmFkYSxwZXJzaWFuLHRoYWksdXJkdSxjamtFYXJ0aGx5QnJhbmNoLGNqa0hlYXZlbmx5U3RlbSxoYW5ndWwsaGFuZ3VsQ29uc3RhbnQsaGlyYWdhbmEsaGlyYWdhbmFJcm9oYSxrYXRha2FuYSxrYXRha2FuYUlyb2hhLGxvd2VyQWxwaGEsbG93ZXJHcmVlayxsb3dlckxhdGluLHVwcGVyQWxwaGEsdXBwZXJHcmVlayx1cHBlckxhdGluLGluaGVyaXQiKV0KICAgICAgICAvKioKICAgICAgICAgKiA8cD5MZWdhbCB2YWx1ZXMgYXJlIExpc3RTdHlsZVR5cGUuVVBQRVJfQUxQSEEsIExpc3RTdHlsZVR5cGUuTE9XRVJfQUxQSEEsIExpc3RTdHlsZVR5cGUuVVBQRVJfUk9NQU4sIExpc3RTdHlsZVR5cGUuTE9XRVJfUk9NQU4sIExpc3RTdHlsZVR5cGUuTk9ORSwgTGlzdFN0eWxlVHlwZS5ESVNDLCBMaXN0U3R5bGVUeXBlLkNJUkNMRSwgTGlzdFN0eWxlVHlwZS5TUVVBUkUsIExpc3RTdHlsZVR5cGUuQk9YLCBMaXN0U3R5bGVUeXBlLkNIRUNLLCBMaXN0U3R5bGVUeXBlLkRJQU1PTkQsIExpc3RTdHlsZVR5cGUuSFlQSEVOLCBMaXN0U3R5bGVUeXBlLkFSQUJJQ19JTkRJQywgTGlzdFN0eWxlVHlwZS5CRU5HQUxJLCBMaXN0U3R5bGVUeXBlLkRFQ0lNQUwsIExpc3RTdHlsZVR5cGUuREVDSU1BTF9MRUFESU5HX1pFUk8sIExpc3RTdHlsZVR5cGUuREVWQU5BR0FSSSwgTGlzdFN0eWxlVHlwZS5HVUpBUkFUSSwgTGlzdFN0eWxlVHlwZS5HVVJNVUtISSwgTGlzdFN0eWxlVHlwZS5LQU5OQURBLCBMaXN0U3R5bGVUeXBlLlBFUlNJQU4sIExpc3RTdHlsZVR5cGUuVEhBSSwgTGlzdFN0eWxlVHlwZS5VUkRVLCBMaXN0U3R5bGVUeXBlLkNKS19FQVJUSExZX0JSQU5DSCwgTGlzdFN0eWxlVHlwZS5DSktfSEVBVkVOTFlfU1RFTSwgTGlzdFN0eWxlVHlwZS5IQU5HVUwsIExpc3RTdHlsZVR5cGUuSEFOR1VMX0NPTlNUQU5ULCBMaXN0U3R5bGVUeXBlLkhJUkFHQU5BLCBMaXN0U3R5bGVUeXBlLkhJUkFHQU5BX0lST0hBLCBMaXN0U3R5bGVUeXBlLktBVEFLQU5BLCBMaXN0U3R5bGVUeXBlLktBVEFLQU5BX0lST0hBLCBMaXN0U3R5bGVUeXBlLkxPV0VSX0FMUEhBLCBMaXN0U3R5bGVUeXBlLkxPV0VSX0dSRUVLLCBMaXN0U3R5bGVUeXBlLkxPV0VSX0xBVElOLCBMaXN0U3R5bGVUeXBlLlVQUEVSX0FMUEhBLCBMaXN0U3R5bGVUeXBlLlVQUEVSX0dSRUVLLCBMaXN0U3R5bGVUeXBlLlVQUEVSX0xBVElOLCBGb3JtYXRWYWx1ZS5JTkhFUklULjwvcD4KICAgICAgICAgKiA8cD5EZWZhdWx0IHZhbHVlIGlzIHVuZGVmaW5lZCBpbmRpY2F0aW5nIG5vdCBzZXQuPC9wPgogICAgICAgICAqIDxwPklmIHVuZGVmaW5lZCBkdXJpbmcgdGhlIGNhc2NhZGUsIHRoaXMgcHJvcGVydHkgaW5oZXJpdHMgaXRzIHZhbHVlIGZyb20gYW4gYW5jZXN0b3IuIElmIG5vIGFuY2VzdG9yIGhhcyBzZXQgdGhpcyBwcm9wZXJ0eSwgaXQgd2lsbCBoYXZlIGEgdmFsdWUgb2YgTGlzdFN0eWxlVHlwZS5ESVNDLjwvcD4KICAgICAgICAgKiAKICAgICAgICAgKiBAdGhyb3dzIFJhbmdlRXJyb3Igd2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eQogICAgICAgICAqIAogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQogICAgICAgICAqIEBsYW5ndmVyc2lvbiAzLjAKICAgICAgICAgKiBAc2VlIGZsYXNoeC50ZXh0TGF5b3V0LmZvcm1hdHMuTGlzdFN0eWxlVHlwZQogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBmdW5jdGlvbiBnZXQgbGlzdFN0eWxlVHlwZSgpOioKICAgICAgICB7IHJldHVybiBfc3R5bGVzLmxpc3RTdHlsZVR5cGU7IH0KICAgICAgICBwdWJsaWMgZnVuY3Rpb24gc2V0IGxpc3RTdHlsZVR5cGUodmFsdWU6Kik6dm9pZAogICAgICAgIHsgc2V0U3R5bGVCeVByb3BlcnR5KFRleHRMYXlvdXRGb3JtYXQubGlzdFN0eWxlVHlwZVByb3BlcnR5LHZhbHVlKTsgfQoKICAgICAgICBbSW5zcGVjdGFibGUoZW51bWVyYXRpb249Imluc2lkZSxvdXRzaWRlLGluaGVyaXQiKV0KICAgICAgICAvKioKICAgICAgICAgKiA8cD5MZWdhbCB2YWx1ZXMgYXJlIExpc3RTdHlsZVBvc2l0aW9uLklOU0lERSwgTGlzdFN0eWxlUG9zaXRpb24uT1VUU0lERSwgRm9ybWF0VmFsdWUuSU5IRVJJVC48L3A+CiAgICAgICAgICogPHA+RGVmYXVsdCB2YWx1ZSBpcyB1bmRlZmluZWQgaW5kaWNhdGluZyBub3Qgc2V0LjwvcD4KICAgICAgICAgKiA8cD5JZiB1bmRlZmluZWQgZHVyaW5nIHRoZSBjYXNjYWRlLCB0aGlzIHByb3BlcnR5IGluaGVyaXRzIGl0cyB2YWx1ZSBmcm9tIGFuIGFuY2VzdG9yLiBJZiBubyBhbmNlc3RvciBoYXMgc2V0IHRoaXMgcHJvcGVydHksIGl0IHdpbGwgaGF2ZSBhIHZhbHVlIG9mIExpc3RTdHlsZVBvc2l0aW9uLk9VVFNJREUuPC9wPgogICAgICAgICAqIAogICAgICAgICAqIEB0aHJvd3MgUmFuZ2VFcnJvciB3aGVuIHNldCB2YWx1ZSBpcyBub3Qgd2l0aGluIHJhbmdlIGZvciB0aGlzIHByb3BlcnR5CiAgICAgICAgICogCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gRmxhc2ggMTAKICAgICAgICAgKiBAcGxheWVydmVyc2lvbiBBSVIgMS41CiAgICAgICAgICogQGxhbmd2ZXJzaW9uIDMuMAogICAgICAgICAqIEBzZWUgZmxhc2h4LnRleHRMYXlvdXQuZm9ybWF0cy5MaXN0U3R5bGVQb3NpdGlvbgogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBmdW5jdGlvbiBnZXQgbGlzdFN0eWxlUG9zaXRpb24oKToqCiAgICAgICAgeyByZXR1cm4gX3N0eWxlcy5saXN0U3R5bGVQb3NpdGlvbjsgfQogICAgICAgIHB1YmxpYyBmdW5jdGlvbiBzZXQgbGlzdFN0eWxlUG9zaXRpb24odmFsdWU6Kik6dm9pZAogICAgICAgIHsgc2V0U3R5bGVCeVByb3BlcnR5KFRleHRMYXlvdXRGb3JtYXQubGlzdFN0eWxlUG9zaXRpb25Qcm9wZXJ0eSx2YWx1ZSk7IH0KCiAgICAgICAgLyoqCiAgICAgICAgICogVGhpcyBzcGVjaWZpZXMgYW4gYXV0byBpbmRlbnQgZm9yIHRoZSBzdGFydCBlZGdlIG9mIGxpc3RzIHdoZW4gdGhlIHBhZGRpbmcgdmFsdWUgb2YgdGhlIGxpc3Qgb24gdGhhdCBzaWRlIGlzIDxjb2RlPmF1dG88L2NvZGU+LgogICAgICAgICAqIDxwPkxlZ2FsIHZhbHVlcyBhcmUgbnVtYmVycyBmcm9tIC0xMDAwIHRvIDEwMDAgYW5kIEZvcm1hdFZhbHVlLklOSEVSSVQuPC9wPgogICAgICAgICAqIDxwPkRlZmF1bHQgdmFsdWUgaXMgdW5kZWZpbmVkIGluZGljYXRpbmcgbm90IHNldC48L3A+CiAgICAgICAgICogPHA+SWYgdW5kZWZpbmVkIGR1cmluZyB0aGUgY2FzY2FkZSwgdGhpcyBwcm9wZXJ0eSBpbmhlcml0cyBpdHMgdmFsdWUgZnJvbSBhbiBhbmNlc3Rvci4gSWYgbm8gYW5jZXN0b3IgaGFzIHNldCB0aGlzIHByb3BlcnR5LCBpdCB3aWxsIGhhdmUgYSB2YWx1ZSBvZiA0MC48L3A+CiAgICAgICAgICogCiAgICAgICAgICogQHRocm93cyBSYW5nZUVycm9yIHdoZW4gc2V0IHZhbHVlIGlzIG5vdCB3aXRoaW4gcmFuZ2UgZm9yIHRoaXMgcHJvcGVydHkKICAgICAgICAgKiAKICAgICAgICAgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKICAgICAgICAgKiBAbGFuZ3ZlcnNpb24gMy4wCiAgICAgICAgICovCiAgICAgICAgcHVibGljIGZ1bmN0aW9uIGdldCBsaXN0QXV0b1BhZGRpbmcoKToqCiAgICAgICAgeyByZXR1cm4gX3N0eWxlcy5saXN0QXV0b1BhZGRpbmc7IH0KICAgICAgICBwdWJsaWMgZnVuY3Rpb24gc2V0IGxpc3RBdXRvUGFkZGluZyh2YWx1ZToqKTp2b2lkCiAgICAgICAgeyBzZXRTdHlsZUJ5UHJvcGVydHkoVGV4dExheW91dEZvcm1hdC5saXN0QXV0b1BhZGRpbmdQcm9wZXJ0eSx2YWx1ZSk7IH0KCiAgICAgICAgW0luc3BlY3RhYmxlKGVudW1lcmF0aW9uPSJzdGFydCxlbmQsbGVmdCxyaWdodCxib3RoLG5vbmUsaW5oZXJpdCIpXQogICAgICAgIC8qKgogICAgICAgICAqIENvbnRyb2xzIGhvdyB0ZXh0IHdyYXBzIGFyb3VuZCBhIGZsb2F0LiBBIHZhbHVlIG9mICJub25lIiBhbGxvd3MgdGhlIHRleHQgdG8gd3JhcCBtb3N0IGNsb3NlbHkgYXJvdW5kIGEgZmxvYXQuIEEgdmFsdWUgb2YgImxlZnQiIGNhdXNlcyB0aGUgdGV4dCB0byBza2lwIG92ZXIgYW55IHBvcnRpb24gb2YgdGhlIGNvbnRhaW5lciB0aGF0IGhhcyBhIGxlZnQgZmxvYXQuCiAgICAgICAgICogQSB2YWx1ZSBvZiAicmlnaHQiIGNhdXNlcyB0aGUgdGV4dCB0byBza2lwIG92ZXIgYW55IHBvcnRpb24gb2YgdGhlIGNvbnRhaW5lciB0aGF0IGhhcyBhIHJpZ2h0IGZsb2F0LiBBIHZhbHVlIG9mICJib3RoIiBjYXVzZXMgdGhlIHRleHQgdG8gc2tpcCBvdmVyIGFueSBmbG9hdHMuCiAgICAgICAgICogPHA+TGVnYWwgdmFsdWVzIGFyZSA8Y29kZT5DbGVhckZsb2F0cy5TVEFSVDwvY29kZT4sIDxjb2RlPkNsZWFyRmxvYXRzLkVORDwvY29kZT4sIDxjb2RlPkNsZWFyRmxvYXRzLkxFRlQ8L2NvZGU+LCA8Y29kZT5DbGVhckZsb2F0cy5SSUdIVDwvY29kZT4sIDxjb2RlPkNsZWFyRmxvYXRzLkJPVEg8L2NvZGU+LCAKICAgICAgICAgKiA8Y29kZT5DbGVhckZsb2F0cy5OT05FPC9jb2RlPiwgYW5kIDxjb2RlPkZvcm1hdFZhbHVlLklOSEVSSVQ8L2NvZGU+LjwvcD4KICAgICAgICAgKiAKICAgICAgICAgKiA8cD5EZWZhdWx0IHZhbHVlIGlzIHVuZGVmaW5lZCBpbmRpY2F0aW5nIG5vdCBzZXQuPC9wPgogICAgICAgICAqIAogICAgICAgICAqIDxwPklmIHVuZGVmaW5lZCBkdXJpbmcgdGhlIGNhc2NhZGUsIHRoaXMgcHJvcGVydHkgaGFzIGEgdmFsdWUgb2YgPGNvZGU+Q2xlYXJGbG9hdHMuTk9ORTwvY29kZT4uPC9wPgogICAgICAgICAqIAogICAgICAgICAqIEB0aHJvd3MgUmFuZ2VFcnJvciBXaGVuIHNldCB2YWx1ZSBpcyBub3Qgd2l0aGluIHJhbmdlIGZvciB0aGlzIHByb3BlcnR5LgogICAgICAgICAqIAogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQogICAgICAgICAqIEBsYW5ndmVyc2lvbiAzLjAKICAgICAgICAgKiAKICAgICAgICAgKiBAc2VlIGZsYXNoeC50ZXh0TGF5b3V0LmZvcm1hdHMuQ2xlYXJGbG9hdHMKICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgZnVuY3Rpb24gZ2V0IGNsZWFyRmxvYXRzKCk6KgogICAgICAgIHsgcmV0dXJuIF9zdHlsZXMuY2xlYXJGbG9hdHM7IH0KICAgICAgICBwdWJsaWMgZnVuY3Rpb24gc2V0IGNsZWFyRmxvYXRzKHZhbHVlOiopOnZvaWQKICAgICAgICB7IHNldFN0eWxlQnlQcm9wZXJ0eShUZXh0TGF5b3V0Rm9ybWF0LmNsZWFyRmxvYXRzUHJvcGVydHksdmFsdWUpOyB9CgogICAgICAgIC8qKgogICAgICAgICAqIEFzc2lnbnMgYW4gaWRlbnRpZnlpbmcgY2xhc3MgdG8gdGhlIGVsZW1lbnQsIG1ha2luZyBpdCBwb3NzaWJsZSB0byBzZXQgYSBzdHlsZSBmb3IgdGhlIGVsZW1lbnQgYnkgcmVmZXJlbmNpbmcgdGhlIDxjb2RlPnN0eWxlTmFtZTwvY29kZT4uCiAgICAgICAgICogPHA+RGVmYXVsdCB2YWx1ZSBpcyB1bmRlZmluZWQgaW5kaWNhdGluZyBub3Qgc2V0LjwvcD4KICAgICAgICAgKiA8cD5JZiB1bmRlZmluZWQgZHVyaW5nIHRoZSBjYXNjYWRlLCB0aGlzIHByb3BlcnR5IGhhcyBhIHZhbHVlIG9mIG51bGwuPC9wPgogICAgICAgICAqIAogICAgICAgICAqIEB0aHJvd3MgUmFuZ2VFcnJvciBXaGVuIHNldCB2YWx1ZSBpcyBub3Qgd2l0aGluIHJhbmdlIGZvciB0aGlzIHByb3BlcnR5LgogICAgICAgICAqIAogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQogICAgICAgICAqIEBsYW5ndmVyc2lvbiAzLjAKICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgZnVuY3Rpb24gZ2V0IHN0eWxlTmFtZSgpOioKICAgICAgICB7IHJldHVybiBfc3R5bGVzLnN0eWxlTmFtZTsgfQogICAgICAgIHB1YmxpYyBmdW5jdGlvbiBzZXQgc3R5bGVOYW1lKHZhbHVlOiopOnZvaWQKICAgICAgICB7IHNldFN0eWxlQnlQcm9wZXJ0eShUZXh0TGF5b3V0Rm9ybWF0LnN0eWxlTmFtZVByb3BlcnR5LHZhbHVlKTsgfQoKICAgICAgICAvKioKICAgICAgICAgKiBEZWZpbmVzIHRoZSBmb3JtYXR0aW5nIGF0dHJpYnV0ZXMgdXNlZCBmb3IgbGlua3MgaW4gbm9ybWFsIHN0YXRlLiBUaGlzIHZhbHVlIHdpbGwgY2FzY2FkZSBkb3duIHRoZSBoaWVyYXJjaHkgYW5kIGFwcGx5IHRvIGFueSBsaW5rcyB0aGF0IGFyZSBkZXNjZW5kYW50cy4KICAgICAgICAgKiBBY2NlcHRzIDxjb2RlPmluaGVyaXQ8L2NvZGU+LCBhbiA8Y29kZT5JVGV4dExheW91dEZvcm1hdDwvY29kZT4gb3IgY29udmVydHMgYW4gYXJyYXkgb2Ygb2JqZWN0cyB3aXRoIGtleSBhbmQgdmFsdWUgYXMgbWVtYmVycyB0byBhIFRleHRMYXlvdXRGb3JtYXQuCiAgICAgICAgICogPHA+TGVnYWwgdmFsdWVzIGluY2x1ZGUgRm9ybWF0VmFsdWUuSU5IRVJJVC48L3A+CiAgICAgICAgICogPHA+RGVmYXVsdCB2YWx1ZSBpcyB1bmRlZmluZWQgaW5kaWNhdGluZyBub3Qgc2V0LjwvcD4KICAgICAgICAgKiA8cD5JZiB1bmRlZmluZWQgZHVyaW5nIHRoZSBjYXNjYWRlLCB0aGlzIHByb3BlcnR5IGluaGVyaXRzIGl0cyB2YWx1ZSBmcm9tIGFuIGFuY2VzdG9yLiBJZiBubyBhbmNlc3RvciBoYXMgc2V0IHRoaXMgcHJvcGVydHksIGl0IHdpbGwgaGF2ZSBhIHZhbHVlIG9mIG51bGwuPC9wPgogICAgICAgICAqIAogICAgICAgICAqIEB0aHJvd3MgUmFuZ2VFcnJvciBXaGVuIHNldCB2YWx1ZSBpcyBub3Qgd2l0aGluIHJhbmdlIGZvciB0aGlzIHByb3BlcnR5LgogICAgICAgICAqIAogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQogICAgICAgICAqIEBsYW5ndmVyc2lvbiAzLjAKICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgZnVuY3Rpb24gZ2V0IGxpbmtOb3JtYWxGb3JtYXQoKToqCiAgICAgICAgeyByZXR1cm4gX3N0eWxlcy5saW5rTm9ybWFsRm9ybWF0OyB9CiAgICAgICAgcHVibGljIGZ1bmN0aW9uIHNldCBsaW5rTm9ybWFsRm9ybWF0KHZhbHVlOiopOnZvaWQKICAgICAgICB7IHNldFN0eWxlQnlQcm9wZXJ0eShUZXh0TGF5b3V0Rm9ybWF0LmxpbmtOb3JtYWxGb3JtYXRQcm9wZXJ0eSx2YWx1ZSk7IH0KCiAgICAgICAgLyoqCiAgICAgICAgICogRGVmaW5lcyB0aGUgZm9ybWF0dGluZyBhdHRyaWJ1dGVzIHVzZWQgZm9yIGxpbmtzIGluIG5vcm1hbCBzdGF0ZS4gVGhpcyB2YWx1ZSB3aWxsIGNhc2NhZGUgZG93biB0aGUgaGllcmFyY2h5IGFuZCBhcHBseSB0byBhbnkgbGlua3MgdGhhdCBhcmUgZGVzY2VuZGFudHMuCiAgICAgICAgICogQWNjZXB0cyA8Y29kZT5pbmhlcml0PC9jb2RlPiwgYW4gPGNvZGU+SVRleHRMYXlvdXRGb3JtYXQ8L2NvZGU+IG9yIGNvbnZlcnRzIGFuIGFycmF5IG9mIG9iamVjdHMgd2l0aCBrZXkgYW5kIHZhbHVlIGFzIG1lbWJlcnMgdG8gYSBUZXh0TGF5b3V0Rm9ybWF0LgogICAgICAgICAqIDxwPkxlZ2FsIHZhbHVlcyBpbmNsdWRlIEZvcm1hdFZhbHVlLklOSEVSSVQuPC9wPgogICAgICAgICAqIDxwPkRlZmF1bHQgdmFsdWUgaXMgdW5kZWZpbmVkIGluZGljYXRpbmcgbm90IHNldC48L3A+CiAgICAgICAgICogPHA+SWYgdW5kZWZpbmVkIGR1cmluZyB0aGUgY2FzY2FkZSwgdGhpcyBwcm9wZXJ0eSBpbmhlcml0cyBpdHMgdmFsdWUgZnJvbSBhbiBhbmNlc3Rvci4gSWYgbm8gYW5jZXN0b3IgaGFzIHNldCB0aGlzIHByb3BlcnR5LCBpdCB3aWxsIGhhdmUgYSB2YWx1ZSBvZiBudWxsLjwvcD4KICAgICAgICAgKiAKICAgICAgICAgKiBAdGhyb3dzIFJhbmdlRXJyb3IgV2hlbiBzZXQgdmFsdWUgaXMgbm90IHdpdGhpbiByYW5nZSBmb3IgdGhpcyBwcm9wZXJ0eS4KICAgICAgICAgKiAKICAgICAgICAgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKICAgICAgICAgKiBAbGFuZ3ZlcnNpb24gMy4wCiAgICAgICAgICovCiAgICAgICAgcHVibGljIGZ1bmN0aW9uIGdldCBsaW5rQWN0aXZlRm9ybWF0KCk6KgogICAgICAgIHsgcmV0dXJuIF9zdHlsZXMubGlua0FjdGl2ZUZvcm1hdDsgfQogICAgICAgIHB1YmxpYyBmdW5jdGlvbiBzZXQgbGlua0FjdGl2ZUZvcm1hdCh2YWx1ZToqKTp2b2lkCiAgICAgICAgeyBzZXRTdHlsZUJ5UHJvcGVydHkoVGV4dExheW91dEZvcm1hdC5saW5rQWN0aXZlRm9ybWF0UHJvcGVydHksdmFsdWUpOyB9CgogICAgICAgIC8qKgogICAgICAgICAqIERlZmluZXMgdGhlIGZvcm1hdHRpbmcgYXR0cmlidXRlcyB1c2VkIGZvciBsaW5rcyBpbiBob3ZlciBzdGF0ZSwgd2hlbiB0aGUgbW91c2UgaXMgd2l0aGluIHRoZSBib3VuZHMgKHJvbGxpbmcgb3ZlcikgYSBsaW5rLiBUaGlzIHZhbHVlIHdpbGwgY2FzY2FkZSBkb3duIHRoZSBoaWVyYXJjaHkgYW5kIGFwcGx5IHRvIGFueSBsaW5rcyB0aGF0IGFyZSBkZXNjZW5kYW50cy4KICAgICAgICAgKiBBY2NlcHRzIDxjb2RlPmluaGVyaXQ8L2NvZGU+LCBhbiA8Y29kZT5JVGV4dExheW91dEZvcm1hdDwvY29kZT4gb3IgY29udmVydHMgYW4gYXJyYXkgb2Ygb2JqZWN0cyB3aXRoIGtleSBhbmQgdmFsdWUgYXMgbWVtYmVycyB0byBhIFRleHRMYXlvdXRGb3JtYXQuCiAgICAgICAgICogPHA+TGVnYWwgdmFsdWVzIGluY2x1ZGUgRm9ybWF0VmFsdWUuSU5IRVJJVC48L3A+CiAgICAgICAgICogPHA+RGVmYXVsdCB2YWx1ZSBpcyB1bmRlZmluZWQgaW5kaWNhdGluZyBub3Qgc2V0LjwvcD4KICAgICAgICAgKiA8cD5JZiB1bmRlZmluZWQgZHVyaW5nIHRoZSBjYXNjYWRlIHRoaXMgcHJvcGVydHkgd2lsbCBpbmhlcml0IGl0cyB2YWx1ZSBmcm9tIGFuIGFuY2VzdG9yLiBJZiBubyBhbmNlc3RvciBoYXMgc2V0IHRoaXMgcHJvcGVydHksIGl0IHdpbGwgaGF2ZSBhIHZhbHVlIG9mIG51bGwuPC9wPgogICAgICAgICAqIAogICAgICAgICAqIEB0aHJvd3MgUmFuZ2VFcnJvciBXaGVuIHNldCB2YWx1ZSBpcyBub3Qgd2l0aGluIHJhbmdlIGZvciB0aGlzIHByb3BlcnR5LgogICAgICAgICAqIAogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQogICAgICAgICAqIEBsYW5ndmVyc2lvbiAzLjAKICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgZnVuY3Rpb24gZ2V0IGxpbmtIb3ZlckZvcm1hdCgpOioKICAgICAgICB7IHJldHVybiBfc3R5bGVzLmxpbmtIb3ZlckZvcm1hdDsgfQogICAgICAgIHB1YmxpYyBmdW5jdGlvbiBzZXQgbGlua0hvdmVyRm9ybWF0KHZhbHVlOiopOnZvaWQKICAgICAgICB7IHNldFN0eWxlQnlQcm9wZXJ0eShUZXh0TGF5b3V0Rm9ybWF0LmxpbmtIb3ZlckZvcm1hdFByb3BlcnR5LHZhbHVlKTsgfQoKICAgICAgICAvKioKICAgICAgICAgKiBEZWZpbmVzIHRoZSBmb3JtYXR0aW5nIGF0dHJpYnV0ZXMgbGlzdCBtYXJrZXJzLiBUaGlzIHZhbHVlIHdpbGwgY2FzY2FkZSBkb3duIHRoZSBoaWVyYXJjaHkgYW5kIGFwcGx5IHRvIGFueSBsaW5rcyB0aGF0IGFyZSBkZXNjZW5kYW50cy4KICAgICAgICAgKiBBY2NlcHRzIDxjb2RlPmluaGVyaXQ8L2NvZGU+LCBhbiA8Y29kZT5JTGlzdE1hcmtlckZvcm1hdDwvY29kZT4gb3IgY29udmVydHMgYW4gYXJyYXkgb2Ygb2JqZWN0cyB3aXRoIGtleSBhbmQgdmFsdWUgYXMgbWVtYmVycyB0byBhIExpc3RNYXJrZXJGb3JtYXQuCiAgICAgICAgICogPHA+TGVnYWwgdmFsdWVzIGluY2x1ZGUgRm9ybWF0VmFsdWUuSU5IRVJJVC48L3A+CiAgICAgICAgICogPHA+RGVmYXVsdCB2YWx1ZSBpcyB1bmRlZmluZWQgaW5kaWNhdGluZyBub3Qgc2V0LjwvcD4KICAgICAgICAgKiA8cD5JZiB1bmRlZmluZWQgZHVyaW5nIHRoZSBjYXNjYWRlLCB0aGlzIHByb3BlcnR5IGluaGVyaXRzIGl0cyB2YWx1ZSBmcm9tIGFuIGFuY2VzdG9yLiBJZiBubyBhbmNlc3RvciBoYXMgc2V0IHRoaXMgcHJvcGVydHksIGl0IHdpbGwgaGF2ZSBhIHZhbHVlIG9mIG51bGwuPC9wPgogICAgICAgICAqIAogICAgICAgICAqIEB0aHJvd3MgUmFuZ2VFcnJvciBXaGVuIHNldCB2YWx1ZSBpcyBub3Qgd2l0aGluIHJhbmdlIGZvciB0aGlzIHByb3BlcnR5LgogICAgICAgICAqIAogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEZsYXNoIDEwCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gQUlSIDEuNQogICAgICAgICAqIEBsYW5ndmVyc2lvbiAzLjAKICAgICAgICAgKi8KICAgICAgICBwdWJsaWMgZnVuY3Rpb24gZ2V0IGxpc3RNYXJrZXJGb3JtYXQoKToqCiAgICAgICAgeyByZXR1cm4gX3N0eWxlcy5saXN0TWFya2VyRm9ybWF0OyB9CiAgICAgICAgcHVibGljIGZ1bmN0aW9uIHNldCBsaXN0TWFya2VyRm9ybWF0KHZhbHVlOiopOnZvaWQKICAgICAgICB7IHNldFN0eWxlQnlQcm9wZXJ0eShUZXh0TGF5b3V0Rm9ybWF0Lmxpc3RNYXJrZXJGb3JtYXRQcm9wZXJ0eSx2YWx1ZSk7IH0KCiAgICAgICAgc3RhdGljIHByaXZhdGUgdmFyIF9kZWZhdWx0czpUZXh0TGF5b3V0Rm9ybWF0OwogICAgICAgIC8qKgogICAgICAgICAqIFJldHVybnMgYSBUZXh0TGF5b3V0Rm9ybWF0IG9iamVjdCB3aXRoIGRlZmF1bHQgc2V0dGluZ3MuCiAgICAgICAgICogVGhpcyBtZXRob2QgYWx3YXlzIHJldHVybnMgdGhlIHNhbWUgb2JqZWN0LgogICAgICAgICAqIAogICAgICAgICAqIEByZXR1cm4gQSBzaW5nbGV0b24gaW5zdGFuY2Ugb2YgSVRleHRMYXlvdXRGb3JtYXQgdGhhdCBpcyBwb3B1bGF0ZWQgd2l0aCBkZWZhdWx0IHZhbHVlcy4KICAgICAgICAgKiAKICAgICAgICAgKiBAcGxheWVydmVyc2lvbiBGbGFzaCAxMAogICAgICAgICAqIEBwbGF5ZXJ2ZXJzaW9uIEFJUiAxLjUKICAgICAgICAgKiBAbGFuZ3ZlcnNpb24gMy4wCiAgICAgICAgICovCiAgICAgICAgc3RhdGljIHB1YmxpYyBmdW5jdGlvbiBnZXQgZGVmYXVsdEZvcm1hdCgpOklUZXh0TGF5b3V0Rm9ybWF0CiAgICAgICAgewogICAgICAgICAgICBpZiAoX2RlZmF1bHRzID09IG51bGwpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIF9kZWZhdWx0cyA9IG5ldyBUZXh0TGF5b3V0Rm9ybWF0KCk7CiAgICAgICAgICAgICAgICBQcm9wZXJ0eS5kZWZhdWx0c0FsbEhlbHBlcihfZGVzY3JpcHRpb24sX2RlZmF1bHRzKTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gX2RlZmF1bHRzOwogICAgICAgIH0KCiAgICAgICAgLyoqIEBwcml2YXRlICovCiAgICAgICAgdGxmX2ludGVybmFsIHN0YXRpYyBmdW5jdGlvbiByZXNldE1vZGlmaWVkTm9uaW5oZXJpdGVkU3R5bGVzKHN0eWxlc09iamVjdDpPYmplY3QpOnZvaWQKICAgICAgICB7CiAgICAgICAgICAgIGlmIChzdHlsZXNPYmplY3QuYmFja2dyb3VuZENvbG9yICE9IFRleHRMYXlvdXRGb3JtYXQuYmFja2dyb3VuZENvbG9yUHJvcGVydHkuZGVmYXVsdFZhbHVlKQogICAgICAgICAgICAgICAgc3R5bGVzT2JqZWN0LmJhY2tncm91bmRDb2xvciA9IFRleHRMYXlvdXRGb3JtYXQuYmFja2dyb3VuZENvbG9yUHJvcGVydHkuZGVmYXVsdFZhbHVlOwogICAgICAgICAgICBpZiAoc3R5bGVzT2JqZWN0LmJhY2tncm91bmRBbHBoYSAhPSBUZXh0TGF5b3V0Rm9ybWF0LmJhY2tncm91bmRBbHBoYVByb3BlcnR5LmRlZmF1bHRWYWx1ZSkKICAgICAgICAgICAgICAgIHN0eWxlc09iamVjdC5iYWNrZ3JvdW5kQWxwaGEgPSBUZXh0TGF5b3V0Rm9ybWF0LmJhY2tncm91bmRBbHBoYVByb3BlcnR5LmRlZmF1bHRWYWx1ZTsKICAgICAgICAgICAgaWYgKHN0eWxlc09iamVjdC5jb2x1bW5HYXAgIT0gVGV4dExheW91dEZvcm1hdC5jb2x1bW5HYXBQcm9wZXJ0eS5kZWZhdWx0VmFsdWUpCiAgICAgICAgICAgICAgICBzdHlsZXNPYmplY3QuY29sdW1uR2FwID0gVGV4dExheW91dEZvcm1hdC5jb2x1bW5HYXBQcm9wZXJ0eS5kZWZhdWx0VmFsdWU7CiAgICAgICAgICAgIGlmIChzdHlsZXNPYmplY3QucGFkZGluZ0xlZnQgIT0gVGV4dExheW91dEZvcm1hdC5wYWRkaW5nTGVmdFByb3BlcnR5LmRlZmF1bHRWYWx1ZSkKICAgICAgICAgICAgICAgIHN0eWxlc09iamVjdC5wYWRkaW5nTGVmdCA9IFRleHRMYXlvdXRGb3JtYXQucGFkZGluZ0xlZnRQcm9wZXJ0eS5kZWZhdWx0VmFsdWU7CiAgICAgICAgICAgIGlmIChzdHlsZXNPYmplY3QucGFkZGluZ1RvcCAhPSBUZXh0TGF5b3V0Rm9ybWF0LnBhZGRpbmdUb3BQcm9wZXJ0eS5kZWZhdWx0VmFsdWUpCiAgICAgICAgICAgICAgICBzdHlsZXNPYmplY3QucGFkZGluZ1RvcCA9IFRleHRMYXlvdXRGb3JtYXQucGFkZGluZ1RvcFByb3BlcnR5LmRlZmF1bHRWYWx1ZTsKICAgICAgICAgICAgaWYgKHN0eWxlc09iamVjdC5wYWRkaW5nUmlnaHQgIT0gVGV4dExheW91dEZvcm1hdC5wYWRkaW5nUmlnaHRQcm9wZXJ0eS5kZWZhdWx0VmFsdWUpCiAgICAgICAgICAgICAgICBzdHlsZXNPYmplY3QucGFkZGluZ1JpZ2h0ID0gVGV4dExheW91dEZvcm1hdC5wYWRkaW5nUmlnaHRQcm9wZXJ0eS5kZWZhdWx0VmFsdWU7CiAgICAgICAgICAgIGlmIChzdHlsZXNPYmplY3QucGFkZGluZ0JvdHRvbSAhPSBUZXh0TGF5b3V0Rm9ybWF0LnBhZGRpbmdCb3R0b21Qcm9wZXJ0eS5kZWZhdWx0VmFsdWUpCiAgICAgICAgICAgICAgICBzdHlsZXNPYmplY3QucGFkZGluZ0JvdHRvbSA9IFRleHRMYXlvdXRGb3JtYXQucGFkZGluZ0JvdHRvbVByb3BlcnR5LmRlZmF1bHRWYWx1ZTsKICAgICAgICAgICAgaWYgKHN0eWxlc09iamVjdC5jb2x1bW5Db3VudCAhPSBUZXh0TGF5b3V0Rm9ybWF0LmNvbHVtbkNvdW50UHJvcGVydHkuZGVmYXVsdFZhbHVlKQogICAgICAgICAgICAgICAgc3R5bGVzT2JqZWN0LmNvbHVtbkNvdW50ID0gVGV4dExheW91dEZvcm1hdC5jb2x1bW5Db3VudFByb3BlcnR5LmRlZmF1bHRWYWx1ZTsKICAgICAgICAgICAgaWYgKHN0eWxlc09iamVjdC5jb2x1bW5XaWR0aCAhPSBUZXh0TGF5b3V0Rm9ybWF0LmNvbHVtbldpZHRoUHJvcGVydHkuZGVmYXVsdFZhbHVlKQogICAgICAgICAgICAgICAgc3R5bGVzT2JqZWN0LmNvbHVtbldpZHRoID0gVGV4dExheW91dEZvcm1hdC5jb2x1bW5XaWR0aFByb3BlcnR5LmRlZmF1bHRWYWx1ZTsKICAgICAgICAgICAgaWYgKHN0eWxlc09iamVjdC52ZXJ0aWNhbEFsaWduICE9IFRleHRMYXlvdXRGb3JtYXQudmVydGljYWxBbGlnblByb3BlcnR5LmRlZmF1bHRWYWx1ZSkKICAgICAgICAgICAgICAgIHN0eWxlc09iamVjdC52ZXJ0aWNhbEFsaWduID0gVGV4dExheW91dEZvcm1hdC52ZXJ0aWNhbEFsaWduUHJvcGVydHkuZGVmYXVsdFZhbHVlOwogICAgICAgICAgICBpZiAoc3R5bGVzT2JqZWN0LmxpbmVCcmVhayAhPSBUZXh0TGF5b3V0Rm9ybWF0LmxpbmVCcmVha1Byb3BlcnR5LmRlZmF1bHRWYWx1ZSkKICAgICAgICAgICAgICAgIHN0eWxlc09iamVjdC5saW5lQnJlYWsgPSBUZXh0TGF5b3V0Rm9ybWF0LmxpbmVCcmVha1Byb3BlcnR5LmRlZmF1bHRWYWx1ZTsKICAgICAgICAgICAgaWYgKHN0eWxlc09iamVjdC5jbGVhckZsb2F0cyAhPSBUZXh0TGF5b3V0Rm9ybWF0LmNsZWFyRmxvYXRzUHJvcGVydHkuZGVmYXVsdFZhbHVlKQogICAgICAgICAgICAgICAgc3R5bGVzT2JqZWN0LmNsZWFyRmxvYXRzID0gVGV4dExheW91dEZvcm1hdC5jbGVhckZsb2F0c1Byb3BlcnR5LmRlZmF1bHRWYWx1ZTsKICAgICAgICAgICAgaWYgKHN0eWxlc09iamVjdC5zdHlsZU5hbWUgIT0gVGV4dExheW91dEZvcm1hdC5zdHlsZU5hbWVQcm9wZXJ0eS5kZWZhdWx0VmFsdWUpCiAgICAgICAgICAgICAgICBzdHlsZXNPYmplY3Quc3R5bGVOYW1lID0gVGV4dExheW91dEZvcm1hdC5zdHlsZU5hbWVQcm9wZXJ0eS5kZWZhdWx0VmFsdWU7CiAgICAgICAgfQoKICAgICAgICAvKioKICAgICAgICAgKiBDcmVhdGVzIGEgbmV3IFRleHRMYXlvdXRGb3JtYXQgb2JqZWN0LiBBbGwgc2V0dGluZ3MgYXJlIGVtcHR5IG9yLCBvcHRpb25hbGx5LCBhcmUgaW5pdGlhbGl6ZWQgZnJvbSB0aGUKICAgICAgICAgKiBzdXBwbGllZCA8Y29kZT5pbml0aWFsVmFsdWVzPC9jb2RlPiBvYmplY3QuCiAgICAgICAgICogCiAgICAgICAgICogQHBhcmFtIGluaXRpYWxWYWx1ZXMgT3B0aW9uYWwgaW5zdGFuY2UgZnJvbSB3aGljaCB0byBjb3B5IGluaXRpYWwgdmFsdWVzLCBpZiBhbiBJVGV4dExheW91dEZvcm1hdCBvYmplY3QncyB2YWx1ZXMgYXJlIGNvcGllZC4KICAgICAgICAgKiBPdGhlcndpc2UgdGhpcyBwYXJhbWV0ZXIgaXMgdHJlYXRlZCBsaWtlIGEgRGljdGlvbmFyeSBvciBPYmplY3QgYW5kIGl0ZXJhdGVkIG92ZXIuCiAgICAgICAgICogCiAgICAgICAgICogQHBsYXllcnZlcnNpb24gRmxhc2ggMTAKICAgICAgICAgKiBAcGxheWVydmVyc2lvbiBBSVIgMS41CiAgICAgICAgICogQGxhbmd2ZXJzaW9uIDMuMAogICAgICAgICAqLwogICAgICAgIHB1YmxpYyBzdGF0aWMgZnVuY3Rpb24gY3JlYXRlVGV4dExheW91dEZvcm1hdChpbml0aWFsVmFsdWVzOk9iamVjdCk6VGV4dExheW91dEZvcm1hdAogICAgICAgIHsKICAgICAgICAgICAgdmFyIGZvcm1hdDpJVGV4dExheW91dEZvcm1hdCA9IGluaXRpYWxWYWx1ZXMgYXMgSVRleHRMYXlvdXRGb3JtYXQ7CiAgICAgICAgICAgIHZhciByc2x0OlRleHRMYXlvdXRGb3JtYXQgPSBuZXcgVGV4dExheW91dEZvcm1hdChmb3JtYXQpOwogICAgICAgICAgICBpZiAoZm9ybWF0ID09IG51bGwgJiYgaW5pdGlhbFZhbHVlcykKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgZm9yICh2YXIga2V5OlN0cmluZyBpbiBpbml0aWFsVmFsdWVzKQogICAgICAgICAgICAgICAgICAgIHJzbHQuc2V0U3R5bGUoa2V5LGluaXRpYWxWYWx1ZXNba2V5XSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIHJzbHQ7CiAgICAgICAgfQogICAgfQp9Cg==