Skip to content

Instantly share code, notes, and snippets.

@RamadhanAmizudin
Created May 26, 2015 09:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RamadhanAmizudin/e70f2dae61a5455ee85b to your computer and use it in GitHub Desktop.
Save RamadhanAmizudin/e70f2dae61a5455ee85b to your computer and use it in GitHub Desktop.
Wargames.MY 2015 - Challenge 7 Base64 String
LyoNCiAqIFRoaXMgZmlsZSBoYXMgYmVlbiBjb21tZW50ZWQgdG8gc3VwcG9ydCBWaXN1YWwgU3R1ZGlvIEludGVsbGlzZW5zZS4NCiAqIFlvdSBzaG91bGQgbm90IHVzZSB0aGlzIGZpbGUgYXQgcnVudGltZSBpbnNpZGUgdGhlIGJyb3dzZXItLWl0IGlzIG9ubHkNCiAqIGludGVuZGVkIHRvIGJlIHVzZWQgb25seSBmb3IgZGVzaWduLXRpbWUgSW50ZWxsaVNlbnNlLiAgUGxlYXNlIHVzZSB0aGUNCiAqIHN0YW5kYXJkIGpRdWVyeSBsaWJyYXJ5IGZvciBhbGwgcHJvZHVjdGlvbiB1c2UuDQogKg0KICogQ29tbWVudCB2ZXJzaW9uOiAxLjMuMmINCiAqLw0KDQovKg0KICogalF1ZXJ5IEphdmFTY3JpcHQgTGlicmFyeSB2MS4zLjINCiAqIGh0dHA6Ly9qcXVlcnkuY29tLw0KICoNCiAqIENvcHlyaWdodCAoYykgMjAwOSBKb2huIFJlc2lnDQogKg0KICogUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nDQogKiBhIGNvcHkgb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUNCiAqICJTb2Z0d2FyZSIpLCB0byBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcNCiAqIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwNCiAqIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0bw0KICogcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvDQogKiB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6DQogKg0KICogVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUNCiAqIGluY2x1ZGVkIGluIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLg0KICoNCiAqIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCAiQVMgSVMiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELA0KICogRVhQUkVTUyBPUiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GDQogKiBNRVJDSEFOVEFCSUxJVFksIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORA0KICogTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRQ0KICogTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVIgTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTg0KICogT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9ODQogKiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS4NCiAqDQogKiBEYXRlOiAyMDA5LTAyLTE5IDE3OjM0OjIxIC0wNTAwIChUaHUsIDE5IEZlYiAyMDA5KQ0KICogUmV2aXNpb246IDYyNDYNCiAqLw0KDQooZnVuY3Rpb24oKXsNCg0KdmFyIA0KCS8vIFdpbGwgc3BlZWQgdXAgcmVmZXJlbmNlcyB0byB3aW5kb3csIGFuZCBhbGxvd3MgbXVuZ2luZyBpdHMgbmFtZS4NCgl3aW5kb3cgPSB0aGlzLA0KCS8vIFdpbGwgc3BlZWQgdXAgcmVmZXJlbmNlcyB0byB1bmRlZmluZWQsIGFuZCBhbGxvd3MgbXVuZ2luZyBpdHMgbmFtZS4NCgl1bmRlZmluZWQsDQoJLy8gTWFwIG92ZXIgalF1ZXJ5IGluIGNhc2Ugb2Ygb3ZlcndyaXRlDQoJX2pRdWVyeSA9IHdpbmRvdy5qUXVlcnksDQoJLy8gTWFwIG92ZXIgdGhlICQgaW4gY2FzZSBvZiBvdmVyd3JpdGUNCglfJCA9IHdpbmRvdy4kLA0KDQoJalF1ZXJ5ID0gd2luZG93LmpRdWVyeSA9IHdpbmRvdy4kID0gZnVuY3Rpb24oc2VsZWN0b3IsIGNvbnRleHQpIHsNCiAgICAgICAgLy8vCTxzdW1tYXJ5Pg0KICAgICAgICAvLy8JCTE6ICQoZXhwcmVzc2lvbiwgY29udGV4dCkgLSBUaGlzIGZ1bmN0aW9uIGFjY2VwdHMgYSBzdHJpbmcgY29udGFpbmluZyBhIENTUyBzZWxlY3RvciB3aGljaCBpcyB0aGVuIHVzZWQgdG8gbWF0Y2ggYSBzZXQgb2YgZWxlbWVudHMuDQogICAgICAgIC8vLwkJMjogJChodG1sKSAtIENyZWF0ZSBET00gZWxlbWVudHMgb24tdGhlLWZseSBmcm9tIHRoZSBwcm92aWRlZCBTdHJpbmcgb2YgcmF3IEhUTUwuDQogICAgICAgIC8vLwkJMzogJChlbGVtZW50cykgLSBXcmFwIGpRdWVyeSBmdW5jdGlvbmFsaXR5IGFyb3VuZCBhIHNpbmdsZSBvciBtdWx0aXBsZSBET00gRWxlbWVudChzKS4NCiAgICAgICAgLy8vCQk0OiAkKGNhbGxiYWNrKSAtIEEgc2hvcnRoYW5kIGZvciAkKGRvY3VtZW50KS5yZWFkeSgpLg0KICAgICAgICAvLy8JPC9zdW1tYXJ5Pg0KICAgICAgICAvLy8JPHBhcmFtIG5hbWU9InNlbGVjdG9yIiB0eXBlPSJTdHJpbmciPg0KICAgICAgICAvLy8JCTE6IGV4cHJlc3Npb24gLSBBbiBleHByZXNzaW9uIHRvIHNlYXJjaCB3aXRoLg0KICAgICAgICAvLy8JCTI6IGh0bWwgLSBBIHN0cmluZyBvZiBIVE1MIHRvIGNyZWF0ZSBvbiB0aGUgZmx5Lg0KICAgICAgICAvLy8JCTM6IGVsZW1lbnRzIC0gRE9NIGVsZW1lbnQocykgdG8gYmUgZW5jYXBzdWxhdGVkIGJ5IGEgalF1ZXJ5IG9iamVjdC4NCiAgICAgICAgLy8vCQk0OiBjYWxsYmFjayAtIFRoZSBmdW5jdGlvbiB0byBleGVjdXRlIHdoZW4gdGhlIERPTSBpcyByZWFkeS4NCiAgICAgICAgLy8vCTwvcGFyYW0+DQogICAgICAgIC8vLwk8cGFyYW0gbmFtZT0iY29udGV4dCIgdHlwZT0ialF1ZXJ5Ij4NCiAgICAgICAgLy8vCQkxOiBjb250ZXh0IC0gQSBET00gRWxlbWVudCwgRG9jdW1lbnQgb3IgalF1ZXJ5IHRvIHVzZSBhcyBjb250ZXh0Lg0KICAgICAgICAvLy8JPC9wYXJhbT4NCiAgICAgICAgLy8vIDxmaWVsZCBuYW1lPSJzZWxlY3RvciIgVHlwZT0iT2JqZWN0Ij4NCiAgICAgICAgLy8vICAgICBUaGUgRE9NIG5vZGUgY29udGV4dCBvcmlnaW5hbGx5IHBhc3NlZCB0byBqUXVlcnkoKSAoaWYgbm9uZSB3YXMgcGFzc2VkIHRoZW4gY29udGV4dCB3aWxsIGJlIGVxdWFsIHRvIHRoZSBkb2N1bWVudCkuDQogICAgICAgIC8vLyA8L2ZpZWxkPg0KICAgICAgICAvLy8gPGZpZWxkIG5hbWU9ImNvbnRleHQiIFR5cGU9IlN0cmluZyI+DQogICAgICAgIC8vLyAgICAgQSBzZWxlY3RvciByZXByZXNlbnRpbmcgc2VsZWN0b3Igb3JpZ2luYWxseSBwYXNzZWQgdG8galF1ZXJ5KCkuDQogICAgICAgIC8vLyA8L2ZpZWxkPg0KICAgICAgICAvLy8JPHJldHVybnMgdHlwZT0ialF1ZXJ5IiAvPg0KCQ0KCQkvLyBUaGUgalF1ZXJ5IG9iamVjdCBpcyBhY3R1YWxseSBqdXN0IHRoZSBpbml0IGNvbnN0cnVjdG9yICdlbmhhbmNlZCcNCgkJcmV0dXJuIG5ldyBqUXVlcnkuZm4uaW5pdCggc2VsZWN0b3IsIGNvbnRleHQgKTsNCgl9LA0KDQoJLy8gQSBzaW1wbGUgd2F5IHRvIGNoZWNrIGZvciBIVE1MIHN0cmluZ3Mgb3IgSUQgc3RyaW5ncw0KCS8vIChib3RoIG9mIHdoaWNoIHdlIG9wdGltaXplIGZvcikNCglxdWlja0V4cHIgPSAvXltePF0qKDwoLnxccykrPilbXj5dKiR8XiMoW1x3LV0rKSQvLA0KCS8vIElzIGl0IGEgc2ltcGxlIHNlbGVjdG9yDQoJaXNTaW1wbGUgPSAvXi5bXjojXFtcLixdKiQvOw0KDQpqUXVlcnkuZm4gPSBqUXVlcnkucHJvdG90eXBlID0gew0KCWluaXQ6IGZ1bmN0aW9uKCBzZWxlY3RvciwgY29udGV4dCApIHsNCgkJLy8vCTxzdW1tYXJ5Pg0KCQkvLy8JCTE6ICQoZXhwcmVzc2lvbiwgY29udGV4dCkgLSBUaGlzIGZ1bmN0aW9uIGFjY2VwdHMgYSBzdHJpbmcgY29udGFpbmluZyBhIENTUyBzZWxlY3RvciB3aGljaCBpcyB0aGVuIHVzZWQgdG8gbWF0Y2ggYSBzZXQgb2YgZWxlbWVudHMuDQoJCS8vLwkJMjogJChodG1sKSAtIENyZWF0ZSBET00gZWxlbWVudHMgb24tdGhlLWZseSBmcm9tIHRoZSBwcm92aWRlZCBTdHJpbmcgb2YgcmF3IEhUTUwuDQoJCS8vLwkJMzogJChlbGVtZW50cykgLSBXcmFwIGpRdWVyeSBmdW5jdGlvbmFsaXR5IGFyb3VuZCBhIHNpbmdsZSBvciBtdWx0aXBsZSBET00gRWxlbWVudChzKS4NCgkJLy8vCQk0OiAkKGNhbGxiYWNrKSAtIEEgc2hvcnRoYW5kIGZvciAkKGRvY3VtZW50KS5yZWFkeSgpLg0KCQkvLy8JPC9zdW1tYXJ5Pg0KCQkvLy8JPHBhcmFtIG5hbWU9InNlbGVjdG9yIiB0eXBlPSJTdHJpbmciPg0KCQkvLy8JCTE6IGV4cHJlc3Npb24gLSBBbiBleHByZXNzaW9uIHRvIHNlYXJjaCB3aXRoLg0KCQkvLy8JCTI6IGh0bWwgLSBBIHN0cmluZyBvZiBIVE1MIHRvIGNyZWF0ZSBvbiB0aGUgZmx5Lg0KCQkvLy8JCTM6IGVsZW1lbnRzIC0gRE9NIGVsZW1lbnQocykgdG8gYmUgZW5jYXBzdWxhdGVkIGJ5IGEgalF1ZXJ5IG9iamVjdC4NCgkJLy8vCQk0OiBjYWxsYmFjayAtIFRoZSBmdW5jdGlvbiB0byBleGVjdXRlIHdoZW4gdGhlIERPTSBpcyByZWFkeS4NCgkJLy8vCTwvcGFyYW0+DQoJCS8vLwk8cGFyYW0gbmFtZT0iY29udGV4dCIgdHlwZT0ialF1ZXJ5Ij4NCgkJLy8vCQkxOiBjb250ZXh0IC0gQSBET00gRWxlbWVudCwgRG9jdW1lbnQgb3IgalF1ZXJ5IHRvIHVzZSBhcyBjb250ZXh0Lg0KCQkvLy8JPC9wYXJhbT4NCgkJLy8vCTxyZXR1cm5zIHR5cGU9ImpRdWVyeSIgLz4NCg0KCQkvLyBNYWtlIHN1cmUgdGhhdCBhIHNlbGVjdGlvbiB3YXMgcHJvdmlkZWQNCgkJc2VsZWN0b3IgPSBzZWxlY3RvciB8fCBkb2N1bWVudDsNCg0KCQkvLyBIYW5kbGUgJChET01FbGVtZW50KQ0KCQlpZiAoIHNlbGVjdG9yLm5vZGVUeXBlICkgew0KCQkJdGhpc1swXSA9IHNlbGVjdG9yOw0KCQkJdGhpcy5sZW5ndGggPSAxOw0KCQkJdGhpcy5jb250ZXh0ID0gc2VsZWN0b3I7DQoJCQlyZXR1cm4gdGhpczsNCgkJfQ0KCQkvLyBIYW5kbGUgSFRNTCBzdHJpbmdzDQoJCWlmICh0eXBlb2Ygc2VsZWN0b3IgPT09ICJzdHJpbmciKSB7DQoJCSAgICAvLyBBcmUgd2UgZGVhbGluZyB3aXRoIEhUTUwgc3RyaW5nIG9yIGFuIElEPw0KCQkgICAgdmFyIG1hdGNoID0gcXVpY2tFeHByLmV4ZWMoc2VsZWN0b3IpOw0KDQoJCSAgICAvLyBWZXJpZnkgYSBtYXRjaCwgYW5kIHRoYXQgbm8gY29udGV4dCB3YXMgc3BlY2lmaWVkIGZvciAjaWQNCgkJICAgIGlmIChtYXRjaCAmJiAobWF0Y2hbMV0gfHwgIWNvbnRleHQpKSB7DQoNCgkJICAgICAgICAvLyBIQU5ETEU6ICQoaHRtbCkgLT4gJChhcnJheSkNCgkJICAgICAgICBpZiAobWF0Y2hbMV0pDQoJCSAgICAgICAgICAgIHNlbGVjdG9yID0galF1ZXJ5LmNsZWFuKFttYXRjaFsxXV0sIGNvbnRleHQpOw0KDQoJCSAgICAgICAgLy8gSEFORExFOiAkKCIjaWQiKQ0KCQkgICAgICAgIGVsc2Ugew0KCQkgICAgICAgICAgICB2YXIgZWxlbSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKG1hdGNoWzNdKTsNCg0KCQkgICAgICAgICAgICAvLyBIYW5kbGUgdGhlIGNhc2Ugd2hlcmUgSUUgYW5kIE9wZXJhIHJldHVybiBpdGVtcw0KCQkgICAgICAgICAgICAvLyBieSBuYW1lIGluc3RlYWQgb2YgSUQNCgkJICAgICAgICAgICAgaWYgKGVsZW0gJiYgZWxlbS5pZCAhPSBtYXRjaFszXSkNCgkJICAgICAgICAgICAgICAgIHJldHVybiBqUXVlcnkoKS5maW5kKHNlbGVjdG9yKTsNCg0KCQkgICAgICAgICAgICAvLyBPdGhlcndpc2UsIHdlIGluamVjdCB0aGUgZWxlbWVudCBkaXJlY3RseSBpbnRvIHRoZSBqUXVlcnkgb2JqZWN0DQoJCSAgICAgICAgICAgIHZhciByZXQgPSBqUXVlcnkoZWxlbSB8fCBbXSk7DQoJCSAgICAgICAgICAgIHJldC5jb250ZXh0ID0gZG9jdW1lbnQ7DQoJCSAgICAgICAgICAgIHJldC5zZWxlY3RvciA9IHNlbGVjdG9yOw0KCQkgICAgICAgICAgICByZXR1cm4gcmV0Ow0KCQkgICAgICAgIH0NCg0KCQkgICAgICAgIC8vIEhBTkRMRTogJChleHByLCBbY29udGV4dF0pDQoJCSAgICAgICAgLy8gKHdoaWNoIGlzIGp1c3QgZXF1aXZhbGVudCB0bzogJChjb250ZW50KS5maW5kKGV4cHIpDQoJCSAgICB9IGVsc2UNCgkJICAgICAgICByZXR1cm4galF1ZXJ5KGNvbnRleHQpLmZpbmQoc2VsZWN0b3IpOw0KDQoJCSAgICAvLyBIQU5ETEU6ICQoZnVuY3Rpb24pDQoJCSAgICAvLyBTaG9ydGN1dCBmb3IgZG9jdW1lbnQgcmVhZHkNCgkJfSBlbHNlIGlmICggalF1ZXJ5LmlzRnVuY3Rpb24oIHNlbGVjdG9yICkgKQ0KCQkJcmV0dXJuIGpRdWVyeSggZG9jdW1lbnQgKS5yZWFkeSggc2VsZWN0b3IgKTsNCg0KCQkvLyBNYWtlIHN1cmUgdGhhdCBvbGQgc2VsZWN0b3Igc3RhdGUgaXMgcGFzc2VkIGFsb25nDQoJCWlmICggc2VsZWN0b3Iuc2VsZWN0b3IgJiYgc2VsZWN0b3IuY29udGV4dCApIHsNCgkJCXRoaXMuc2VsZWN0b3IgPSBzZWxlY3Rvci5zZWxlY3RvcjsNCgkJCXRoaXMuY29udGV4dCA9IHNlbGVjdG9yLmNvbnRleHQ7DQoJCX0NCg0KCQlyZXR1cm4gdGhpcy5zZXRBcnJheShqUXVlcnkuaXNBcnJheSggc2VsZWN0b3IgKSA/DQoJCQlzZWxlY3RvciA6DQoJCQlqUXVlcnkubWFrZUFycmF5KHNlbGVjdG9yKSk7DQoJfSwNCg0KCS8vIFN0YXJ0IHdpdGggYW4gZW1wdHkgc2VsZWN0b3INCglzZWxlY3RvcjogIiIsDQoNCgkvLyBUaGUgY3VycmVudCB2ZXJzaW9uIG9mIGpRdWVyeSBiZWluZyB1c2VkDQoJanF1ZXJ5OiAiMS4zLjIiLA0KDQoJLy8gVGhlIG51bWJlciBvZiBlbGVtZW50cyBjb250YWluZWQgaW4gdGhlIG1hdGNoZWQgZWxlbWVudCBzZXQNCglzaXplOiBmdW5jdGlvbigpIHsNCgkJLy8vCTxzdW1tYXJ5Pg0KCQkvLy8JCVRoZSBudW1iZXIgb2YgZWxlbWVudHMgY3VycmVudGx5IG1hdGNoZWQuDQoJCS8vLwkJUGFydCBvZiBDb3JlDQoJCS8vLwk8L3N1bW1hcnk+DQoJCS8vLwk8cmV0dXJucyB0eXBlPSJOdW1iZXIiIC8+DQoNCgkJcmV0dXJuIHRoaXMubGVuZ3RoOw0KCX0sDQoNCgkvLyBHZXQgdGhlIE50aCBlbGVtZW50IGluIHRoZSBtYXRjaGVkIGVsZW1lbnQgc2V0IE9SDQoJLy8gR2V0IHRoZSB3aG9sZSBtYXRjaGVkIGVsZW1lbnQgc2V0IGFzIGEgY2xlYW4gYXJyYXkNCglnZXQ6IGZ1bmN0aW9uKCBudW0gKSB7DQoJCS8vLwk8c3VtbWFyeT4NCgkJLy8vCQlBY2Nlc3MgYSBzaW5nbGUgbWF0Y2hlZCBlbGVtZW50LiBudW0gaXMgdXNlZCB0byBhY2Nlc3MgdGhlDQoJCS8vLwkJTnRoIGVsZW1lbnQgbWF0Y2hlZC4NCgkJLy8vCQlQYXJ0IG9mIENvcmUNCgkJLy8vCTwvc3VtbWFyeT4NCgkJLy8vCTxyZXR1cm5zIHR5cGU9IkVsZW1lbnQiIC8+DQoJCS8vLwk8cGFyYW0gbmFtZT0ibnVtIiB0eXBlPSJOdW1iZXIiPg0KCQkvLy8JCUFjY2VzcyB0aGUgZWxlbWVudCBpbiB0aGUgTnRoIHBvc2l0aW9uLg0KCQkvLy8JPC9wYXJhbT4NCg0KCQlyZXR1cm4gbnVtID09IHVuZGVmaW5lZCA/DQoNCgkJCS8vIFJldHVybiBhICdjbGVhbicgYXJyYXkNCgkJCUFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKCB0aGlzICkgOg0KDQoJCQkvLyBSZXR1cm4ganVzdCB0aGUgb2JqZWN0DQoJCQl0aGlzWyBudW0gXTsNCgl9LA0KDQoJLy8gVGFrZSBhbiBhcnJheSBvZiBlbGVtZW50cyBhbmQgcHVzaCBpdCBvbnRvIHRoZSBzdGFjaw0KCS8vIChyZXR1cm5pbmcgdGhlIG5ldyBtYXRjaGVkIGVsZW1lbnQgc2V0KQ0KCXB1c2hTdGFjazogZnVuY3Rpb24oIGVsZW1zLCBuYW1lLCBzZWxlY3RvciApIHsNCgkJLy8vCTxzdW1tYXJ5Pg0KCQkvLy8JCVNldCB0aGUgalF1ZXJ5IG9iamVjdCB0byBhbiBhcnJheSBvZiBlbGVtZW50cywgd2hpbGUgbWFpbnRhaW5pbmcNCgkJLy8vCQl0aGUgc3RhY2suDQoJCS8vLwkJUGFydCBvZiBDb3JlDQoJCS8vLwk8L3N1bW1hcnk+DQoJCS8vLwk8cmV0dXJucyB0eXBlPSJqUXVlcnkiIC8+DQoJCS8vLwk8cGFyYW0gbmFtZT0iZWxlbXMiIHR5cGU9IkVsZW1lbnRzIj4NCgkJLy8vCQlBbiBhcnJheSBvZiBlbGVtZW50cw0KCQkvLy8JPC9wYXJhbT4NCgkJDQoJCS8vIEJ1aWxkIGEgbmV3IGpRdWVyeSBtYXRjaGVkIGVsZW1lbnQgc2V0DQoJCXZhciByZXQgPSBqUXVlcnkoIGVsZW1zICk7DQoNCgkJLy8gQWRkIHRoZSBvbGQgb2JqZWN0IG9udG8gdGhlIHN0YWNrIChhcyBhIHJlZmVyZW5jZSkNCgkJcmV0LnByZXZPYmplY3QgPSB0aGlzOw0KDQoJCXJldC5jb250ZXh0ID0gdGhpcy5jb250ZXh0Ow0KDQoJCWlmICggbmFtZSA9PT0gImZpbmQiICkNCgkJCXJldC5zZWxlY3RvciA9IHRoaXMuc2VsZWN0b3IgKyAodGhpcy5zZWxlY3RvciA/ICIgIiA6ICIiKSArIHNlbGVjdG9yOw0KCQllbHNlIGlmICggbmFtZSApDQoJCQlyZXQuc2VsZWN0b3IgPSB0aGlzLnNlbGVjdG9yICsgIi4iICsgbmFtZSArICIoIiArIHNlbGVjdG9yICsgIikiOw0KDQoJCS8vIFJldHVybiB0aGUgbmV3bHktZm9ybWVkIGVsZW1lbnQgc2V0DQoJCXJldHVybiByZXQ7DQoJfSwNCg0KCS8vIEZvcmNlIHRoZSBjdXJyZW50IG1hdGNoZWQgc2V0IG9mIGVsZW1lbnRzIHRvIGJlY29tZQ0KCS8vIHRoZSBzcGVjaWZpZWQgYXJyYXkgb2YgZWxlbWVudHMgKGRlc3Ryb3lpbmcgdGhlIHN0YWNrIGluIHRoZSBwcm9jZXNzKQ0KCS8vIFlvdSBzaG91bGQgdXNlIHB1c2hTdGFjaygpIGluIG9yZGVyIHRvIGRvIHRoaXMsIGJ1dCBtYWludGFpbiB0aGUgc3RhY2sNCglzZXRBcnJheTogZnVuY3Rpb24oIGVsZW1zICkgew0KCQkvLy8JPHN1bW1hcnk+DQoJCS8vLwkJU2V0IHRoZSBqUXVlcnkgb2JqZWN0IHRvIGFuIGFycmF5IG9mIGVsZW1lbnRzLiBUaGlzIG9wZXJhdGlvbiBpcw0KCQkvLy8JCWNvbXBsZXRlbHkgZGVzdHJ1Y3RpdmUgLSBiZSBzdXJlIHRvIHVzZSAucHVzaFN0YWNrKCkgaWYgeW91IHdpc2ggdG8gbWFpbnRhaW4NCgkJLy8vCQl0aGUgalF1ZXJ5IHN0YWNrLg0KCQkvLy8JCVBhcnQgb2YgQ29yZQ0KCQkvLy8JPC9zdW1tYXJ5Pg0KCQkvLy8JPHJldHVybnMgdHlwZT0ialF1ZXJ5IiAvPg0KCQkvLy8JPHBhcmFtIG5hbWU9ImVsZW1zIiB0eXBlPSJFbGVtZW50cyI+DQoJCS8vLwkJQW4gYXJyYXkgb2YgZWxlbWVudHMNCgkJLy8vCTwvcGFyYW0+DQoJCQ0KCQkvLyBSZXNldHRpbmcgdGhlIGxlbmd0aCB0byAwLCB0aGVuIHVzaW5nIHRoZSBuYXRpdmUgQXJyYXkgcHVzaA0KCQkvLyBpcyBhIHN1cGVyLWZhc3Qgd2F5IHRvIHBvcHVsYXRlIGFuIG9iamVjdCB3aXRoIGFycmF5LWxpa2UgcHJvcGVydGllcw0KCQl0aGlzLmxlbmd0aCA9IDA7DQoJCUFycmF5LnByb3RvdHlwZS5wdXNoLmFwcGx5KCB0aGlzLCBlbGVtcyApOw0KDQoJCXJldHVybiB0aGlzOw0KCX0sDQoNCgkvLyBFeGVjdXRlIGEgY2FsbGJhY2sgZm9yIGV2ZXJ5IGVsZW1lbnQgaW4gdGhlIG1hdGNoZWQgc2V0Lg0KCS8vIChZb3UgY2FuIHNlZWQgdGhlIGFyZ3VtZW50cyB3aXRoIGFuIGFycmF5IG9mIGFyZ3MsIGJ1dCB0aGlzIGlzDQoJLy8gb25seSB1c2VkIGludGVybmFsbHkuKQ0KCWVhY2g6IGZ1bmN0aW9uKCBjYWxsYmFjaywgYXJncyApIHsNCgkJLy8vCTxzdW1tYXJ5Pg0KCQkvLy8JCUV4ZWN1dGUgYSBmdW5jdGlvbiB3aXRoaW4gdGhlIGNvbnRleHQgb2YgZXZlcnkgbWF0Y2hlZCBlbGVtZW50Lg0KCQkvLy8JCVRoaXMgbWVhbnMgdGhhdCBldmVyeSB0aW1lIHRoZSBwYXNzZWQtaW4gZnVuY3Rpb24gaXMgZXhlY3V0ZWQNCgkJLy8vCQkod2hpY2ggaXMgb25jZSBmb3IgZXZlcnkgZWxlbWVudCBtYXRjaGVkKSB0aGUgJ3RoaXMnIGtleXdvcmQNCgkJLy8vCQlwb2ludHMgdG8gdGhlIHNwZWNpZmljIGVsZW1lbnQuDQoJCS8vLwkJQWRkaXRpb25hbGx5LCB0aGUgZnVuY3Rpb24sIHdoZW4gZXhlY3V0ZWQsIGlzIHBhc3NlZCBhIHNpbmdsZQ0KCQkvLy8JCWFyZ3VtZW50IHJlcHJlc2VudGluZyB0aGUgcG9zaXRpb24gb2YgdGhlIGVsZW1lbnQgaW4gdGhlIG1hdGNoZWQNCgkJLy8vCQlzZXQuDQoJCS8vLwkJUGFydCBvZiBDb3JlDQoJCS8vLwk8L3N1bW1hcnk+DQoJCS8vLwk8cmV0dXJucyB0eXBlPSJqUXVlcnkiIC8+DQoJCS8vLwk8cGFyYW0gbmFtZT0iY2FsbGJhY2siIHR5cGU9IkZ1bmN0aW9uIj4NCgkJLy8vCQlBIGZ1bmN0aW9uIHRvIGV4ZWN1dGUNCgkJLy8vCTwvcGFyYW0+DQoNCgkJcmV0dXJuIGpRdWVyeS5lYWNoKCB0aGlzLCBjYWxsYmFjaywgYXJncyApOw0KCX0sDQoNCgkvLyBEZXRlcm1pbmUgdGhlIHBvc2l0aW9uIG9mIGFuIGVsZW1lbnQgd2l0aGluDQoJLy8gdGhlIG1hdGNoZWQgc2V0IG9mIGVsZW1lbnRzDQoJaW5kZXg6IGZ1bmN0aW9uKCBlbGVtICkgew0KCQkvLy8JPHN1bW1hcnk+DQoJCS8vLwkJU2VhcmNoZXMgZXZlcnkgbWF0Y2hlZCBlbGVtZW50IGZvciB0aGUgb2JqZWN0IGFuZCByZXR1cm5zDQoJCS8vLwkJdGhlIGluZGV4IG9mIHRoZSBlbGVtZW50LCBpZiBmb3VuZCwgc3RhcnRpbmcgd2l0aCB6ZXJvLiANCgkJLy8vCQlSZXR1cm5zIC0xIGlmIHRoZSBvYmplY3Qgd2Fzbid0IGZvdW5kLg0KCQkvLy8JCVBhcnQgb2YgQ29yZQ0KCQkvLy8JPC9zdW1tYXJ5Pg0KCQkvLy8JPHJldHVybnMgdHlwZT0iTnVtYmVyIiAvPg0KCQkvLy8JPHBhcmFtIG5hbWU9ImVsZW0iIHR5cGU9IkVsZW1lbnQiPg0KCQkvLy8JCU9iamVjdCB0byBzZWFyY2ggZm9yDQoJCS8vLwk8L3BhcmFtPg0KDQoJCS8vIExvY2F0ZSB0aGUgcG9zaXRpb24gb2YgdGhlIGRlc2lyZWQgZWxlbWVudA0KCQlyZXR1cm4galF1ZXJ5LmluQXJyYXkoDQoJCQkvLyBJZiBpdCByZWNlaXZlcyBhIGpRdWVyeSBvYmplY3QsIHRoZSBmaXJzdCBlbGVtZW50IGlzIHVzZWQNCgkJCWVsZW0gJiYgZWxlbS5qcXVlcnkgPyBlbGVtWzBdIDogZWxlbQ0KCQksIHRoaXMgKTsNCgl9LA0KDQoJYXR0cjogZnVuY3Rpb24oIG5hbWUsIHZhbHVlLCB0eXBlICkgew0KCQkvLy8JPHN1bW1hcnk+DQoJCS8vLwkJU2V0IGEgc2luZ2xlIHByb3BlcnR5IHRvIGEgY29tcHV0ZWQgdmFsdWUsIG9uIGFsbCBtYXRjaGVkIGVsZW1lbnRzLg0KCQkvLy8JCUluc3RlYWQgb2YgYSB2YWx1ZSwgYSBmdW5jdGlvbiBpcyBwcm92aWRlZCwgdGhhdCBjb21wdXRlcyB0aGUgdmFsdWUuDQoJCS8vLwkJUGFydCBvZiBET00vQXR0cmlidXRlcw0KCQkvLy8JPC9zdW1tYXJ5Pg0KCQkvLy8JPHJldHVybnMgdHlwZT0ialF1ZXJ5IiAvPg0KCQkvLy8JPHBhcmFtIG5hbWU9Im5hbWUiIHR5cGU9IlN0cmluZyI+DQoJCS8vLwkJVGhlIG5hbWUgb2YgdGhlIHByb3BlcnR5IHRvIHNldC4NCgkJLy8vCTwvcGFyYW0+DQoJCS8vLwk8cGFyYW0gbmFtZT0idmFsdWUiIHR5cGU9IkZ1bmN0aW9uIj4NCgkJLy8vCQlBIGZ1bmN0aW9uIHJldHVybmluZyB0aGUgdmFsdWUgdG8gc2V0Lg0KCQkvLy8JPC9wYXJhbT4NCg0KCQl2YXIgb3B0aW9ucyA9IG5hbWU7DQoNCgkJLy8gTG9vayBmb3IgdGhlIGNhc2Ugd2hlcmUgd2UncmUgYWNjZXNzaW5nIGEgc3R5bGUgdmFsdWUNCgkJaWYgKCB0eXBlb2YgbmFtZSA9PT0gInN0cmluZyIgKQ0KCQkJaWYgKCB2YWx1ZSA9PT0gdW5kZWZpbmVkICkNCgkJCQlyZXR1cm4gdGhpc1swXSAmJiBqUXVlcnlbIHR5cGUgfHwgImF0dHIiIF0oIHRoaXNbMF0sIG5hbWUgKTsNCg0KCQkJZWxzZSB7DQoJCQkJb3B0aW9ucyA9IHt9Ow0KCQkJCW9wdGlvbnNbIG5hbWUgXSA9IHZhbHVlOw0KCQkJfQ0KDQoJCS8vIENoZWNrIHRvIHNlZSBpZiB3ZSdyZSBzZXR0aW5nIHN0eWxlIHZhbHVlcw0KCQlyZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uKGkpew0KCQkJLy8gU2V0IGFsbCB0aGUgc3R5bGVzDQoJCQlmb3IgKCBuYW1lIGluIG9wdGlvbnMgKQ0KCQkJCWpRdWVyeS5hdHRyKA0KCQkJCQl0eXBlID8NCgkJCQkJCXRoaXMuc3R5bGUgOg0KCQkJCQkJdGhpcywNCgkJCQkJbmFtZSwgalF1ZXJ5LnByb3AoIHRoaXMsIG9wdGlvbnNbIG5hbWUgXSwgdHlwZSwgaSwgbmFtZSApDQoJCQkJKTsNCgkJfSk7DQoJfSwNCg0KCWNzczogZnVuY3Rpb24oIGtleSwgdmFsdWUgKSB7DQoJCS8vLwk8c3VtbWFyeT4NCgkJLy8vCQlTZXQgYSBzaW5nbGUgc3R5bGUgcHJvcGVydHkgdG8gYSB2YWx1ZSwgb24gYWxsIG1hdGNoZWQgZWxlbWVudHMuDQoJCS8vLwkJSWYgYSBudW1iZXIgaXMgcHJvdmlkZWQsIGl0IGlzIGF1dG9tYXRpY2FsbHkgY29udmVydGVkIGludG8gYSBwaXhlbCB2YWx1ZS4NCgkJLy8vCQlQYXJ0IG9mIENTUw0KCQkvLy8JPC9zdW1tYXJ5Pg0KCQkvLy8JPHJldHVybnMgdHlwZT0ialF1ZXJ5IiAvPg0KCQkvLy8JPHBhcmFtIG5hbWU9ImtleSIgdHlwZT0iU3RyaW5nIj4NCgkJLy8vCQlUaGUgbmFtZSBvZiB0aGUgcHJvcGVydHkgdG8gc2V0Lg0KCQkvLy8JPC9wYXJhbT4NCgkJLy8vCTxwYXJhbSBuYW1lPSJ2YWx1ZSIgdHlwZT0iU3RyaW5nIj4NCgkJLy8vCQlUaGUgdmFsdWUgdG8gc2V0IHRoZSBwcm9wZXJ0eSB0by4NCgkJLy8vCTwvcGFyYW0+DQoNCgkJLy8gaWdub3JlIG5lZ2F0aXZlIHdpZHRoIGFuZCBoZWlnaHQgdmFsdWVzDQoJCWlmICggKGtleSA9PSAnd2lkdGgnIHx8IGtleSA9PSAnaGVpZ2h0JykgJiYgcGFyc2VGbG9hdCh2YWx1ZSkgPCAwICkNCgkJCXZhbHVlID0gdW5kZWZpbmVkOw0KCQlyZXR1cm4gdGhpcy5hdHRyKCBrZXksIHZhbHVlLCAiY3VyQ1NTIiApOw0KCX0sDQoNCgl0ZXh0OiBmdW5jdGlvbiggdGV4dCApIHsNCgkJLy8vCTxzdW1tYXJ5Pg0KCQkvLy8JCVNldCB0aGUgdGV4dCBjb250ZW50cyBvZiBhbGwgbWF0Y2hlZCBlbGVtZW50cy4NCgkJLy8vCQlTaW1pbGFyIHRvIGh0bWwoKSwgYnV0IGVzY2FwZXMgSFRNTCAocmVwbGFjZSAmcXVvdDsmbHQ7JnF1b3Q7IGFuZCAmcXVvdDsmZ3Q7JnF1b3Q7IHdpdGggdGhlaXINCgkJLy8vCQlIVE1MIGVudGl0aWVzKS4NCgkJLy8vCQlQYXJ0IG9mIERPTS9BdHRyaWJ1dGVzDQoJCS8vLwk8L3N1bW1hcnk+DQoJCS8vLwk8cmV0dXJucyB0eXBlPSJTdHJpbmciIC8+DQoJCS8vLwk8cGFyYW0gbmFtZT0idGV4dCIgdHlwZT0iU3RyaW5nIj4NCgkJLy8vCQlUaGUgdGV4dCB2YWx1ZSB0byBzZXQgdGhlIGNvbnRlbnRzIG9mIHRoZSBlbGVtZW50IHRvLg0KCQkvLy8JPC9wYXJhbT4NCg0KCQlpZiAoIHR5cGVvZiB0ZXh0ICE9PSAib2JqZWN0IiAmJiB0ZXh0ICE9IG51bGwgKQ0KCQkJcmV0dXJuIHRoaXMuZW1wdHkoKS5hcHBlbmQoICh0aGlzWzBdICYmIHRoaXNbMF0ub3duZXJEb2N1bWVudCB8fCBkb2N1bWVudCkuY3JlYXRlVGV4dE5vZGUoIHRleHQgKSApOw0KDQoJCXZhciByZXQgPSAiIjsNCg0KCQlqUXVlcnkuZWFjaCggdGV4dCB8fCB0aGlzLCBmdW5jdGlvbigpew0KCQkJalF1ZXJ5LmVhY2goIHRoaXMuY2hpbGROb2RlcywgZnVuY3Rpb24oKXsNCgkJCQlpZiAoIHRoaXMubm9kZVR5cGUgIT0gOCApDQoJCQkJCXJldCArPSB0aGlzLm5vZGVUeXBlICE9IDEgPw0KCQkJCQkJdGhpcy5ub2RlVmFsdWUgOg0KCQkJCQkJalF1ZXJ5LmZuLnRleHQoIFsgdGhpcyBdICk7DQoJCQl9KTsNCgkJfSk7DQoNCgkJcmV0dXJuIHJldDsNCgl9LA0KDQoJd3JhcEFsbDogZnVuY3Rpb24oIGh0bWwgKSB7DQoJCS8vLwk8c3VtbWFyeT4NCgkJLy8vCQlXcmFwIGFsbCBtYXRjaGVkIGVsZW1lbnRzIHdpdGggYSBzdHJ1Y3R1cmUgb2Ygb3RoZXIgZWxlbWVudHMuDQoJCS8vLwkJVGhpcyB3cmFwcGluZyBwcm9jZXNzIGlzIG1vc3QgdXNlZnVsIGZvciBpbmplY3RpbmcgYWRkaXRpb25hbA0KCQkvLy8JCXN0dWN0dXJlIGludG8gYSBkb2N1bWVudCwgd2l0aG91dCBydWluaW5nIHRoZSBvcmlnaW5hbCBzZW1hbnRpYw0KCQkvLy8JCXF1YWxpdGllcyBvZiBhIGRvY3VtZW50Lg0KCQkvLy8JCVRoaXMgd29ya3MgYnkgZ29pbmcgdGhyb3VnaCB0aGUgZmlyc3QgZWxlbWVudA0KCQkvLy8JCXByb3ZpZGVkIGFuZCBmaW5kaW5nIHRoZSBkZWVwZXN0IGFuY2VzdG9yIGVsZW1lbnQgd2l0aGluIGl0cw0KCQkvLy8JCXN0cnVjdHVyZSAtIGl0IGlzIHRoYXQgZWxlbWVudCB0aGF0IHdpbGwgZW4td3JhcCBldmVyeXRoaW5nIGVsc2UuDQoJCS8vLwkJVGhpcyBkb2VzIG5vdCB3b3JrIHdpdGggZWxlbWVudHMgdGhhdCBjb250YWluIHRleHQuIEFueSBuZWNlc3NhcnkgdGV4dA0KCQkvLy8JCW11c3QgYmUgYWRkZWQgYWZ0ZXIgdGhlIHdyYXBwaW5nIGlzIGRvbmUuDQoJCS8vLwkJUGFydCBvZiBET00vTWFuaXB1bGF0aW9uDQoJCS8vLwk8L3N1bW1hcnk+DQoJCS8vLwk8cmV0dXJucyB0eXBlPSJqUXVlcnkiIC8+DQoJCS8vLwk8cGFyYW0gbmFtZT0iaHRtbCIgdHlwZT0iRWxlbWVudCI+DQoJCS8vLwkJQSBET00gZWxlbWVudCB0aGF0IHdpbGwgYmUgd3JhcHBlZCBhcm91bmQgdGhlIHRhcmdldC4NCgkJLy8vCTwvcGFyYW0+DQoNCgkJaWYgKCB0aGlzWzBdICkgew0KCQkJLy8gVGhlIGVsZW1lbnRzIHRvIHdyYXAgdGhlIHRhcmdldCBhcm91bmQNCgkJCXZhciB3cmFwID0galF1ZXJ5KCBodG1sLCB0aGlzWzBdLm93bmVyRG9jdW1lbnQgKS5jbG9uZSgpOw0KDQoJCQlpZiAoIHRoaXNbMF0ucGFyZW50Tm9kZSApDQoJCQkJd3JhcC5pbnNlcnRCZWZvcmUoIHRoaXNbMF0gKTsNCg0KCQkJd3JhcC5tYXAoZnVuY3Rpb24oKXsNCgkJCQl2YXIgZWxlbSA9IHRoaXM7DQoNCgkJCQl3aGlsZSAoIGVsZW0uZmlyc3RDaGlsZCApDQoJCQkJCWVsZW0gPSBlbGVtLmZpcnN0Q2hpbGQ7DQoNCgkJCQlyZXR1cm4gZWxlbTsNCgkJCX0pLmFwcGVuZCh0aGlzKTsNCgkJfQ0KDQoJCXJldHVybiB0aGlzOw0KCX0sDQoNCgl3cmFwSW5uZXI6IGZ1bmN0aW9uKCBodG1sICkgew0KCQkvLy8JPHN1bW1hcnk+DQoJCS8vLwkJV3JhcHMgdGhlIGlubmVyIGNoaWxkIGNvbnRlbnRzIG9mIGVhY2ggbWF0Y2hlZCBlbGVtZW5odCAoaW5jbHVkaW5nIHRleHQgbm9kZXMpIHdpdGggYW4gSFRNTCBzdHJ1Y3R1cmUuDQoJCS8vLwk8L3N1bW1hcnk+DQoJCS8vLwk8cGFyYW0gbmFtZT0iaHRtbCIgdHlwZT0iU3RyaW5nIj4NCgkJLy8vCQlBIHN0cmluZyBvZiBIVE1MIG9yIGEgRE9NIGVsZW1lbnQgdGhhdCB3aWxsIGJlIHdyYXBwZWQgYXJvdW5kIHRoZSB0YXJnZXQgY29udGVudHMuDQoJCS8vLwk8L3BhcmFtPg0KCQkvLy8JPHJldHVybnMgdHlwZT0ialF1ZXJ5IiAvPg0KDQoJCXJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24oKXsNCgkJCWpRdWVyeSggdGhpcyApLmNvbnRlbnRzKCkud3JhcEFsbCggaHRtbCApOw0KCQl9KTsNCgl9LA0KDQoJd3JhcDogZnVuY3Rpb24oIGh0bWwgKSB7DQoJCS8vLwk8c3VtbWFyeT4NCgkJLy8vCQlXcmFwIGFsbCBtYXRjaGVkIGVsZW1lbnRzIHdpdGggYSBzdHJ1Y3R1cmUgb2Ygb3RoZXIgZWxlbWVudHMuDQoJCS8vLwkJVGhpcyB3cmFwcGluZyBwcm9jZXNzIGlzIG1vc3QgdXNlZnVsIGZvciBpbmplY3RpbmcgYWRkaXRpb25hbA0KCQkvLy8JCXN0dWN0dXJlIGludG8gYSBkb2N1bWVudCwgd2l0aG91dCBydWluaW5nIHRoZSBvcmlnaW5hbCBzZW1hbnRpYw0KCQkvLy8JCXF1YWxpdGllcyBvZiBhIGRvY3VtZW50Lg0KCQkvLy8JCVRoaXMgd29ya3MgYnkgZ29pbmcgdGhyb3VnaCB0aGUgZmlyc3QgZWxlbWVudA0KCQkvLy8JCXByb3ZpZGVkIGFuZCBmaW5kaW5nIHRoZSBkZWVwZXN0IGFuY2VzdG9yIGVsZW1lbnQgd2l0aGluIGl0cw0KCQkvLy8JCXN0cnVjdHVyZSAtIGl0IGlzIHRoYXQgZWxlbWVudCB0aGF0IHdpbGwgZW4td3JhcCBldmVyeXRoaW5nIGVsc2UuDQoJCS8vLwkJVGhpcyBkb2VzIG5vdCB3b3JrIHdpdGggZWxlbWVudHMgdGhhdCBjb250YWluIHRleHQuIEFueSBuZWNlc3NhcnkgdGV4dA0KCQkvLy8JCW11c3QgYmUgYWRkZWQgYWZ0ZXIgdGhlIHdyYXBwaW5nIGlzIGRvbmUuDQoJCS8vLwkJUGFydCBvZiBET00vTWFuaXB1bGF0aW9uDQoJCS8vLwk8L3N1bW1hcnk+DQoJCS8vLwk8cmV0dXJucyB0eXBlPSJqUXVlcnkiIC8+DQoJCS8vLwk8cGFyYW0gbmFtZT0iaHRtbCIgdHlwZT0iRWxlbWVudCI+DQoJCS8vLwkJQSBET00gZWxlbWVudCB0aGF0IHdpbGwgYmUgd3JhcHBlZCBhcm91bmQgdGhlIHRhcmdldC4NCgkJLy8vCTwvcGFyYW0+DQoJCQ0KCQlyZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uKCl7DQoJCQlqUXVlcnkoIHRoaXMgKS53cmFwQWxsKCBodG1sICk7DQoJCX0pOw0KCX0sDQoNCglhcHBlbmQ6IGZ1bmN0aW9uKCkgew0KCQkvLy8JPHN1bW1hcnk+DQoJCS8vLwkJQXBwZW5kIGNvbnRlbnQgdG8gdGhlIGluc2lkZSBvZiBldmVyeSBtYXRjaGVkIGVsZW1lbnQuDQoJCS8vLwkJVGhpcyBvcGVyYXRpb24gaXMgc2ltaWxhciB0byBkb2luZyBhbiBhcHBlbmRDaGlsZCB0byBhbGwgdGhlDQoJCS8vLwkJc3BlY2lmaWVkIGVsZW1lbnRzLCBhZGRpbmcgdGhlbSBpbnRvIHRoZSBkb2N1bWVudC4NCgkJLy8vCQlQYXJ0IG9mIERPTS9NYW5pcHVsYXRpb24NCgkJLy8vCTwvc3VtbWFyeT4NCgkJLy8vCTxyZXR1cm5zIHR5cGU9ImpRdWVyeSIgLz4NCgkJLy8vCTxwYXJhbSBuYW1lPSJjb250ZW50IiB0eXBlPSJDb250ZW50Ij4NCgkJLy8vCQlDb250ZW50IHRvIGFwcGVuZCB0byB0aGUgdGFyZ2V0DQoJCS8vLwk8L3BhcmFtPg0KDQoJCXJldHVybiB0aGlzLmRvbU1hbmlwKGFyZ3VtZW50cywgdHJ1ZSwgZnVuY3Rpb24oZWxlbSl7DQoJCQlpZiAodGhpcy5ub2RlVHlwZSA9PSAxKQ0KCQkJCXRoaXMuYXBwZW5kQ2hpbGQoIGVsZW0gKTsNCgkJfSk7DQoJfSwNCg0KCXByZXBlbmQ6IGZ1bmN0aW9uKCkgew0KCQkvLy8JPHN1bW1hcnk+DQoJCS8vLwkJUHJlcGVuZCBjb250ZW50IHRvIHRoZSBpbnNpZGUgb2YgZXZlcnkgbWF0Y2hlZCBlbGVtZW50Lg0KCQkvLy8JCVRoaXMgb3BlcmF0aW9uIGlzIHRoZSBiZXN0IHdheSB0byBpbnNlcnQgZWxlbWVudHMNCgkJLy8vCQlpbnNpZGUsIGF0IHRoZSBiZWdpbm5pbmcsIG9mIGFsbCBtYXRjaGVkIGVsZW1lbnRzLg0KCQkvLy8JCVBhcnQgb2YgRE9NL01hbmlwdWxhdGlvbg0KCQkvLy8JPC9zdW1tYXJ5Pg0KCQkvLy8JPHJldHVybnMgdHlwZT0ialF1ZXJ5IiAvPg0KCQkvLy8JPHBhcmFtIG5hbWU9IiIgdHlwZT0iQ29udGVudCI+DQoJCS8vLwkJQ29udGVudCB0byBwcmVwZW5kIHRvIHRoZSB0YXJnZXQuDQoJCS8vLwk8L3BhcmFtPg0KDQoJCXJldHVybiB0aGlzLmRvbU1hbmlwKGFyZ3VtZW50cywgdHJ1ZSwgZnVuY3Rpb24oZWxlbSl7DQoJCQlpZiAodGhpcy5ub2RlVHlwZSA9PSAxKQ0KCQkJCXRoaXMuaW5zZXJ0QmVmb3JlKCBlbGVtLCB0aGlzLmZpcnN0Q2hpbGQgKTsNCgkJfSk7DQoJfSwNCg0KCWJlZm9yZTogZnVuY3Rpb24oKSB7DQoJCS8vLwk8c3VtbWFyeT4NCgkJLy8vCQlJbnNlcnQgY29udGVudCBiZWZvcmUgZWFjaCBvZiB0aGUgbWF0Y2hlZCBlbGVtZW50cy4NCgkJLy8vCQlQYXJ0IG9mIERPTS9NYW5pcHVsYXRpb24NCgkJLy8vCTwvc3VtbWFyeT4NCgkJLy8vCTxyZXR1cm5zIHR5cGU9ImpRdWVyeSIgLz4NCgkJLy8vCTxwYXJhbSBuYW1lPSIiIHR5cGU9IkNvbnRlbnQiPg0KCQkvLy8JCUNvbnRlbnQgdG8gaW5zZXJ0IGJlZm9yZSBlYWNoIHRhcmdldC4NCgkJLy8vCTwvcGFyYW0+DQoNCgkJcmV0dXJuIHRoaXMuZG9tTWFuaXAoYXJndW1lbnRzLCBmYWxzZSwgZnVuY3Rpb24oZWxlbSl7DQoJCQl0aGlzLnBhcmVudE5vZGUuaW5zZXJ0QmVmb3JlKCBlbGVtLCB0aGlzICk7DQoJCX0pOw0KCX0sDQoNCglhZnRlcjogZnVuY3Rpb24oKSB7DQoJCS8vLwk8c3VtbWFyeT4NCgkJLy8vCQlJbnNlcnQgY29udGVudCBhZnRlciBlYWNoIG9mIHRoZSBtYXRjaGVkIGVsZW1lbnRzLg0KCQkvLy8JCVBhcnQgb2YgRE9NL01hbmlwdWxhdGlvbg0KCQkvLy8JPC9zdW1tYXJ5Pg0KCQkvLy8JPHJldHVybnMgdHlwZT0ialF1ZXJ5IiAvPg0KCQkvLy8JPHBhcmFtIG5hbWU9IiIgdHlwZT0iQ29udGVudCI+DQoJCS8vLwkJQ29udGVudCB0byBpbnNlcnQgYWZ0ZXIgZWFjaCB0YXJnZXQuDQoJCS8vLwk8L3BhcmFtPg0KDQoJCXJldHVybiB0aGlzLmRvbU1hbmlwKGFyZ3VtZW50cywgZmFsc2UsIGZ1bmN0aW9uKGVsZW0pew0KCQkJdGhpcy5wYXJlbnROb2RlLmluc2VydEJlZm9yZSggZWxlbSwgdGhpcy5uZXh0U2libGluZyApOw0KCQl9KTsNCgl9LA0KDQoJZW5kOiBmdW5jdGlvbigpIHsNCgkJLy8vCTxzdW1tYXJ5Pg0KCQkvLy8JCUVuZCB0aGUgbW9zdCByZWNlbnQgJ2Rlc3RydWN0aXZlJyBvcGVyYXRpb24sIHJldmVydGluZyB0aGUgbGlzdCBvZiBtYXRjaGVkIGVsZW1lbnRzDQoJCS8vLwkJYmFjayB0byBpdHMgcHJldmlvdXMgc3RhdGUuIEFmdGVyIGFuIGVuZCBvcGVyYXRpb24sIHRoZSBsaXN0IG9mIG1hdGNoZWQgZWxlbWVudHMgd2lsbA0KCQkvLy8JCXJldmVydCB0byB0aGUgbGFzdCBzdGF0ZSBvZiBtYXRjaGVkIGVsZW1lbnRzLg0KCQkvLy8JCUlmIHRoZXJlIHdhcyBubyBkZXN0cnVjdGl2ZSBvcGVyYXRpb24gYmVmb3JlLCBhbiBlbXB0eSBzZXQgaXMgcmV0dXJuZWQuDQoJCS8vLwkJUGFydCBvZiBET00vVHJhdmVyc2luZw0KCQkvLy8JPC9zdW1tYXJ5Pg0KCQkvLy8JPHJldHVybnMgdHlwZT0ialF1ZXJ5IiAvPg0KDQoJCXJldHVybiB0aGlzLnByZXZPYmplY3QgfHwgalF1ZXJ5KCBbXSApOw0KCX0sDQoNCgkvLyBGb3IgaW50ZXJuYWwgdXNlIG9ubHkuDQoJLy8gQmVoYXZlcyBsaWtlIGFuIEFycmF5J3MgbWV0aG9kLCBub3QgbGlrZSBhIGpRdWVyeSBtZXRob2QuDQoJcHVzaDogW10ucHVzaCwNCglzb3J0OiBbXS5zb3J0LA0KCXNwbGljZTogW10uc3BsaWNlLA0KDQoJZmluZDogZnVuY3Rpb24oIHNlbGVjdG9yICkgew0KCQkvLy8JPHN1bW1hcnk+DQoJCS8vLwkJU2VhcmNoZXMgZm9yIGFsbCBlbGVtZW50cyB0aGF0IG1hdGNoIHRoZSBzcGVjaWZpZWQgZXhwcmVzc2lvbi4NCgkJLy8vCQlUaGlzIG1ldGhvZCBpcyBhIGdvb2Qgd2F5IHRvIGZpbmQgYWRkaXRpb25hbCBkZXNjZW5kYW50DQoJCS8vLwkJZWxlbWVudHMgd2l0aCB3aGljaCB0byBwcm9jZXNzLg0KCQkvLy8JCUFsbCBzZWFyY2hpbmcgaXMgZG9uZSB1c2luZyBhIGpRdWVyeSBleHByZXNzaW9uLiBUaGUgZXhwcmVzc2lvbiBjYW4gYmUNCgkJLy8vCQl3cml0dGVuIHVzaW5nIENTUyAxLTMgU2VsZWN0b3Igc3ludGF4LCBvciBiYXNpYyBYUGF0aC4NCgkJLy8vCQlQYXJ0IG9mIERPTS9UcmF2ZXJzaW5nDQoJCS8vLwk8L3N1bW1hcnk+DQoJCS8vLwk8cmV0dXJucyB0eXBlPSJqUXVlcnkiIC8+DQoJCS8vLwk8cGFyYW0gbmFtZT0ic2VsZWN0b3IiIHR5cGU9IlN0cmluZyI+DQoJCS8vLwkJQW4gZXhwcmVzc2lvbiB0byBzZWFyY2ggd2l0aC4NCgkJLy8vCTwvcGFyYW0+DQoJCS8vLwk8cmV0dXJucyB0eXBlPSJqUXVlcnkiIC8+DQoNCgkJaWYgKCB0aGlzLmxlbmd0aCA9PT0gMSApIHsNCgkJCXZhciByZXQgPSB0aGlzLnB1c2hTdGFjayggW10sICJmaW5kIiwgc2VsZWN0b3IgKTsNCgkJCXJldC5sZW5ndGggPSAwOw0KCQkJalF1ZXJ5LmZpbmQoIHNlbGVjdG9yLCB0aGlzWzBdLCByZXQgKTsNCgkJCXJldHVybiByZXQ7DQoJCX0gZWxzZSB7DQoJCQlyZXR1cm4gdGhpcy5wdXNoU3RhY2soIGpRdWVyeS51bmlxdWUoalF1ZXJ5Lm1hcCh0aGlzLCBmdW5jdGlvbihlbGVtKXsNCgkJCQlyZXR1cm4galF1ZXJ5LmZpbmQoIHNlbGVjdG9yLCBlbGVtICk7DQoJCQl9KSksICJmaW5kIiwgc2VsZWN0b3IgKTsNCgkJfQ0KCX0sDQoNCgljbG9uZTogZnVuY3Rpb24oIGV2ZW50cyApIHsNCgkJLy8vCTxzdW1tYXJ5Pg0KCQkvLy8JCUNsb25lIG1hdGNoZWQgRE9NIEVsZW1lbnRzIGFuZCBzZWxlY3QgdGhlIGNsb25lcy4gDQoJCS8vLwkJVGhpcyBpcyB1c2VmdWwgZm9yIG1vdmluZyBjb3BpZXMgb2YgdGhlIGVsZW1lbnRzIHRvIGFub3RoZXINCgkJLy8vCQlsb2NhdGlvbiBpbiB0aGUgRE9NLg0KCQkvLy8JCVBhcnQgb2YgRE9NL01hbmlwdWxhdGlvbg0KCQkvLy8JPC9zdW1tYXJ5Pg0KCQkvLy8JPHJldHVybnMgdHlwZT0ialF1ZXJ5IiAvPg0KCQkvLy8JPHBhcmFtIG5hbWU9ImRlZXAiIHR5cGU9IkJvb2xlYW4iIG9wdGlvbmFsPSJ0cnVlIj4NCgkJLy8vCQkoT3B0aW9uYWwpIFNldCB0byBmYWxzZSBpZiB5b3UgZG9uJ3Qgd2FudCB0byBjbG9uZSBhbGwgZGVzY2VuZGFudCBub2RlcywgaW4gYWRkaXRpb24gdG8gdGhlIGVsZW1lbnQgaXRzZWxmLg0KCQkvLy8JPC9wYXJhbT4NCg0KCQkvLyBEbyB0aGUgY2xvbmUNCgkJdmFyIHJldCA9IHRoaXMubWFwKGZ1bmN0aW9uKCl7DQoJCQlpZiAoICFqUXVlcnkuc3VwcG9ydC5ub0Nsb25lRXZlbnQgJiYgIWpRdWVyeS5pc1hNTERvYyh0aGlzKSApIHsNCgkJCQkvLyBJRSBjb3BpZXMgZXZlbnRzIGJvdW5kIHZpYSBhdHRhY2hFdmVudCB3aGVuDQoJCQkJLy8gdXNpbmcgY2xvbmVOb2RlLiBDYWxsaW5nIGRldGFjaEV2ZW50IG9uIHRoZQ0KCQkJCS8vIGNsb25lIHdpbGwgYWxzbyByZW1vdmUgdGhlIGV2ZW50cyBmcm9tIHRoZSBvcmlnbmFsDQoJCQkJLy8gSW4gb3JkZXIgdG8gZ2V0IGFyb3VuZCB0aGlzLCB3ZSB1c2UgaW5uZXJIVE1MLg0KCQkJCS8vIFVuZm9ydHVuYXRlbHksIHRoaXMgbWVhbnMgc29tZSBtb2RpZmljYXRpb25zIHRvDQoJCQkJLy8gYXR0cmlidXRlcyBpbiBJRSB0aGF0IGFyZSBhY3R1YWxseSBvbmx5IHN0b3JlZA0KCQkJCS8vIGFzIHByb3BlcnRpZXMgd2lsbCBub3QgYmUgY29waWVkIChzdWNoIGFzIHRoZQ0KCQkJCS8vIHRoZSBuYW1lIGF0dHJpYnV0ZSBvbiBhbiBpbnB1dCkuDQoJCQkJdmFyIGh0bWwgPSB0aGlzLm91dGVySFRNTDsNCgkJCQlpZiAoICFodG1sICkgew0KCQkJCQl2YXIgZGl2ID0gdGhpcy5vd25lckRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoImRpdiIpOw0KCQkJCQlkaXYuYXBwZW5kQ2hpbGQoIHRoaXMuY2xvbmVOb2RlKHRydWUpICk7DQoJCQkJCWh0bWwgPSBkaXYuaW5uZXJIVE1MOw0KCQkJCX0NCg0KCQkJCXJldHVybiBqUXVlcnkuY2xlYW4oW2h0bWwucmVwbGFjZSgvIGpRdWVyeVxkKz0iKD86XGQrfG51bGwpIi9nLCAiIikucmVwbGFjZSgvXlxzKi8sICIiKV0pWzBdOw0KCQkJfSBlbHNlDQoJCQkJcmV0dXJuIHRoaXMuY2xvbmVOb2RlKHRydWUpOw0KCQl9KTsNCg0KCQkvLyBDb3B5IHRoZSBldmVudHMgZnJvbSB0aGUgb3JpZ2luYWwgdG8gdGhlIGNsb25lDQoJCWlmICggZXZlbnRzID09PSB0cnVlICkgew0KCQkJdmFyIG9yaWcgPSB0aGlzLmZpbmQoIioiKS5hbmRTZWxmKCksIGkgPSAwOw0KDQoJCQlyZXQuZmluZCgiKiIpLmFuZFNlbGYoKS5lYWNoKGZ1bmN0aW9uKCl7DQoJCQkJaWYgKCB0aGlzLm5vZGVOYW1lICE9PSBvcmlnW2ldLm5vZGVOYW1lICkNCgkJCQkJcmV0dXJuOw0KDQoJCQkJdmFyIGV2ZW50cyA9IGpRdWVyeS5kYXRhKCBvcmlnW2ldLCAiZXZlbnRzIiApOw0KDQoJCQkJZm9yICggdmFyIHR5cGUgaW4gZXZlbnRzICkgew0KCQkJCQlmb3IgKCB2YXIgaGFuZGxlciBpbiBldmVudHNbIHR5cGUgXSApIHsNCgkJCQkJCWpRdWVyeS5ldmVudC5hZGQoIHRoaXMsIHR5cGUsIGV2ZW50c1sgdHlwZSBdWyBoYW5kbGVyIF0sIGV2ZW50c1sgdHlwZSBdWyBoYW5kbGVyIF0uZGF0YSApOw0KCQkJCQl9DQoJCQkJfQ0KDQoJCQkJaSsrOw0KCQkJfSk7DQoJCX0NCg0KCQkvLyBSZXR1cm4gdGhlIGNsb25lZCBzZXQNCgkJcmV0dXJuIHJldDsNCgl9LA0KDQoJZmlsdGVyOiBmdW5jdGlvbiggc2VsZWN0b3IgKSB7DQoJCS8vLwk8c3VtbWFyeT4NCgkJLy8vCQlSZW1vdmVzIGFsbCBlbGVtZW50cyBmcm9tIHRoZSBzZXQgb2YgbWF0Y2hlZCBlbGVtZW50cyB0aGF0IGRvIG5vdA0KCQkvLy8JCXBhc3MgdGhlIHNwZWNpZmllZCBmaWx0ZXIuIFRoaXMgbWV0aG9kIGlzIHVzZWQgdG8gbmFycm93IGRvd24NCgkJLy8vCQl0aGUgcmVzdWx0cyBvZiBhIHNlYXJjaC4NCgkJLy8vCQl9KQ0KCQkvLy8JCVBhcnQgb2YgRE9NL1RyYXZlcnNpbmcNCgkJLy8vCTwvc3VtbWFyeT4NCgkJLy8vCTxyZXR1cm5zIHR5cGU9ImpRdWVyeSIgLz4NCgkJLy8vCTxwYXJhbSBuYW1lPSJzZWxlY3RvciIgdHlwZT0iRnVuY3Rpb24iPg0KCQkvLy8JCUEgZnVuY3Rpb24gdG8gdXNlIGZvciBmaWx0ZXJpbmcNCgkJLy8vCTwvcGFyYW0+DQoJCS8vLwk8cmV0dXJucyB0eXBlPSJqUXVlcnkiIC8+DQoJDQoJCXJldHVybiB0aGlzLnB1c2hTdGFjaygNCgkJCWpRdWVyeS5pc0Z1bmN0aW9uKCBzZWxlY3RvciApICYmDQoJCQlqUXVlcnkuZ3JlcCh0aGlzLCBmdW5jdGlvbihlbGVtLCBpKXsNCgkJCQlyZXR1cm4gc2VsZWN0b3IuY2FsbCggZWxlbSwgaSApOw0KCQkJfSkgfHwNCg0KCQkJalF1ZXJ5Lm11bHRpRmlsdGVyKCBzZWxlY3RvciwgalF1ZXJ5LmdyZXAodGhpcywgZnVuY3Rpb24oZWxlbSl7DQoJCQkJcmV0dXJuIGVsZW0ubm9kZVR5cGUgPT09IDE7DQoJCQl9KSApLCAiZmlsdGVyIiwgc2VsZWN0b3IgKTsNCgl9LA0KDQoJY2xvc2VzdDogZnVuY3Rpb24oIHNlbGVjdG9yICkgew0KCQkvLy8JPHN1bW1hcnk+DQoJCS8vLwkJR2V0IGEgc2V0IG9mIGVsZW1lbnRzIGNvbnRhaW5pbmcgdGhlIGNsb3Nlc3QgcGFyZW50IGVsZW1lbnQgdGhhdCBtYXRjaGVzIHRoZSBzcGVjaWZpZWQgc2VsZWN0b3IsIHRoZSBzdGFydGluZyBlbGVtZW50IGluY2x1ZGVkLg0KCQkvLy8JPC9zdW1tYXJ5Pg0KCQkvLy8JPHJldHVybnMgdHlwZT0ialF1ZXJ5IiAvPg0KCQkvLy8JPHBhcmFtIG5hbWU9InNlbGVjdG9yIiB0eXBlPSJGdW5jdGlvbiI+DQoJCS8vLwkJQW4gZXhwcmVzc2lvbiB0byBmaWx0ZXIgdGhlIGVsZW1lbnRzIHdpdGguDQoJCS8vLwk8L3BhcmFtPg0KCQkvLy8JPHJldHVybnMgdHlwZT0ialF1ZXJ5IiAvPg0KDQoJCXZhciBwb3MgPSBqUXVlcnkuZXhwci5tYXRjaC5QT1MudGVzdCggc2VsZWN0b3IgKSA/IGpRdWVyeShzZWxlY3RvcikgOiBudWxsLA0KCQkJY2xvc2VyID0gMDsNCg0KCQlyZXR1cm4gdGhpcy5tYXAoZnVuY3Rpb24oKXsNCgkJCXZhciBjdXIgPSB0aGlzOw0KCQkJd2hpbGUgKCBjdXIgJiYgY3VyLm93bmVyRG9jdW1lbnQgKSB7DQoJCQkJaWYgKCBwb3MgPyBwb3MuaW5kZXgoY3VyKSA+IC0xIDogalF1ZXJ5KGN1cikuaXMoc2VsZWN0b3IpICkgew0KCQkJCQlqUXVlcnkuZGF0YShjdXIsICJjbG9zZXN0IiwgY2xvc2VyKTsNCgkJCQkJcmV0dXJuIGN1cjsNCgkJCQl9DQoJCQkJY3VyID0gY3VyLnBhcmVudE5vZGU7DQoJCQkJY2xvc2VyKys7DQoJCQl9DQoJCX0pOw0KCX0sDQoNCglub3Q6IGZ1bmN0aW9uKCBzZWxlY3RvciApIHsNCgkJLy8vCTxzdW1tYXJ5Pg0KCQkvLy8JCVJlbW92ZXMgYW55IGVsZW1lbnRzIGluc2lkZSB0aGUgYXJyYXkgb2YgZWxlbWVudHMgZnJvbSB0aGUgc2V0DQoJCS8vLwkJb2YgbWF0Y2hlZCBlbGVtZW50cy4gVGhpcyBtZXRob2QgaXMgdXNlZCB0byByZW1vdmUgb25lIG9yIG1vcmUNCgkJLy8vCQllbGVtZW50cyBmcm9tIGEgalF1ZXJ5IG9iamVjdC4NCgkJLy8vCQlQYXJ0IG9mIERPTS9UcmF2ZXJzaW5nDQoJCS8vLwk8L3N1bW1hcnk+DQoJCS8vLwk8cGFyYW0gbmFtZT0ic2VsZWN0b3IiIHR5cGU9ImpRdWVyeSI+DQoJCS8vLwkJQSBzZXQgb2YgZWxlbWVudHMgdG8gcmVtb3ZlIGZyb20gdGhlIGpRdWVyeSBzZXQgb2YgbWF0Y2hlZCBlbGVtZW50cy4NCgkJLy8vCTwvcGFyYW0+DQoJCS8vLwk8cmV0dXJucyB0eXBlPSJqUXVlcnkiIC8+DQoNCgkJaWYgKCB0eXBlb2Ygc2VsZWN0b3IgPT09ICJzdHJpbmciICkNCgkJCS8vIHRlc3Qgc3BlY2lhbCBjYXNlIHdoZXJlIGp1c3Qgb25lIHNlbGVjdG9yIGlzIHBhc3NlZCBpbg0KCQkJaWYgKCBpc1NpbXBsZS50ZXN0KCBzZWxlY3RvciApICkNCgkJCQlyZXR1cm4gdGhpcy5wdXNoU3RhY2soIGpRdWVyeS5tdWx0aUZpbHRlciggc2VsZWN0b3IsIHRoaXMsIHRydWUgKSwgIm5vdCIsIHNlbGVjdG9yICk7DQoJCQllbHNlDQoJCQkJc2VsZWN0b3IgPSBqUXVlcnkubXVsdGlGaWx0ZXIoIHNlbGVjdG9yLCB0aGlzICk7DQoNCgkJdmFyIGlzQXJyYXlMaWtlID0gc2VsZWN0b3IubGVuZ3RoICYmIHNlbGVjdG9yW3NlbGVjdG9yLmxlbmd0aCAtIDFdICE9PSB1bmRlZmluZWQgJiYgIXNlbGVjdG9yLm5vZGVUeXBlOw0KCQlyZXR1cm4gdGhpcy5maWx0ZXIoZnVuY3Rpb24oKSB7DQoJCQlyZXR1cm4gaXNBcnJheUxpa2UgPyBqUXVlcnkuaW5BcnJheSggdGhpcywgc2VsZWN0b3IgKSA8IDAgOiB0aGlzICE9IHNlbGVjdG9yOw0KCQl9KTsNCgl9LA0KDQoJYWRkOiBmdW5jdGlvbiggc2VsZWN0b3IgKSB7DQoJCS8vLwk8c3VtbWFyeT4NCgkJLy8vCQlBZGRzIG9uZSBvciBtb3JlIEVsZW1lbnRzIHRvIHRoZSBzZXQgb2YgbWF0Y2hlZCBlbGVtZW50cy4NCgkJLy8vCQlQYXJ0IG9mIERPTS9UcmF2ZXJzaW5nDQoJCS8vLwk8L3N1bW1hcnk+DQoJCS8vLwk8cGFyYW0gbmFtZT0iZWxlbWVudHMiIHR5cGU9IkVsZW1lbnQiPg0KCQkvLy8JCU9uZSBvciBtb3JlIEVsZW1lbnRzIHRvIGFkZA0KCQkvLy8JPC9wYXJhbT4NCgkJLy8vCTxyZXR1cm5zIHR5cGU9ImpRdWVyeSIgLz4NCgkNCgkJcmV0dXJuIHRoaXMucHVzaFN0YWNrKCBqUXVlcnkudW5pcXVlKCBqUXVlcnkubWVyZ2UoDQoJCQl0aGlzLmdldCgpLA0KCQkJdHlwZW9mIHNlbGVjdG9yID09PSAic3RyaW5nIiA/DQoJCQkJalF1ZXJ5KCBzZWxlY3RvciApIDoNCgkJCQlqUXVlcnkubWFrZUFycmF5KCBzZWxlY3RvciApDQoJCSkpKTsNCgl9LA0KDQoJaXM6IGZ1bmN0aW9uKCBzZWxlY3RvciApIHsNCgkJLy8vCTxzdW1tYXJ5Pg0KCQkvLy8JCUNoZWNrcyB0aGUgY3VycmVudCBzZWxlY3Rpb24gYWdhaW5zdCBhbiBleHByZXNzaW9uIGFuZCByZXR1cm5zIHRydWUsDQoJCS8vLwkJaWYgYXQgbGVhc3Qgb25lIGVsZW1lbnQgb2YgdGhlIHNlbGVjdGlvbiBmaXRzIHRoZSBnaXZlbiBleHByZXNzaW9uLg0KCQkvLy8JCURvZXMgcmV0dXJuIGZhbHNlLCBpZiBubyBlbGVtZW50IGZpdHMgb3IgdGhlIGV4cHJlc3Npb24gaXMgbm90IHZhbGlkLg0KCQkvLy8JCWZpbHRlcihTdHJpbmcpIGlzIHVzZWQgaW50ZXJuYWxseSwgdGhlcmVmb3JlIGFsbCBydWxlcyB0aGF0IGFwcGx5IHRoZXJlDQoJCS8vLwkJYXBwbHkgaGVyZSwgdG9vLg0KCQkvLy8JCVBhcnQgb2YgRE9NL1RyYXZlcnNpbmcNCgkJLy8vCTwvc3VtbWFyeT4NCgkJLy8vCTxyZXR1cm5zIHR5cGU9IkJvb2xlYW4iIC8+DQoJCS8vLwk8cGFyYW0gbmFtZT0iZXhwciIgdHlwZT0iU3RyaW5nIj4NCgkJLy8vCQkgVGhlIGV4cHJlc3Npb24gd2l0aCB3aGljaCB0byBmaWx0ZXINCgkJLy8vCTwvcGFyYW0+DQoNCgkJcmV0dXJuICEhc2VsZWN0b3IgJiYgalF1ZXJ5Lm11bHRpRmlsdGVyKCBzZWxlY3RvciwgdGhpcyApLmxlbmd0aCA+IDA7DQoJfSwNCg0KCWhhc0NsYXNzOiBmdW5jdGlvbiggc2VsZWN0b3IgKSB7DQoJCS8vLwk8c3VtbWFyeT4NCgkJLy8vCQlDaGVja3MgdGhlIGN1cnJlbnQgc2VsZWN0aW9uIGFnYWluc3QgYSBjbGFzcyBhbmQgcmV0dXJucyB3aGV0aGVyIGF0IGxlYXN0IG9uZSBzZWxlY3Rpb24gaGFzIGEgZ2l2ZW4gY2xhc3MuDQoJCS8vLwk8L3N1bW1hcnk+DQoJCS8vLwk8cGFyYW0gbmFtZT0ic2VsZWN0b3IiIHR5cGU9IlN0cmluZyI+VGhlIGNsYXNzIHRvIGNoZWNrIGFnYWluc3Q8L3BhcmFtPg0KCQkvLy8JPHJldHVybnMgdHlwZT0iQm9vbGVhbiI+VHJ1ZSBpZiBhdCBsZWFzdCBvbmUgZWxlbWVudCBpbiB0aGUgc2VsZWN0aW9uIGhhcyB0aGUgY2xhc3MsIG90aGVyd2lzZSBmYWxzZS48L3JldHVybnM+DQoNCgkJcmV0dXJuICEhc2VsZWN0b3IgJiYgdGhpcy5pcyggIi4iICsgc2VsZWN0b3IgKTsNCgl9LA0KDQoJdmFsOiBmdW5jdGlvbiggdmFsdWUgKSB7DQoJCS8vLwk8c3VtbWFyeT4NCgkJLy8vCQlTZXQgdGhlIHZhbHVlIG9mIGV2ZXJ5IG1hdGNoZWQgZWxlbWVudC4NCgkJLy8vCQlQYXJ0IG9mIERPTS9BdHRyaWJ1dGVzDQoJCS8vLwk8L3N1bW1hcnk+DQoJCS8vLwk8cmV0dXJucyB0eXBlPSJqUXVlcnkiIC8+DQoJCS8vLwk8cGFyYW0gbmFtZT0idmFsIiB0eXBlPSJTdHJpbmciPg0KCQkvLy8JCSBTZXQgdGhlIHByb3BlcnR5IHRvIHRoZSBzcGVjaWZpZWQgdmFsdWUuDQoJCS8vLwk8L3BhcmFtPg0KDQoJCWlmICggdmFsdWUgPT09IHVuZGVmaW5lZCApIHsJCQkNCgkJCXZhciBlbGVtID0gdGhpc1swXTsNCg0KCQkJaWYgKCBlbGVtICkgew0KCQkJCWlmKCBqUXVlcnkubm9kZU5hbWUoIGVsZW0sICdvcHRpb24nICkgKQ0KCQkJCQlyZXR1cm4gKGVsZW0uYXR0cmlidXRlcy52YWx1ZSB8fCB7fSkuc3BlY2lmaWVkID8gZWxlbS52YWx1ZSA6IGVsZW0udGV4dDsNCgkJCQkNCgkJCQkvLyBXZSBuZWVkIHRvIGhhbmRsZSBzZWxlY3QgYm94ZXMgc3BlY2lhbA0KCQkJCWlmICggalF1ZXJ5Lm5vZGVOYW1lKCBlbGVtLCAic2VsZWN0IiApICkgew0KCQkJCQl2YXIgaW5kZXggPSBlbGVtLnNlbGVjdGVkSW5kZXgsDQoJCQkJCQl2YWx1ZXMgPSBbXSwNCgkJCQkJCW9wdGlvbnMgPSBlbGVtLm9wdGlvbnMsDQoJCQkJCQlvbmUgPSBlbGVtLnR5cGUgPT0gInNlbGVjdC1vbmUiOw0KDQoJCQkJCS8vIE5vdGhpbmcgd2FzIHNlbGVjdGVkDQoJCQkJCWlmICggaW5kZXggPCAwICkNCgkJCQkJCXJldHVybiBudWxsOw0KDQoJCQkJCS8vIExvb3AgdGhyb3VnaCBhbGwgdGhlIHNlbGVjdGVkIG9wdGlvbnMNCgkJCQkJZm9yICggdmFyIGkgPSBvbmUgPyBpbmRleCA6IDAsIG1heCA9IG9uZSA/IGluZGV4ICsgMSA6IG9wdGlvbnMubGVuZ3RoOyBpIDwgbWF4OyBpKysgKSB7DQoJCQkJCQl2YXIgb3B0aW9uID0gb3B0aW9uc1sgaSBdOw0KDQoJCQkJCQlpZiAoIG9wdGlvbi5zZWxlY3RlZCApIHsNCgkJCQkJCQkvLyBHZXQgdGhlIHNwZWNpZmMgdmFsdWUgZm9yIHRoZSBvcHRpb24NCgkJCQkJCQl2YWx1ZSA9IGpRdWVyeShvcHRpb24pLnZhbCgpOw0KDQoJCQkJCQkJLy8gV2UgZG9uJ3QgbmVlZCBhbiBhcnJheSBmb3Igb25lIHNlbGVjdHMNCgkJCQkJCQlpZiAoIG9uZSApDQoJCQkJCQkJCXJldHVybiB2YWx1ZTsNCg0KCQkJCQkJCS8vIE11bHRpLVNlbGVjdHMgcmV0dXJuIGFuIGFycmF5DQoJCQkJCQkJdmFsdWVzLnB1c2goIHZhbHVlICk7DQoJCQkJCQl9DQoJCQkJCX0NCg0KCQkJCQlyZXR1cm4gdmFsdWVzOwkJCQkNCgkJCQl9DQoNCgkJCQkvLyBFdmVyeXRoaW5nIGVsc2UsIHdlIGp1c3QgZ3JhYiB0aGUgdmFsdWUNCgkJCQlyZXR1cm4gKGVsZW0udmFsdWUgfHwgIiIpLnJlcGxhY2UoL1xyL2csICIiKTsNCg0KCQkJfQ0KDQoJCQlyZXR1cm4gdW5kZWZpbmVkOw0KCQl9DQoNCgkJaWYgKCB0eXBlb2YgdmFsdWUgPT09ICJudW1iZXIiICkNCgkJCXZhbHVlICs9ICcnOw0KDQoJCXJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24oKXsNCgkJCWlmICggdGhpcy5ub2RlVHlwZSAhPSAxICkNCgkJCQlyZXR1cm47DQoNCgkJCWlmICggalF1ZXJ5LmlzQXJyYXkodmFsdWUpICYmIC9yYWRpb3xjaGVja2JveC8udGVzdCggdGhpcy50eXBlICkgKQ0KCQkJCXRoaXMuY2hlY2tlZCA9IChqUXVlcnkuaW5BcnJheSh0aGlzLnZhbHVlLCB2YWx1ZSkgPj0gMCB8fA0KCQkJCQlqUXVlcnkuaW5BcnJheSh0aGlzLm5hbWUsIHZhbHVlKSA+PSAwKTsNCg0KCQkJZWxzZSBpZiAoIGpRdWVyeS5ub2RlTmFtZSggdGhpcywgInNlbGVjdCIgKSApIHsNCgkJCQl2YXIgdmFsdWVzID0galF1ZXJ5Lm1ha2VBcnJheSh2YWx1ZSk7DQoNCgkJCQlqUXVlcnkoICJvcHRpb24iLCB0aGlzICkuZWFjaChmdW5jdGlvbigpew0KCQkJCQl0aGlzLnNlbGVjdGVkID0gKGpRdWVyeS5pbkFycmF5KCB0aGlzLnZhbHVlLCB2YWx1ZXMgKSA+PSAwIHx8DQoJCQkJCQlqUXVlcnkuaW5BcnJheSggdGhpcy50ZXh0LCB2YWx1ZXMgKSA+PSAwKTsNCgkJCQl9KTsNCg0KCQkJCWlmICggIXZhbHVlcy5sZW5ndGggKQ0KCQkJCQl0aGlzLnNlbGVjdGVkSW5kZXggPSAtMTsNCg0KCQkJfSBlbHNlDQoJCQkJdGhpcy52YWx1ZSA9IHZhbHVlOw0KCQl9KTsNCgl9LA0KDQoJaHRtbDogZnVuY3Rpb24oIHZhbHVlICkgew0KCQkvLy8JPHN1bW1hcnk+DQoJCS8vLwkJU2V0IHRoZSBodG1sIGNvbnRlbnRzIG9mIGV2ZXJ5IG1hdGNoZWQgZWxlbWVudC4NCgkJLy8vCQlUaGlzIHByb3BlcnR5IGlzIG5vdCBhdmFpbGFibGUgb24gWE1MIGRvY3VtZW50cy4NCgkJLy8vCQlQYXJ0IG9mIERPTS9BdHRyaWJ1dGVzDQoJCS8vLwk8L3N1bW1hcnk+DQoJCS8vLwk8cmV0dXJucyB0eXBlPSJqUXVlcnkiIC8+DQoJCS8vLwk8cGFyYW0gbmFtZT0idmFsIiB0eXBlPSJTdHJpbmciPg0KCQkvLy8JCSBTZXQgdGhlIGh0bWwgY29udGVudHMgdG8gdGhlIHNwZWNpZmllZCB2YWx1ZS4NCgkJLy8vCTwvcGFyYW0+DQoNCgkJcmV0dXJuIHZhbHVlID09PSB1bmRlZmluZWQgPw0KCQkJKHRoaXNbMF0gPw0KCQkJCXRoaXNbMF0uaW5uZXJIVE1MLnJlcGxhY2UoLyBqUXVlcnlcZCs9Iig/OlxkK3xudWxsKSIvZywgIiIpIDoNCgkJCQludWxsKSA6DQoJCQl0aGlzLmVtcHR5KCkuYXBwZW5kKCB2YWx1ZSApOw0KCX0sDQoNCglyZXBsYWNlV2l0aDogZnVuY3Rpb24oIHZhbHVlICkgew0KCQkvLy8JPHN1bW1hcnk+DQoJCS8vLwkJUmVwbGFjZXMgYWxsIG1hdGNoZWQgZWxlbWVudCB3aXRoIHRoZSBzcGVjaWZpZWQgSFRNTCBvciBET00gZWxlbWVudHMuDQoJCS8vLwk8L3N1bW1hcnk+DQoJCS8vLwk8cGFyYW0gbmFtZT0idmFsdWUiIHR5cGU9IlN0cmluZyI+DQoJCS8vLwkJVGhlIGNvbnRlbnQgd2l0aCB3aGljaCB0byByZXBsYWNlIHRoZSBtYXRjaGVkIGVsZW1lbnRzLg0KCQkvLy8JPC9wYXJhbT4NCgkJLy8vCTxyZXR1cm5zIHR5cGU9ImpRdWVyeSI+VGhlIGVsZW1lbnQgdGhhdCB3YXMganVzdCByZXBsYWNlZC48L3JldHVybnM+DQoNCgkJcmV0dXJuIHRoaXMuYWZ0ZXIoIHZhbHVlICkucmVtb3ZlKCk7DQoJfSwNCg0KCWVxOiBmdW5jdGlvbiggaSApIHsNCgkJLy8vCTxzdW1tYXJ5Pg0KCQkvLy8JCVJlZHVjZSB0aGUgc2V0IG9mIG1hdGNoZWQgZWxlbWVudHMgdG8gYSBzaW5nbGUgZWxlbWVudC4NCgkJLy8vCQlUaGUgcG9zaXRpb24gb2YgdGhlIGVsZW1lbnQgaW4gdGhlIHNldCBvZiBtYXRjaGVkIGVsZW1lbnRzDQoJCS8vLwkJc3RhcnRzIGF0IDAgYW5kIGdvZXMgdG8gbGVuZ3RoIC0gMS4NCgkJLy8vCQlQYXJ0IG9mIENvcmUNCgkJLy8vCTwvc3VtbWFyeT4NCgkJLy8vCTxyZXR1cm5zIHR5cGU9ImpRdWVyeSIgLz4NCgkJLy8vCTxwYXJhbSBuYW1lPSJudW0iIHR5cGU9Ik51bWJlciI+DQoJCS8vLwkJcG9zIFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB0aGF0IHlvdSB3aXNoIHRvIGxpbWl0IHRvLg0KCQkvLy8JPC9wYXJhbT4NCg0KCQlyZXR1cm4gdGhpcy5zbGljZSggaSwgK2kgKyAxICk7DQoJfSwNCg0KCXNsaWNlOiBmdW5jdGlvbigpIHsNCgkJLy8vCTxzdW1tYXJ5Pg0KCQkvLy8JCVNlbGVjdHMgYSBzdWJzZXQgb2YgdGhlIG1hdGNoZWQgZWxlbWVudHMuICBCZWhhdmVzIGV4YWN0bHkgbGlrZSB0aGUgYnVpbHQtaW4gQXJyYXkgc2xpY2UgbWV0aG9kLg0KCQkvLy8JPC9zdW1tYXJ5Pg0KCQkvLy8JPHBhcmFtIG5hbWU9InN0YXJ0IiB0eXBlPSJOdW1iZXIiIGludGVnZXI9InRydWUiPldoZXJlIHRvIHN0YXJ0IHRoZSBzdWJzZXQgKDAtYmFzZWQpLjwvcGFyYW0+DQoJCS8vLwk8cGFyYW0gbmFtZT0iZW5kIiBvcHRpb25hbD0idHJ1ZSIgdHlwZT0iTnVtYmVyIiBpbnRlZ2VyPSJ0cnVlIj5XaGVyZSB0byBlbmQgdGhlIHN1YnNldCAobm90IGluY2x1ZGluZyB0aGUgZW5kIGVsZW1lbnQgaXRzZWxmKS4NCgkJLy8vCQlJZiBvbWl0dGVkLCBlbmRzIGF0IHRoZSBlbmQgb2YgdGhlIHNlbGVjdGlvbjwvcGFyYW0+DQoJCS8vLwk8cmV0dXJucyB0eXBlPSJqUXVlcnkiPlRoZSBzbGljZWQgZWxlbWVudHM8L3JldHVybnM+DQoNCgkJcmV0dXJuIHRoaXMucHVzaFN0YWNrKCBBcnJheS5wcm90b3R5cGUuc2xpY2UuYXBwbHkoIHRoaXMsIGFyZ3VtZW50cyApLA0KCQkJInNsaWNlIiwgQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKS5qb2luKCIsIikgKTsNCgl9LA0KDQoJbWFwOiBmdW5jdGlvbiggY2FsbGJhY2sgKSB7DQoJCS8vLwk8c3VtbWFyeT4NCgkJLy8vCQlUaGlzIG1lbWJlciBpcyBpbnRlcm5hbC4NCgkJLy8vCTwvc3VtbWFyeT4NCgkJLy8vCTxwcml2YXRlIC8+DQoJCS8vLwk8cmV0dXJucyB0eXBlPSJqUXVlcnkiIC8+DQoJCQ0KCQlyZXR1cm4gdGhpcy5wdXNoU3RhY2soIGpRdWVyeS5tYXAodGhpcywgZnVuY3Rpb24oZWxlbSwgaSl7DQoJCQlyZXR1cm4gY2FsbGJhY2suY2FsbCggZWxlbSwgaSwgZWxlbSApOw0KCQl9KSk7DQoJfSwNCg0KCWFuZFNlbGY6IGZ1bmN0aW9uKCkgew0KCQkvLy8JPHN1bW1hcnk+DQoJCS8vLwkJQWRkcyB0aGUgcHJldmlvdXMgc2VsZWN0aW9uIHRvIHRoZSBjdXJyZW50IHNlbGVjdGlvbi4NCgkJLy8vCTwvc3VtbWFyeT4NCgkJLy8vCTxyZXR1cm5zIHR5cGU9ImpRdWVyeSIgLz4NCgkJDQoJCXJldHVybiB0aGlzLmFkZCggdGhpcy5wcmV2T2JqZWN0ICk7DQoJfSwNCg0KCWRvbU1hbmlwOiBmdW5jdGlvbiggYXJncywgdGFibGUsIGNhbGxiYWNrICkgew0KCQkvLy8JPHBhcmFtIG5hbWU9ImFyZ3MiIHR5cGU9IkFycmF5Ij4NCgkJLy8vCQkgQXJncw0KCQkvLy8JPC9wYXJhbT4NCgkJLy8vCTxwYXJhbSBuYW1lPSJ0YWJsZSIgdHlwZT0iQm9vbGVhbiI+DQoJCS8vLwkJIEluc2VydCBUQk9EWSBpbiBUQUJMRXMgaWYgb25lIGlzIG5vdCBmb3VuZC4NCgkJLy8vCTwvcGFyYW0+DQoJCS8vLwk8cGFyYW0gbmFtZT0iZGlyIiB0eXBlPSJOdW1iZXIiPg0KCQkvLy8JCSBJZiBkaXImbHQ7MCwgcHJvY2VzcyBhcmdzIGluIHJldmVyc2Ugb3JkZXIuDQoJCS8vLwk8L3BhcmFtPg0KCQkvLy8JPHBhcmFtIG5hbWU9ImZuIiB0eXBlPSJGdW5jdGlvbiI+DQoJCS8vLwkJIFRoZSBmdW5jdGlvbiBkb2luZyB0aGUgRE9NIG1hbmlwdWxhdGlvbi4NCgkJLy8vCTwvcGFyYW0+DQoJCS8vLwk8cmV0dXJucyB0eXBlPSJqUXVlcnkiIC8+DQoJCS8vLwk8c3VtbWFyeT4NCgkJLy8vCQlQYXJ0IG9mIENvcmUNCgkJLy8vCTwvc3VtbWFyeT4NCgkJDQoJCWlmICggdGhpc1swXSApIHsNCgkJCXZhciBmcmFnbWVudCA9ICh0aGlzWzBdLm93bmVyRG9jdW1lbnQgfHwgdGhpc1swXSkuY3JlYXRlRG9jdW1lbnRGcmFnbWVudCgpLA0KCQkJCXNjcmlwdHMgPSBqUXVlcnkuY2xlYW4oIGFyZ3MsICh0aGlzWzBdLm93bmVyRG9jdW1lbnQgfHwgdGhpc1swXSksIGZyYWdtZW50ICksDQoJCQkJZmlyc3QgPSBmcmFnbWVudC5maXJzdENoaWxkOw0KDQoJCQlpZiAoIGZpcnN0ICkNCgkJCQlmb3IgKCB2YXIgaSA9IDAsIGwgPSB0aGlzLmxlbmd0aDsgaSA8IGw7IGkrKyApDQoJCQkJCWNhbGxiYWNrLmNhbGwoIHJvb3QodGhpc1tpXSwgZmlyc3QpLCB0aGlzLmxlbmd0aCA+IDEgfHwgaSA+IDAgPw0KCQkJCQkJCWZyYWdtZW50LmNsb25lTm9kZSh0cnVlKSA6IGZyYWdtZW50ICk7DQoJCQ0KCQkJaWYgKCBzY3JpcHRzICkNCgkJCQlqUXVlcnkuZWFjaCggc2NyaXB0cywgZXZhbFNjcmlwdCApOw0KCQl9DQoNCgkJcmV0dXJuIHRoaXM7DQoJCQ0KCQlmdW5jdGlvbiByb290KCBlbGVtLCBjdXIgKSB7DQoJCQlyZXR1cm4gdGFibGUgJiYgalF1ZXJ5Lm5vZGVOYW1lKGVsZW0sICJ0YWJsZSIpICYmIGpRdWVyeS5ub2RlTmFtZShjdXIsICJ0ciIpID8NCgkJCQkoZWxlbS5nZXRFbGVtZW50c0J5VGFnTmFtZSgidGJvZHkiKVswXSB8fA0KCQkJCWVsZW0uYXBwZW5kQ2hpbGQoZWxlbS5vd25lckRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoInRib2R5IikpKSA6DQoJCQkJZWxlbTsNCgkJfQ0KCX0NCn07DQoNCi8vIEdpdmUgdGhlIGluaXQgZnVuY3Rpb24gdGhlIGpRdWVyeSBwcm90b3R5cGUgZm9yIGxhdGVyIGluc3RhbnRpYXRpb24NCmpRdWVyeS5mbi5pbml0LnByb3RvdHlwZSA9IGpRdWVyeS5mbjsNCg0KZnVuY3Rpb24gZXZhbFNjcmlwdCggaSwgZWxlbSApIHsNCgkvLy8JPHN1bW1hcnk+DQoJLy8vCQlUaGlzIG1ldGhvZCBpcyBpbnRlcm5hbC4NCgkvLy8JPC9zdW1tYXJ5Pg0KCS8vLyA8cHJpdmF0ZSAvPg0KCQ0KCWlmICggZWxlbS5zcmMgKQ0KCQlqUXVlcnkuYWpheCh7DQoJCQl1cmw6IGVsZW0uc3JjLA0KCQkJYXN5bmM6IGZhbHNlLA0KCQkJZGF0YVR5cGU6ICJzY3JpcHQiDQoJCX0pOw0KDQoJZWxzZQ0KCQlqUXVlcnkuZ2xvYmFsRXZhbCggZWxlbS50ZXh0IHx8IGVsZW0udGV4dENvbnRlbnQgfHwgZWxlbS5pbm5lckhUTUwgfHwgIiIgKTsNCg0KCWlmICggZWxlbS5wYXJlbnROb2RlICkNCgkJZWxlbS5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKCBlbGVtICk7DQp9DQoNCmZ1bmN0aW9uIG5vdygpew0KCS8vLwk8c3VtbWFyeT4NCgkvLy8JCUdldHMgdGhlIGN1cnJlbnQgZGF0ZS4NCgkvLy8JPC9zdW1tYXJ5Pg0KCS8vLwk8cmV0dXJucyB0eXBlPSJEYXRlIj5UaGUgY3VycmVudCBkYXRlLjwvcmV0dXJucz4NCglyZXR1cm4gK25ldyBEYXRlOw0KfQ0KDQpqUXVlcnkuZXh0ZW5kID0galF1ZXJ5LmZuLmV4dGVuZCA9IGZ1bmN0aW9uKCkgew0KCS8vLwk8c3VtbWFyeT4NCgkvLy8JCUV4dGVuZCBvbmUgb2JqZWN0IHdpdGggb25lIG9yIG1vcmUgb3RoZXJzLCByZXR1cm5pbmcgdGhlIG9yaWdpbmFsLA0KCS8vLwkJbW9kaWZpZWQsIG9iamVjdC4gVGhpcyBpcyBhIGdyZWF0IHV0aWxpdHkgZm9yIHNpbXBsZSBpbmhlcml0YW5jZS4NCgkvLy8JCWpRdWVyeS5leHRlbmQoc2V0dGluZ3MsIG9wdGlvbnMpOw0KCS8vLwkJdmFyIHNldHRpbmdzID0galF1ZXJ5LmV4dGVuZCh7fSwgZGVmYXVsdHMsIG9wdGlvbnMpOw0KCS8vLwkJUGFydCBvZiBKYXZhU2NyaXB0DQoJLy8vCTwvc3VtbWFyeT4NCgkvLy8JPHBhcmFtIG5hbWU9InRhcmdldCIgdHlwZT0iT2JqZWN0Ij4NCgkvLy8JCSBUaGUgb2JqZWN0IHRvIGV4dGVuZA0KCS8vLwk8L3BhcmFtPg0KCS8vLwk8cGFyYW0gbmFtZT0icHJvcDEiIHR5cGU9Ik9iamVjdCI+DQoJLy8vCQkgVGhlIG9iamVjdCB0aGF0IHdpbGwgYmUgbWVyZ2VkIGludG8gdGhlIGZpcnN0Lg0KCS8vLwk8L3BhcmFtPg0KCS8vLwk8cGFyYW0gbmFtZT0icHJvcE4iIHR5cGU9Ik9iamVjdCIgb3B0aW9uYWw9InRydWUiIHBhcmFtZXRlckFycmF5PSJ0cnVlIj4NCgkvLy8JCSAob3B0aW9uYWwpIE1vcmUgb2JqZWN0cyB0byBtZXJnZSBpbnRvIHRoZSBmaXJzdA0KCS8vLwk8L3BhcmFtPg0KCS8vLwk8cmV0dXJucyB0eXBlPSJPYmplY3QiIC8+DQoNCgkvLyBjb3B5IHJlZmVyZW5jZSB0byB0YXJnZXQgb2JqZWN0DQoJdmFyIHRhcmdldCA9IGFyZ3VtZW50c1swXSB8fCB7fSwgaSA9IDEsIGxlbmd0aCA9IGFyZ3VtZW50cy5sZW5ndGgsIGRlZXAgPSBmYWxzZSwgb3B0aW9uczsNCg0KCS8vIEhhbmRsZSBhIGRlZXAgY29weSBzaXR1YXRpb24NCglpZiAoIHR5cGVvZiB0YXJnZXQgPT09ICJib29sZWFuIiApIHsNCgkJZGVlcCA9IHRhcmdldDsNCgkJdGFyZ2V0ID0gYXJndW1lbnRzWzFdIHx8IHt9Ow0KCQkvLyBza2lwIHRoZSBib29sZWFuIGFuZCB0aGUgdGFyZ2V0DQoJCWkgPSAyOw0KCX0NCg0KCS8vIEhhbmRsZSBjYXNlIHdoZW4gdGFyZ2V0IGlzIGEgc3RyaW5nIG9yIHNvbWV0aGluZyAocG9zc2libGUgaW4gZGVlcCBjb3B5KQ0KCWlmICggdHlwZW9mIHRhcmdldCAhPT0gIm9iamVjdCIgJiYgIWpRdWVyeS5pc0Z1bmN0aW9uKHRhcmdldCkgKQ0KCQl0YXJnZXQgPSB7fTsNCg0KCS8vIGV4dGVuZCBqUXVlcnkgaXRzZWxmIGlmIG9ubHkgb25lIGFyZ3VtZW50IGlzIHBhc3NlZA0KCWlmICggbGVuZ3RoID09IGkgKSB7DQoJCXRhcmdldCA9IHRoaXM7DQoJCS0taTsNCgl9DQoNCglmb3IgKCA7IGkgPCBsZW5ndGg7IGkrKyApDQoJCS8vIE9ubHkgZGVhbCB3aXRoIG5vbi1udWxsL3VuZGVmaW5lZCB2YWx1ZXMNCgkJaWYgKCAob3B0aW9ucyA9IGFyZ3VtZW50c1sgaSBdKSAhPSBudWxsICkNCgkJCS8vIEV4dGVuZCB0aGUgYmFzZSBvYmplY3QNCgkJCWZvciAoIHZhciBuYW1lIGluIG9wdGlvbnMgKSB7DQoJCQkJdmFyIHNyYyA9IHRhcmdldFsgbmFtZSBdLCBjb3B5ID0gb3B0aW9uc1sgbmFtZSBdOw0KDQoJCQkJLy8gUHJldmVudCBuZXZlci1lbmRpbmcgbG9vcA0KCQkJCWlmICggdGFyZ2V0ID09PSBjb3B5ICkNCgkJCQkJY29udGludWU7DQoNCgkJCQkvLyBSZWN1cnNlIGlmIHdlJ3JlIG1lcmdpbmcgb2JqZWN0IHZhbHVlcw0KCQkJCWlmICggZGVlcCAmJiBjb3B5ICYmIHR5cGVvZiBjb3B5ID09PSAib2JqZWN0IiAmJiAhY29weS5ub2RlVHlwZSApDQoJCQkJCXRhcmdldFsgbmFtZSBdID0galF1ZXJ5LmV4dGVuZCggZGVlcCwgDQoJCQkJCQkvLyBOZXZlciBtb3ZlIG9yaWdpbmFsIG9iamVjdHMsIGNsb25lIHRoZW0NCgkJCQkJCXNyYyB8fCAoIGNvcHkubGVuZ3RoICE9IG51bGwgPyBbIF0gOiB7IH0gKQ0KCQkJCQksIGNvcHkgKTsNCg0KCQkJCS8vIERvbid0IGJyaW5nIGluIHVuZGVmaW5lZCB2YWx1ZXMNCgkJCQllbHNlIGlmICggY29weSAhPT0gdW5kZWZpbmVkICkNCgkJCQkJdGFyZ2V0WyBuYW1lIF0gPSBjb3B5Ow0KDQoJCQl9DQoNCgkvLyBSZXR1cm4gdGhlIG1vZGlmaWVkIG9iamVjdA0KCXJldHVybiB0YXJnZXQ7DQp9Ow0KDQovLyBleGNsdWRlIHRoZSBmb2xsb3dpbmcgY3NzIHByb3BlcnRpZXMgdG8gYWRkIHB4DQp2YXIJZXhjbHVkZSA9IC96LT9pbmRleHxmb250LT93ZWlnaHR8b3BhY2l0eXx6b29tfGxpbmUtP2hlaWdodC9pLA0KCS8vIGNhY2hlIGRlZmF1bHRWaWV3DQoJZGVmYXVsdFZpZXcgPSBkb2N1bWVudC5kZWZhdWx0VmlldyB8fCB7fSwNCgl0b1N0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7DQoNCmpRdWVyeS5leHRlbmQoew0KCW5vQ29uZmxpY3Q6IGZ1bmN0aW9uKCBkZWVwICkgew0KCQkvLy8JPHN1bW1hcnk+DQoJCS8vLwkJUnVuIHRoaXMgZnVuY3Rpb24gdG8gZ2l2ZSBjb250cm9sIG9mIHRoZSAkIHZhcmlhYmxlIGJhY2sNCgkJLy8vCQl0byB3aGljaGV2ZXIgbGlicmFyeSBmaXJzdCBpbXBsZW1lbnRlZCBpdC4gVGhpcyBoZWxwcyB0byBtYWtlIA0KCQkvLy8JCXN1cmUgdGhhdCBqUXVlcnkgZG9lc24ndCBjb25mbGljdCB3aXRoIHRoZSAkIG9iamVjdA0KCQkvLy8JCW9mIG90aGVyIGxpYnJhcmllcy4NCgkJLy8vCQlCeSB1c2luZyB0aGlzIGZ1bmN0aW9uLCB5b3Ugd2lsbCBvbmx5IGJlIGFibGUgdG8gYWNjZXNzIGpRdWVyeQ0KCQkvLy8JCXVzaW5nIHRoZSAnalF1ZXJ5JyB2YXJpYWJsZS4gRm9yIGV4YW1wbGUsIHdoZXJlIHlvdSB1c2VkIHRvIGRvDQoJCS8vLwkJJCgmcXVvdDtkaXYgcCZxdW90OyksIHlvdSBub3cgbXVzdCBkbyBqUXVlcnkoJnF1b3Q7ZGl2IHAmcXVvdDspLg0KCQkvLy8JCVBhcnQgb2YgQ29yZSANCgkJLy8vCTwvc3VtbWFyeT4NCgkJLy8vCTxyZXR1cm5zIHR5cGU9InVuZGVmaW5lZCIgLz4NCgkJDQoJCXdpbmRvdy4kID0gXyQ7DQoNCgkJaWYgKCBkZWVwICkNCgkJCXdpbmRvdy5qUXVlcnkgPSBfalF1ZXJ5Ow0KDQoJCXJldHVybiBqUXVlcnk7DQoJfSwNCg0KCS8vIFNlZSB0ZXN0L3VuaXQvY29yZS5qcyBmb3IgZGV0YWlscyBjb25jZXJuaW5nIGlzRnVuY3Rpb24uDQoJLy8gU2luY2UgdmVyc2lvbiAxLjMsIERPTSBtZXRob2RzIGFuZCBmdW5jdGlvbnMgbGlrZSBhbGVydA0KCS8vIGFyZW4ndCBzdXBwb3J0ZWQuIFRoZXkgcmV0dXJuIGZhbHNlIG9uIElFICgjMjk2OCkuDQoJaXNGdW5jdGlvbjogZnVuY3Rpb24oIG9iaiApIHsNCgkJLy8vCTxzdW1tYXJ5Pg0KCQkvLy8JCURldGVybWluZXMgaWYgdGhlIHBhcmFtZXRlciBwYXNzZWQgaXMgYSBmdW5jdGlvbi4NCgkJLy8vCTwvc3VtbWFyeT4NCgkJLy8vCTxwYXJhbSBuYW1lPSJvYmoiIHR5cGU9Ik9iamVjdCI+VGhlIG9iamVjdCB0byBjaGVjazwvcGFyYW0+DQoJCS8vLwk8cmV0dXJucyB0eXBlPSJCb29sZWFuIj5UcnVlIGlmIHRoZSBwYXJhbWV0ZXIgaXMgYSBmdW5jdGlvbjsgb3RoZXJ3aXNlIGZhbHNlLjwvcmV0dXJucz4NCgkJDQoJCXJldHVybiB0b1N0cmluZy5jYWxsKG9iaikgPT09ICJbb2JqZWN0IEZ1bmN0aW9uXSI7DQoJfSwNCg0KCWlzQXJyYXk6IGZ1bmN0aW9uKG9iaikgew0KCSAgICAvLy8JPHN1bW1hcnk+DQoJICAgIC8vLwkJRGV0ZXJtaW5lIGlmIHRoZSBwYXJhbWV0ZXIgcGFzc2VkIGlzIGFuIGFycmF5Lg0KCSAgICAvLy8JPC9zdW1tYXJ5Pg0KCSAgICAvLy8JPHBhcmFtIG5hbWU9Im9iaiIgdHlwZT0iT2JqZWN0Ij5PYmplY3QgdG8gdGVzdCB3aGV0aGVyIG9yIG5vdCBpdCBpcyBhbiBhcnJheS48L3BhcmFtPg0KCSAgICAvLy8JPHJldHVybnMgdHlwZT0iQm9vbGVhbiI+VHJ1ZSBpZiB0aGUgcGFyYW1ldGVyIGlzIGEgZnVuY3Rpb247IG90aGVyd2lzZSBmYWxzZS48L3JldHVybnM+DQogICAgCQkNCgkJcmV0dXJuIHRvU3RyaW5nLmNhbGwob2JqKSA9PT0gIltvYmplY3QgQXJyYXldIjsNCgl9LA0KDQoJLy8gY2hlY2sgaWYgYW4gZWxlbWVudCBpcyBpbiBhIChvciBpcyBhbikgWE1MIGRvY3VtZW50DQoJaXNYTUxEb2M6IGZ1bmN0aW9uKCBlbGVtICkgew0KCQkvLy8JPHN1bW1hcnk+DQoJCS8vLwkJRGV0ZXJtaW5lcyBpZiB0aGUgcGFyYW1ldGVyIHBhc3NlZCBpcyBhbiBYTUwgZG9jdW1lbnQuDQoJCS8vLwk8L3N1bW1hcnk+DQoJCS8vLwk8cGFyYW0gbmFtZT0iZWxlbSIgdHlwZT0iT2JqZWN0Ij5UaGUgb2JqZWN0IHRvIHRlc3Q8L3BhcmFtPg0KCQkvLy8JPHJldHVybnMgdHlwZT0iQm9vbGVhbiI+VHJ1ZSBpZiB0aGUgcGFyYW1ldGVyIGlzIGFuIFhNTCBkb2N1bWVudDsgb3RoZXJ3aXNlIGZhbHNlLjwvcmV0dXJucz4NCg0KCSAgICByZXR1cm4gZWxlbS5ub2RlVHlwZSA9PT0gOSAmJiBlbGVtLmRvY3VtZW50RWxlbWVudC5ub2RlTmFtZSAhPT0gIkhUTUwiIHx8DQoJCQkhIWVsZW0ub3duZXJEb2N1bWVudCAmJiBqUXVlcnkuaXNYTUxEb2MoZWxlbS5vd25lckRvY3VtZW50KTsNCiAgICB9LA0KDQoJLy8gRXZhbHVsYXRlcyBhIHNjcmlwdCBpbiBhIGdsb2JhbCBjb250ZXh0DQoJZ2xvYmFsRXZhbDogZnVuY3Rpb24oIGRhdGEgKSB7DQoJCS8vLwk8c3VtbWFyeT4NCgkJLy8vCQlJbnRlcm5hbGx5IGV2YWx1YXRlcyBhIHNjcmlwdCBpbiBhIGdsb2JhbCBjb250ZXh0Lg0KCQkvLy8JPC9zdW1tYXJ5Pg0KCQkvLy8JPHByaXZhdGUgLz4NCg0KCQlpZiAoIGRhdGEgJiYgL1xTLy50ZXN0KGRhdGEpICkgew0KCQkJLy8gSW5zcGlyZWQgYnkgY29kZSBieSBBbmRyZWEgR2lhbW1hcmNoaQ0KCQkJLy8gaHR0cDovL3dlYnJlZmxlY3Rpb24uYmxvZ3Nwb3QuY29tLzIwMDcvMDgvZ2xvYmFsLXNjb3BlLWV2YWx1YXRpb24tYW5kLWRvbS5odG1sDQoJCQl2YXIgaGVhZCA9IGRvY3VtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKCJoZWFkIilbMF0gfHwgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LA0KCQkJCXNjcmlwdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoInNjcmlwdCIpOw0KDQoJCQlzY3JpcHQudHlwZSA9ICJ0ZXh0L2phdmFzY3JpcHQiOw0KCQkJaWYgKCBqUXVlcnkuc3VwcG9ydC5zY3JpcHRFdmFsICkNCgkJCQlzY3JpcHQuYXBwZW5kQ2hpbGQoIGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKCBkYXRhICkgKTsNCgkJCWVsc2UNCgkJCQlzY3JpcHQudGV4dCA9IGRhdGE7DQoNCgkJCS8vIFVzZSBpbnNlcnRCZWZvcmUgaW5zdGVhZCBvZiBhcHBlbmRDaGlsZCAgdG8gY2lyY3VtdmVudCBhbiBJRTYgYnVnLg0KCQkJLy8gVGhpcyBhcmlzZXMgd2hlbiBhIGJhc2Ugbm9kZSBpcyB1c2VkICgjMjcwOSkuDQoJCQloZWFkLmluc2VydEJlZm9yZSggc2NyaXB0LCBoZWFkLmZpcnN0Q2hpbGQgKTsNCgkJCWhlYWQucmVtb3ZlQ2hpbGQoIHNjcmlwdCApOw0KCQl9DQoJfSwNCg0KCW5vZGVOYW1lOiBmdW5jdGlvbiggZWxlbSwgbmFtZSApIHsNCgkJLy8vCTxzdW1tYXJ5Pg0KCQkvLy8JCUNoZWNrcyB3aGV0aGVyIHRoZSBzcGVjaWZpZWQgZWxlbWVudCBoYXMgdGhlIHNwZWNpZmllZCBET00gbm9kZSBuYW1lLg0KCQkvLy8JPC9zdW1tYXJ5Pg0KCQkvLy8JPHBhcmFtIG5hbWU9ImVsZW0iIHR5cGU9IkVsZW1lbnQiPlRoZSBlbGVtZW50IHRvIGV4YW1pbmU8L3BhcmFtPg0KCQkvLy8JPHBhcmFtIG5hbWU9Im5hbWUiIHR5cGU9IlN0cmluZyI+VGhlIG5vZGUgbmFtZSB0byBjaGVjazwvcGFyYW0+DQoJCS8vLwk8cmV0dXJucyB0eXBlPSJCb29sZWFuIj5UcnVlIGlmIHRoZSBzcGVjaWZpZWQgbm9kZSBuYW1lIG1hdGNoZXMgdGhlIG5vZGUncyBET00gbm9kZSBuYW1lOyBvdGhlcndpc2UgZmFsc2U8L3JldHVybnM+DQoNCgkJcmV0dXJuIGVsZW0ubm9kZU5hbWUgJiYgZWxlbS5ub2RlTmFtZS50b1VwcGVyQ2FzZSgpID09IG5hbWUudG9VcHBlckNhc2UoKTsNCgl9LA0KDQoJLy8gYXJncyBpcyBmb3IgaW50ZXJuYWwgdXNhZ2Ugb25seQ0KCWVhY2g6IGZ1bmN0aW9uKCBvYmplY3QsIGNhbGxiYWNrLCBhcmdzICkgew0KCQkvLy8JPHN1bW1hcnk+DQoJCS8vLwkJQSBnZW5lcmljIGl0ZXJhdG9yIGZ1bmN0aW9uLCB3aGljaCBjYW4gYmUgdXNlZCB0byBzZWVtbGVzc2x5DQoJCS8vLwkJaXRlcmF0ZSBvdmVyIGJvdGggb2JqZWN0cyBhbmQgYXJyYXlzLiBUaGlzIGZ1bmN0aW9uIGlzIG5vdCB0aGUgc2FtZQ0KCQkvLy8JCWFzICQoKS5lYWNoKCkgLSB3aGljaCBpcyB1c2VkIHRvIGl0ZXJhdGUsIGV4Y2x1c2l2ZWx5LCBvdmVyIGEgalF1ZXJ5DQoJCS8vLwkJb2JqZWN0LiBUaGlzIGZ1bmN0aW9uIGNhbiBiZSB1c2VkIHRvIGl0ZXJhdGUgb3ZlciBhbnl0aGluZy4NCgkJLy8vCQlUaGUgY2FsbGJhY2sgaGFzIHR3byBhcmd1bWVudHM6dGhlIGtleSAob2JqZWN0cykgb3IgaW5kZXggKGFycmF5cykgYXMgZmlyc3QNCgkJLy8vCQl0aGUgZmlyc3QsIGFuZCB0aGUgdmFsdWUgYXMgdGhlIHNlY29uZC4NCgkJLy8vCQlQYXJ0IG9mIEphdmFTY3JpcHQNCgkJLy8vCTwvc3VtbWFyeT4NCgkJLy8vCTxwYXJhbSBuYW1lPSJvYmoiIHR5cGU9Ik9iamVjdCI+DQoJCS8vLwkJIFRoZSBvYmplY3QsIG9yIGFycmF5LCB0byBpdGVyYXRlIG92ZXIuDQoJCS8vLwk8L3BhcmFtPg0KCQkvLy8JPHBhcmFtIG5hbWU9ImZuIiB0eXBlPSJGdW5jdGlvbiI+DQoJCS8vLwkJIFRoZSBmdW5jdGlvbiB0aGF0IHdpbGwgYmUgZXhlY3V0ZWQgb24gZXZlcnkgb2JqZWN0Lg0KCQkvLy8JPC9wYXJhbT4NCgkJLy8vCTxyZXR1cm5zIHR5cGU9Ik9iamVjdCIgLz4NCgkJDQoJCXZhciBuYW1lLCBpID0gMCwgbGVuZ3RoID0gb2JqZWN0Lmxlbmd0aDsNCg0KCQlpZiAoIGFyZ3MgKSB7DQoJCQlpZiAoIGxlbmd0aCA9PT0gdW5kZWZpbmVkICkgew0KCQkJCWZvciAoIG5hbWUgaW4gb2JqZWN0ICkNCgkJCQkJaWYgKCBjYWxsYmFjay5hcHBseSggb2JqZWN0WyBuYW1lIF0sIGFyZ3MgKSA9PT0gZmFsc2UgKQ0KCQkJCQkJYnJlYWs7DQoJCQl9IGVsc2UNCgkJCQlmb3IgKCA7IGkgPCBsZW5ndGg7ICkNCgkJCQkJaWYgKCBjYWxsYmFjay5hcHBseSggb2JqZWN0WyBpKysgXSwgYXJncyApID09PSBmYWxzZSApDQoJCQkJCQlicmVhazsNCg0KCQkvLyBBIHNwZWNpYWwsIGZhc3QsIGNhc2UgZm9yIHRoZSBtb3N0IGNvbW1vbiB1c2Ugb2YgZWFjaA0KCQl9IGVsc2Ugew0KCQkJaWYgKCBsZW5ndGggPT09IHVuZGVmaW5lZCApIHsNCgkJCQlmb3IgKCBuYW1lIGluIG9iamVjdCApDQoJCQkJCWlmICggY2FsbGJhY2suY2FsbCggb2JqZWN0WyBuYW1lIF0sIG5hbWUsIG9iamVjdFsgbmFtZSBdICkgPT09IGZhbHNlICkNCgkJCQkJCWJyZWFrOw0KCQkJfSBlbHNlDQoJCQkJZm9yICggdmFyIHZhbHVlID0gb2JqZWN0WzBdOw0KCQkJCQlpIDwgbGVuZ3RoICYmIGNhbGxiYWNrLmNhbGwoIHZhbHVlLCBpLCB2YWx1ZSApICE9PSBmYWxzZTsgdmFsdWUgPSBvYmplY3RbKytpXSApe30NCgkJfQ0KDQoJCXJldHVybiBvYmplY3Q7DQoJfSwNCg0KCXByb3A6IGZ1bmN0aW9uKCBlbGVtLCB2YWx1ZSwgdHlwZSwgaSwgbmFtZSApIHsNCgkJLy8vCTxzdW1tYXJ5Pg0KCQkvLy8JCVRoaXMgbWV0aG9kIGlzIGludGVybmFsLg0KCQkvLy8JPC9zdW1tYXJ5Pg0KCQkvLy8JPHByaXZhdGUgLz4NCgkJLy8gVGhpcyBtZW1iZXIgaXMgbm90IGRvY3VtZW50ZWQgd2l0aGluIHRoZSBqUXVlcnkgQVBJOiBodHRwOi8vZG9jcy5qcXVlcnkuY29tL2FjdGlvbi9lZGl0L0ludGVybmFscy9qUXVlcnkucHJvcA0KDQoJCS8vIEhhbmRsZSBleGVjdXRhYmxlIGZ1bmN0aW9ucw0KCQlpZiAoIGpRdWVyeS5pc0Z1bmN0aW9uKCB2YWx1ZSApICkNCgkJCXZhbHVlID0gdmFsdWUuY2FsbCggZWxlbSwgaSApOw0KDQoJCS8vIEhhbmRsZSBwYXNzaW5nIGluIGEgbnVtYmVyIHRvIGEgQ1NTIHByb3BlcnR5DQoJCXJldHVybiB0eXBlb2YgdmFsdWUgPT09ICJudW1iZXIiICYmIHR5cGUgPT0gImN1ckNTUyIgJiYgIWV4Y2x1ZGUudGVzdCggbmFtZSApID8NCgkJCXZhbHVlICsgInB4IiA6DQoJCQl2YWx1ZTsNCgl9LA0KDQoJY2xhc3NOYW1lOiB7DQoJCS8vIGludGVybmFsIG9ubHksIHVzZSBhZGRDbGFzcygiY2xhc3MiKQ0KCQlhZGQ6IGZ1bmN0aW9uKCBlbGVtLCBjbGFzc05hbWVzICkgew0KICAgCQkJLy8vCTxzdW1tYXJ5Pg0KICAgCQkJLy8vCQlJbnRlcm5hbCB1c2Ugb25seTsgdXNlIGFkZENsYXNzKCdjbGFzcycpDQoJCQkvLy8JPC9zdW1tYXJ5Pg0KICAgCQkJLy8vCTxwcml2YXRlIC8+DQoNCgkJCWpRdWVyeS5lYWNoKChjbGFzc05hbWVzIHx8ICIiKS5zcGxpdCgvXHMrLyksIGZ1bmN0aW9uKGksIGNsYXNzTmFtZSl7DQoJCQkJaWYgKCBlbGVtLm5vZGVUeXBlID09IDEgJiYgIWpRdWVyeS5jbGFzc05hbWUuaGFzKCBlbGVtLmNsYXNzTmFtZSwgY2xhc3NOYW1lICkgKQ0KCQkJCQllbGVtLmNsYXNzTmFtZSArPSAoZWxlbS5jbGFzc05hbWUgPyAiICIgOiAiIikgKyBjbGFzc05hbWU7DQoJCQl9KTsNCgkJfSwNCg0KCQkvLyBpbnRlcm5hbCBvbmx5LCB1c2UgcmVtb3ZlQ2xhc3MoImNsYXNzIikNCgkJcmVtb3ZlOiBmdW5jdGlvbiggZWxlbSwgY2xhc3NOYW1lcyApIHsNCiAgIAkJCS8vLwk8c3VtbWFyeT4NCiAgIAkJCS8vLwkJSW50ZXJuYWwgdXNlIG9ubHk7IHVzZSByZW1vdmVDbGFzcygnY2xhc3MnKQ0KCQkJLy8vCTwvc3VtbWFyeT4NCiAgIAkJCS8vLwk8cHJpdmF0ZSAvPg0KDQoJCQlpZiAoZWxlbS5ub2RlVHlwZSA9PSAxKQ0KCQkJCWVsZW0uY2xhc3NOYW1lID0gY2xhc3NOYW1lcyAhPT0gdW5kZWZpbmVkID8NCgkJCQkJalF1ZXJ5LmdyZXAoZWxlbS5jbGFzc05hbWUuc3BsaXQoL1xzKy8pLCBmdW5jdGlvbihjbGFzc05hbWUpew0KCQkJCQkJcmV0dXJuICFqUXVlcnkuY2xhc3NOYW1lLmhhcyggY2xhc3NOYW1lcywgY2xhc3NOYW1lICk7DQoJCQkJCX0pLmpvaW4oIiAiKSA6DQoJCQkJCSIiOw0KCQl9LA0KDQoJCS8vIGludGVybmFsIG9ubHksIHVzZSBoYXNDbGFzcygiY2xhc3MiKQ0KCQloYXM6IGZ1bmN0aW9uKCBlbGVtLCBjbGFzc05hbWUgKSB7DQogICAJCQkvLy8JPHN1bW1hcnk+DQogICAJCQkvLy8JCUludGVybmFsIHVzZSBvbmx5OyB1c2UgaGFzQ2xhc3MoJ2NsYXNzJykNCgkJCS8vLwk8L3N1bW1hcnk+DQogICAJCQkvLy8JPHByaXZhdGUgLz4NCg0KCQkgICAgcmV0dXJuIGVsZW0gJiYgalF1ZXJ5LmluQXJyYXkoY2xhc3NOYW1lLCAoZWxlbS5jbGFzc05hbWUgfHwgZWxlbSkudG9TdHJpbmcoKS5zcGxpdCgvXHMrLykpID4gLTE7DQoJCX0NCgl9LA0KDQoJLy8gQSBtZXRob2QgZm9yIHF1aWNrbHkgc3dhcHBpbmcgaW4vb3V0IENTUyBwcm9wZXJ0aWVzIHRvIGdldCBjb3JyZWN0IGNhbGN1bGF0aW9ucw0KCXN3YXA6IGZ1bmN0aW9uKCBlbGVtLCBvcHRpb25zLCBjYWxsYmFjayApIHsNCgkJLy8vCTxzdW1tYXJ5Pg0KCQkvLy8JCVN3YXAgaW4vb3V0IHN0eWxlIG9wdGlvbnMuDQoJCS8vLwk8L3N1bW1hcnk+DQoNCgkJdmFyIG9sZCA9IHt9Ow0KCQkvLyBSZW1lbWJlciB0aGUgb2xkIHZhbHVlcywgYW5kIGluc2VydCB0aGUgbmV3IG9uZXMNCgkJZm9yICggdmFyIG5hbWUgaW4gb3B0aW9ucyApIHsNCgkJCW9sZFsgbmFtZSBdID0gZWxlbS5zdHlsZVsgbmFtZSBdOw0KCQkJZWxlbS5zdHlsZVsgbmFtZSBdID0gb3B0aW9uc1sgbmFtZSBdOw0KCQl9DQoNCgkJY2FsbGJhY2suY2FsbCggZWxlbSApOw0KDQoJCS8vIFJldmVydCB0aGUgb2xkIHZhbHVlcw0KCQlmb3IgKCB2YXIgbmFtZSBpbiBvcHRpb25zICkNCgkJCWVsZW0uc3R5bGVbIG5hbWUgXSA9IG9sZFsgbmFtZSBdOw0KCX0sDQoNCgljc3M6IGZ1bmN0aW9uKCBlbGVtLCBuYW1lLCBmb3JjZSwgZXh0cmEgKSB7DQoJCS8vLwk8c3VtbWFyeT4NCgkJLy8vCQlUaGlzIG1ldGhvZCBpcyBpbnRlcm5hbCBvbmx5Lg0KCQkvLy8JPC9zdW1tYXJ5Pg0KCQkvLy8JPHByaXZhdGUgLz4NCgkJLy8gVGhpcyBtZXRob2QgaXMgdW5kb2N1bWVudGVkIGluIGpRdWVyeSBBUEk6IGh0dHA6Ly9kb2NzLmpxdWVyeS5jb20vYWN0aW9uL2VkaXQvSW50ZXJuYWxzL2pRdWVyeS5jc3MNCg0KCQlpZiAoIG5hbWUgPT0gIndpZHRoIiB8fCBuYW1lID09ICJoZWlnaHQiICkgew0KCQkJdmFyIHZhbCwgcHJvcHMgPSB7IHBvc2l0aW9uOiAiYWJzb2x1dGUiLCB2aXNpYmlsaXR5OiAiaGlkZGVuIiwgZGlzcGxheToiYmxvY2siIH0sIHdoaWNoID0gbmFtZSA9PSAid2lkdGgiID8gWyAiTGVmdCIsICJSaWdodCIgXSA6IFsgIlRvcCIsICJCb3R0b20iIF07DQoNCgkJCWZ1bmN0aW9uIGdldFdIKCkgew0KCQkJCXZhbCA9IG5hbWUgPT0gIndpZHRoIiA/IGVsZW0ub2Zmc2V0V2lkdGggOiBlbGVtLm9mZnNldEhlaWdodDsNCg0KCQkJCWlmICggZXh0cmEgPT09ICJib3JkZXIiICkNCgkJCQkJcmV0dXJuOw0KDQoJCQkJalF1ZXJ5LmVhY2goIHdoaWNoLCBmdW5jdGlvbigpIHsNCgkJCQkJaWYgKCAhZXh0cmEgKQ0KCQkJCQkJdmFsIC09IHBhcnNlRmxvYXQoalF1ZXJ5LmN1ckNTUyggZWxlbSwgInBhZGRpbmciICsgdGhpcywgdHJ1ZSkpIHx8IDA7DQoJCQkJCWlmICggZXh0cmEgPT09ICJtYXJnaW4iICkNCgkJCQkJCXZhbCArPSBwYXJzZUZsb2F0KGpRdWVyeS5jdXJDU1MoIGVsZW0sICJtYXJnaW4iICsgdGhpcywgdHJ1ZSkpIHx8IDA7DQoJCQkJCWVsc2UNCgkJCQkJCXZhbCAtPSBwYXJzZUZsb2F0KGpRdWVyeS5jdXJDU1MoIGVsZW0sICJib3JkZXIiICsgdGhpcyArICJXaWR0aCIsIHRydWUpKSB8fCAwOw0KCQkJCX0pOw0KCQkJfQ0KDQoJCQlpZiAoIGVsZW0ub2Zmc2V0V2lkdGggIT09IDAgKQ0KCQkJCWdldFdIKCk7DQoJCQllbHNlDQoJCQkJalF1ZXJ5LnN3YXAoIGVsZW0sIHByb3BzLCBnZXRXSCApOw0KDQoJCQlyZXR1cm4gTWF0aC5tYXgoMCwgTWF0aC5yb3VuZCh2YWwpKTsNCgkJfQ0KDQoJCXJldHVybiBqUXVlcnkuY3VyQ1NTKCBlbGVtLCBuYW1lLCBmb3JjZSApOw0KCX0sDQoNCgljdXJDU1M6IGZ1bmN0aW9uKCBlbGVtLCBuYW1lLCBmb3JjZSApIHsNCgkJLy8vCTxzdW1tYXJ5Pg0KCQkvLy8JCVRoaXMgbWV0aG9kIGlzIGludGVybmFsIG9ubHkuDQoJCS8vLwk8L3N1bW1hcnk+DQoJCS8vLwk8cHJpdmF0ZSAvPg0KCQkvLyBUaGlzIG1ldGhvZCBpcyB1bmRvY3VtZW50ZWQgaW4galF1ZXJ5IEFQSTogaHR0cDovL2RvY3MuanF1ZXJ5LmNvbS9hY3Rpb24vZWRpdC9JbnRlcm5hbHMvalF1ZXJ5LmN1ckNTUw0KDQoJCXZhciByZXQsIHN0eWxlID0gZWxlbS5zdHlsZTsNCg0KCQkvLyBXZSBuZWVkIHRvIGhhbmRsZSBvcGFjaXR5IHNwZWNpYWwgaW4gSUUNCgkJaWYgKCBuYW1lID09ICJvcGFjaXR5IiAmJiAhalF1ZXJ5LnN1cHBvcnQub3BhY2l0eSApIHsNCgkJCXJldCA9IGpRdWVyeS5hdHRyKCBzdHlsZSwgIm9wYWNpdHkiICk7DQoNCgkJCXJldHVybiByZXQgPT0gIiIgPw0KCQkJCSIxIiA6DQoJCQkJcmV0Ow0KCQl9DQoNCgkJLy8gTWFrZSBzdXJlIHdlJ3JlIHVzaW5nIHRoZSByaWdodCBuYW1lIGZvciBnZXR0aW5nIHRoZSBmbG9hdCB2YWx1ZQ0KCQlpZiAoIG5hbWUubWF0Y2goIC9mbG9hdC9pICkgKQ0KCQkJbmFtZSA9IHN0eWxlRmxvYXQ7DQoNCgkJaWYgKCAhZm9yY2UgJiYgc3R5bGUgJiYgc3R5bGVbIG5hbWUgXSApDQoJCQlyZXQgPSBzdHlsZVsgbmFtZSBdOw0KDQoJCWVsc2UgaWYgKCBkZWZhdWx0Vmlldy5nZXRDb21wdXRlZFN0eWxlICkgew0KDQoJCQkvLyBPbmx5ICJmbG9hdCIgaXMgbmVlZGVkIGhlcmUNCgkJCWlmICggbmFtZS5tYXRjaCggL2Zsb2F0L2kgKSApDQoJCQkJbmFtZSA9ICJmbG9hdCI7DQoNCgkJCW5hbWUgPSBuYW1lLnJlcGxhY2UoIC8oW0EtWl0pL2csICItJDEiICkudG9Mb3dlckNhc2UoKTsNCg0KCQkJdmFyIGNvbXB1dGVkU3R5bGUgPSBkZWZhdWx0Vmlldy5nZXRDb21wdXRlZFN0eWxlKCBlbGVtLCBudWxsICk7DQoNCgkJCWlmICggY29tcHV0ZWRTdHlsZSApDQoJCQkJcmV0ID0gY29tcHV0ZWRTdHlsZS5nZXRQcm9wZXJ0eVZhbHVlKCBuYW1lICk7DQoNCgkJCS8vIFdlIHNob3VsZCBhbHdheXMgZ2V0IGEgbnVtYmVyIGJhY2sgZnJvbSBvcGFjaXR5DQoJCQlpZiAoIG5hbWUgPT0gIm9wYWNpdHkiICYmIHJldCA9PSAiIiApDQoJCQkJcmV0ID0gIjEiOw0KDQoJCX0gZWxzZSBpZiAoIGVsZW0uY3VycmVudFN0eWxlICkgew0KCQkJdmFyIGNhbWVsQ2FzZSA9IG5hbWUucmVwbGFjZSgvXC0oXHcpL2csIGZ1bmN0aW9uKGFsbCwgbGV0dGVyKXsNCgkJCQlyZXR1cm4gbGV0dGVyLnRvVXBwZXJDYXNlKCk7DQoJCQl9KTsNCg0KCQkJcmV0ID0gZWxlbS5jdXJyZW50U3R5bGVbIG5hbWUgXSB8fCBlbGVtLmN1cnJlbnRTdHlsZVsgY2FtZWxDYXNlIF07DQoNCgkJCS8vIEZyb20gdGhlIGF3ZXNvbWUgaGFjayBieSBEZWFuIEVkd2FyZHMNCgkJCS8vIGh0dHA6Ly9lcmlrLmVhZS5uZXQvYXJjaGl2ZXMvMjAwNy8wNy8yNy8xOC41NC4xNS8jY29tbWVudC0xMDIyOTENCg0KCQkJLy8gSWYgd2UncmUgbm90IGRlYWxpbmcgd2l0aCBhIHJlZ3VsYXIgcGl4ZWwgbnVtYmVyDQoJCQkvLyBidXQgYSBudW1iZXIgdGhhdCBoYXMgYSB3ZWlyZCBlbmRpbmcsIHdlIG5lZWQgdG8gY29udmVydCBpdCB0byBwaXhlbHMNCgkJCWlmICggIS9eXGQrKHB4KT8kL2kudGVzdCggcmV0ICkgJiYgL15cZC8udGVzdCggcmV0ICkgKSB7DQoJCQkJLy8gUmVtZW1iZXIgdGhlIG9yaWdpbmFsIHZhbHVlcw0KCQkJCXZhciBsZWZ0ID0gc3R5bGUubGVmdCwgcnNMZWZ0ID0gZWxlbS5ydW50aW1lU3R5bGUubGVmdDsNCg0KCQkJCS8vIFB1dCBpbiB0aGUgbmV3IHZhbHVlcyB0byBnZXQgYSBjb21wdXRlZCB2YWx1ZSBvdXQNCgkJCQllbGVtLnJ1bnRpbWVTdHlsZS5sZWZ0ID0gZWxlbS5jdXJyZW50U3R5bGUubGVmdDsNCgkJCQlzdHlsZS5sZWZ0ID0gcmV0IHx8IDA7DQoJCQkJcmV0ID0gc3R5bGUucGl4ZWxMZWZ0ICsgInB4IjsNCg0KCQkJCS8vIFJldmVydCB0aGUgY2hhbmdlZCB2YWx1ZXMNCgkJCQlzdHlsZS5sZWZ0ID0gbGVmdDsNCgkJCQllbGVtLnJ1bnRpbWVTdHlsZS5sZWZ0ID0gcnNMZWZ0Ow0KCQkJfQ0KCQl9DQoNCgkJcmV0dXJuIHJldDsNCgl9LA0KDQoJY2xlYW46IGZ1bmN0aW9uKCBlbGVtcywgY29udGV4dCwgZnJhZ21lbnQgKSB7DQoJCS8vLwk8c3VtbWFyeT4NCgkJLy8vCQlUaGlzIG1ldGhvZCBpcyBpbnRlcm5hbCBvbmx5Lg0KCQkvLy8JPC9zdW1tYXJ5Pg0KCQkvLy8JPHByaXZhdGUgLz4NCgkJLy8gVGhpcyBtZXRob2QgaXMgdW5kb2N1bWVudGVkIGluIHRoZSBqUXVlcnkgQVBJOiBodHRwOi8vZG9jcy5qcXVlcnkuY29tL2FjdGlvbi9lZGl0L0ludGVybmFscy9qUXVlcnkuY2xlYW4NCg0KDQoJCWNvbnRleHQgPSBjb250ZXh0IHx8IGRvY3VtZW50Ow0KDQoJCS8vICFjb250ZXh0LmNyZWF0ZUVsZW1lbnQgZmFpbHMgaW4gSUUgd2l0aCBhbiBlcnJvciBidXQgcmV0dXJucyB0eXBlb2YgJ29iamVjdCcNCgkJaWYgKCB0eXBlb2YgY29udGV4dC5jcmVhdGVFbGVtZW50ID09PSAidW5kZWZpbmVkIiApDQoJCQljb250ZXh0ID0gY29udGV4dC5vd25lckRvY3VtZW50IHx8IGNvbnRleHRbMF0gJiYgY29udGV4dFswXS5vd25lckRvY3VtZW50IHx8IGRvY3VtZW50Ow0KDQoJCS8vIElmIGEgc2luZ2xlIHN0cmluZyBpcyBwYXNzZWQgaW4gYW5kIGl0J3MgYSBzaW5nbGUgdGFnDQoJCS8vIGp1c3QgZG8gYSBjcmVhdGVFbGVtZW50IGFuZCBza2lwIHRoZSByZXN0DQoJCWlmICggIWZyYWdtZW50ICYmIGVsZW1zLmxlbmd0aCA9PT0gMSAmJiB0eXBlb2YgZWxlbXNbMF0gPT09ICJzdHJpbmciICkgew0KCQkJdmFyIG1hdGNoID0gL148KFx3KylccypcLz8+JC8uZXhlYyhlbGVtc1swXSk7DQoJCQlpZiAoIG1hdGNoICkNCgkJCQlyZXR1cm4gWyBjb250ZXh0LmNyZWF0ZUVsZW1lbnQoIG1hdGNoWzFdICkgXTsNCgkJfQ0KDQoJCXZhciByZXQgPSBbXSwgc2NyaXB0cyA9IFtdLCBkaXYgPSBjb250ZXh0LmNyZWF0ZUVsZW1lbnQoImRpdiIpOw0KDQoJCWpRdWVyeS5lYWNoKGVsZW1zLCBmdW5jdGlvbihpLCBlbGVtKXsNCgkJCWlmICggdHlwZW9mIGVsZW0gPT09ICJudW1iZXIiICkNCgkJCQllbGVtICs9ICcnOw0KDQoJCQlpZiAoICFlbGVtICkNCgkJCQlyZXR1cm47DQoNCgkJCS8vIENvbnZlcnQgaHRtbCBzdHJpbmcgaW50byBET00gbm9kZXMNCgkJCWlmICggdHlwZW9mIGVsZW0gPT09ICJzdHJpbmciICkgew0KCQkJCS8vIEZpeCAiWEhUTUwiLXN0eWxlIHRhZ3MgaW4gYWxsIGJyb3dzZXJzDQoJCQkJZWxlbSA9IGVsZW0ucmVwbGFjZSgvKDwoXHcrKVtePl0qPylcLz4vZywgZnVuY3Rpb24oYWxsLCBmcm9udCwgdGFnKXsNCgkJCQkJcmV0dXJuIHRhZy5tYXRjaCgvXihhYmJyfGJyfGNvbHxpbWd8aW5wdXR8bGlua3xtZXRhfHBhcmFtfGhyfGFyZWF8ZW1iZWQpJC9pKSA/DQoJCQkJCQlhbGwgOg0KCQkJCQkJZnJvbnQgKyAiPjwvIiArIHRhZyArICI+IjsNCgkJCQl9KTsNCg0KCQkJCS8vIFRyaW0gd2hpdGVzcGFjZSwgb3RoZXJ3aXNlIGluZGV4T2Ygd29uJ3Qgd29yayBhcyBleHBlY3RlZA0KCQkJCXZhciB0YWdzID0gZWxlbS5yZXBsYWNlKC9eXHMrLywgIiIpLnN1YnN0cmluZygwLCAxMCkudG9Mb3dlckNhc2UoKTsNCg0KCQkJCXZhciB3cmFwID0NCgkJCQkJLy8gb3B0aW9uIG9yIG9wdGdyb3VwDQoJCQkJCSF0YWdzLmluZGV4T2YoIjxvcHQiKSAmJg0KCQkJCQlbIDEsICI8c2VsZWN0IG11bHRpcGxlPSdtdWx0aXBsZSc+IiwgIjwvc2VsZWN0PiIgXSB8fA0KDQoJCQkJCSF0YWdzLmluZGV4T2YoIjxsZWciKSAmJg0KCQkJCQlbIDEsICI8ZmllbGRzZXQ+IiwgIjwvZmllbGRzZXQ+IiBdIHx8DQoNCgkJCQkJdGFncy5tYXRjaCgvXjwodGhlYWR8dGJvZHl8dGZvb3R8Y29sZ3xjYXApLykgJiYNCgkJCQkJWyAxLCAiPHRhYmxlPiIsICI8L3RhYmxlPiIgXSB8fA0KDQoJCQkJCSF0YWdzLmluZGV4T2YoIjx0ciIpICYmDQoJCQkJCVsgMiwgIjx0YWJsZT48dGJvZHk+IiwgIjwvdGJvZHk+PC90YWJsZT4iIF0gfHwNCg0KCQkJCSAJLy8gPHRoZWFkPiBtYXRjaGVkIGFib3ZlDQoJCQkJCSghdGFncy5pbmRleE9mKCI8dGQiKSB8fCAhdGFncy5pbmRleE9mKCI8dGgiKSkgJiYNCgkJCQkJWyAzLCAiPHRhYmxlPjx0Ym9keT48dHI+IiwgIjwvdHI+PC90Ym9keT48L3RhYmxlPiIgXSB8fA0KDQoJCQkJCSF0YWdzLmluZGV4T2YoIjxjb2wiKSAmJg0KCQkJCQlbIDIsICI8dGFibGU+PHRib2R5PjwvdGJvZHk+PGNvbGdyb3VwPiIsICI8L2NvbGdyb3VwPjwvdGFibGU+IiBdIHx8DQoNCgkJCQkJLy8gSUUgY2FuJ3Qgc2VyaWFsaXplIDxsaW5rPiBhbmQgPHNjcmlwdD4gdGFncyBub3JtYWxseQ0KCQkJCQkhalF1ZXJ5LnN1cHBvcnQuaHRtbFNlcmlhbGl6ZSAmJg0KCQkJCQlbIDEsICJkaXY8ZGl2PiIsICI8L2Rpdj4iIF0gfHwNCg0KCQkJCQlbIDAsICIiLCAiIiBdOw0KDQoJCQkJLy8gR28gdG8gaHRtbCBhbmQgYmFjaywgdGhlbiBwZWVsIG9mZiBleHRyYSB3cmFwcGVycw0KCQkJCWRpdi5pbm5lckhUTUwgPSB3cmFwWzFdICsgZWxlbSArIHdyYXBbMl07DQoNCgkJCQkvLyBNb3ZlIHRvIHRoZSByaWdodCBkZXB0aA0KCQkJCXdoaWxlICggd3JhcFswXS0tICkNCgkJCQkJZGl2ID0gZGl2Lmxhc3RDaGlsZDsNCg0KCQkJCS8vIFJlbW92ZSBJRSdzIGF1dG9pbnNlcnRlZCA8dGJvZHk+IGZyb20gdGFibGUgZnJhZ21lbnRzDQoJCQkJaWYgKCAhalF1ZXJ5LnN1cHBvcnQudGJvZHkgKSB7DQoNCgkJCQkJLy8gU3RyaW5nIHdhcyBhIDx0YWJsZT4sICptYXkqIGhhdmUgc3B1cmlvdXMgPHRib2R5Pg0KCQkJCQl2YXIgaGFzQm9keSA9IC88dGJvZHkvaS50ZXN0KGVsZW0pLA0KCQkJCQkJdGJvZHkgPSAhdGFncy5pbmRleE9mKCI8dGFibGUiKSAmJiAhaGFzQm9keSA/DQoJCQkJCQkJZGl2LmZpcnN0Q2hpbGQgJiYgZGl2LmZpcnN0Q2hpbGQuY2hpbGROb2RlcyA6DQoNCgkJCQkJCS8vIFN0cmluZyB3YXMgYSBiYXJlIDx0aGVhZD4gb3IgPHRmb290Pg0KCQkJCQkJd3JhcFsxXSA9PSAiPHRhYmxlPiIgJiYgIWhhc0JvZHkgPw0KCQkJCQkJCWRpdi5jaGlsZE5vZGVzIDoNCgkJCQkJCQlbXTsNCg0KCQkJCQlmb3IgKCB2YXIgaiA9IHRib2R5Lmxlbmd0aCAtIDE7IGogPj0gMCA7IC0taiApDQoJCQkJCQlpZiAoIGpRdWVyeS5ub2RlTmFtZSggdGJvZHlbIGogXSwgInRib2R5IiApICYmICF0Ym9keVsgaiBdLmNoaWxkTm9kZXMubGVuZ3RoICkNCgkJCQkJCQl0Ym9keVsgaiBdLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoIHRib2R5WyBqIF0gKTsNCg0KCQkJCQl9DQoNCgkJCQkvLyBJRSBjb21wbGV0ZWx5IGtpbGxzIGxlYWRpbmcgd2hpdGVzcGFjZSB3aGVuIGlubmVySFRNTCBpcyB1c2VkDQoJCQkJaWYgKCAhalF1ZXJ5LnN1cHBvcnQubGVhZGluZ1doaXRlc3BhY2UgJiYgL15ccy8udGVzdCggZWxlbSApICkNCgkJCQkJZGl2Lmluc2VydEJlZm9yZSggY29udGV4dC5jcmVhdGVUZXh0Tm9kZSggZWxlbS5tYXRjaCgvXlxzKi8pWzBdICksIGRpdi5maXJzdENoaWxkICk7DQoJCQkJDQoJCQkJZWxlbSA9IGpRdWVyeS5tYWtlQXJyYXkoIGRpdi5jaGlsZE5vZGVzICk7DQoJCQl9DQoNCgkJCWlmICggZWxlbS5ub2RlVHlwZSApDQoJCQkJcmV0LnB1c2goIGVsZW0gKTsNCgkJCWVsc2UNCgkJCQlyZXQgPSBqUXVlcnkubWVyZ2UoIHJldCwgZWxlbSApOw0KDQoJCX0pOw0KDQoJCWlmICggZnJhZ21lbnQgKSB7DQoJCQlmb3IgKCB2YXIgaSA9IDA7IHJldFtpXTsgaSsrICkgew0KCQkJCWlmICggalF1ZXJ5Lm5vZGVOYW1lKCByZXRbaV0sICJzY3JpcHQiICkgJiYgKCFyZXRbaV0udHlwZSB8fCByZXRbaV0udHlwZS50b0xvd2VyQ2FzZSgpID09PSAidGV4dC9qYXZhc2NyaXB0IikgKSB7DQoJCQkJCXNjcmlwdHMucHVzaCggcmV0W2ldLnBhcmVudE5vZGUgPyByZXRbaV0ucGFyZW50Tm9kZS5yZW1vdmVDaGlsZCggcmV0W2ldICkgOiByZXRbaV0gKTsNCgkJCQl9IGVsc2Ugew0KCQkJCQlpZiAoIHJldFtpXS5ub2RlVHlwZSA9PT0gMSApDQoJCQkJCQlyZXQuc3BsaWNlLmFwcGx5KCByZXQsIFtpICsgMSwgMF0uY29uY2F0KGpRdWVyeS5tYWtlQXJyYXkocmV0W2ldLmdldEVsZW1lbnRzQnlUYWdOYW1lKCJzY3JpcHQiKSkpICk7DQoJCQkJCWZyYWdtZW50LmFwcGVuZENoaWxkKCByZXRbaV0gKTsNCgkJCQl9DQoJCQl9DQoJCQkNCgkJCXJldHVybiBzY3JpcHRzOw0KCQl9DQoNCgkJcmV0dXJuIHJldDsNCgl9LA0KDQoJYXR0cjogZnVuY3Rpb24oIGVsZW0sIG5hbWUsIHZhbHVlICkgew0KCQkvLy8JPHN1bW1hcnk+DQoJCS8vLwkJVGhpcyBtZXRob2QgaXMgaW50ZXJuYWwuDQoJCS8vLwk8L3N1bW1hcnk+DQoJCS8vLwk8cHJpdmF0ZSAvPg0KDQoJCS8vIGRvbid0IHNldCBhdHRyaWJ1dGVzIG9uIHRleHQgYW5kIGNvbW1lbnQgbm9kZXMNCgkJaWYgKCFlbGVtIHx8IGVsZW0ubm9kZVR5cGUgPT0gMyB8fCBlbGVtLm5vZGVUeXBlID09IDgpDQoJCQlyZXR1cm4gdW5kZWZpbmVkOw0KDQoJCXZhciBub3R4bWwgPSAhalF1ZXJ5LmlzWE1MRG9jKCBlbGVtICksDQoJCQkvLyBXaGV0aGVyIHdlIGFyZSBzZXR0aW5nIChvciBnZXR0aW5nKQ0KCQkJc2V0ID0gdmFsdWUgIT09IHVuZGVmaW5lZDsNCg0KCQkvLyBUcnkgdG8gbm9ybWFsaXplL2ZpeCB0aGUgbmFtZQ0KCQluYW1lID0gbm90eG1sICYmIGpRdWVyeS5wcm9wc1sgbmFtZSBdIHx8IG5hbWU7DQoNCgkJLy8gT25seSBkbyBhbGwgdGhlIGZvbGxvd2luZyBpZiB0aGlzIGlzIGEgbm9kZSAoZmFzdGVyIGZvciBzdHlsZSkNCgkJLy8gSUUgZWxlbS5nZXRBdHRyaWJ1dGUgcGFzc2VzIGV2ZW4gZm9yIHN0eWxlDQoJCWlmICggZWxlbS50YWdOYW1lICkgew0KDQoJCQkvLyBUaGVzZSBhdHRyaWJ1dGVzIHJlcXVpcmUgc3BlY2lhbCB0cmVhdG1lbnQNCgkJCXZhciBzcGVjaWFsID0gL2hyZWZ8c3JjfHN0eWxlLy50ZXN0KCBuYW1lICk7DQoNCgkJCS8vIFNhZmFyaSBtaXMtcmVwb3J0cyB0aGUgZGVmYXVsdCBzZWxlY3RlZCBwcm9wZXJ0eSBvZiBhIGhpZGRlbiBvcHRpb24NCgkJCS8vIEFjY2Vzc2luZyB0aGUgcGFyZW50J3Mgc2VsZWN0ZWRJbmRleCBwcm9wZXJ0eSBmaXhlcyBpdA0KCQkJaWYgKCBuYW1lID09ICJzZWxlY3RlZCIgJiYgZWxlbS5wYXJlbnROb2RlICkNCgkJCQllbGVtLnBhcmVudE5vZGUuc2VsZWN0ZWRJbmRleDsNCg0KCQkJLy8gSWYgYXBwbGljYWJsZSwgYWNjZXNzIHRoZSBhdHRyaWJ1dGUgdmlhIHRoZSBET00gMCB3YXkNCgkJCWlmICggbmFtZSBpbiBlbGVtICYmIG5vdHhtbCAmJiAhc3BlY2lhbCApIHsNCgkJCQlpZiAoIHNldCApew0KCQkJCQkvLyBXZSBjYW4ndCBhbGxvdyB0aGUgdHlwZSBwcm9wZXJ0eSB0byBiZSBjaGFuZ2VkIChzaW5jZSBpdCBjYXVzZXMgcHJvYmxlbXMgaW4gSUUpDQoJCQkJCWlmICggbmFtZSA9PSAidHlwZSIgJiYgalF1ZXJ5Lm5vZGVOYW1lKCBlbGVtLCAiaW5wdXQiICkgJiYgZWxlbS5wYXJlbnROb2RlICkNCgkJCQkJCXRocm93ICJ0eXBlIHByb3BlcnR5IGNhbid0IGJlIGNoYW5nZWQiOw0KDQoJCQkJCWVsZW1bIG5hbWUgXSA9IHZhbHVlOw0KCQkJCX0NCg0KCQkJCS8vIGJyb3dzZXJzIGluZGV4IGVsZW1lbnRzIGJ5IGlkL25hbWUgb24gZm9ybXMsIGdpdmUgcHJpb3JpdHkgdG8gYXR0cmlidXRlcy4NCgkJCQlpZiggalF1ZXJ5Lm5vZGVOYW1lKCBlbGVtLCAiZm9ybSIgKSAmJiBlbGVtLmdldEF0dHJpYnV0ZU5vZGUobmFtZSkgKQ0KCQkJCQlyZXR1cm4gZWxlbS5nZXRBdHRyaWJ1dGVOb2RlKCBuYW1lICkubm9kZVZhbHVlOw0KDQoJCQkJLy8gZWxlbS50YWJJbmRleCBkb2Vzbid0IGFsd2F5cyByZXR1cm4gdGhlIGNvcnJlY3QgdmFsdWUgd2hlbiBpdCBoYXNuJ3QgYmVlbiBleHBsaWNpdGx5IHNldA0KCQkJCS8vIGh0dHA6Ly9mbHVpZHByb2plY3Qub3JnL2Jsb2cvMjAwOC8wMS8wOS9nZXR0aW5nLXNldHRpbmctYW5kLXJlbW92aW5nLXRhYmluZGV4LXZhbHVlcy13aXRoLWphdmFzY3JpcHQvDQoJCQkJaWYgKCBuYW1lID09ICJ0YWJJbmRleCIgKSB7DQoJCQkJCXZhciBhdHRyaWJ1dGVOb2RlID0gZWxlbS5nZXRBdHRyaWJ1dGVOb2RlKCAidGFiSW5kZXgiICk7DQoJCQkJCXJldHVybiBhdHRyaWJ1dGVOb2RlICYmIGF0dHJpYnV0ZU5vZGUuc3BlY2lmaWVkDQoJCQkJCQk/IGF0dHJpYnV0ZU5vZGUudmFsdWUNCgkJCQkJCTogZWxlbS5ub2RlTmFtZS5tYXRjaCgvKGJ1dHRvbnxpbnB1dHxvYmplY3R8c2VsZWN0fHRleHRhcmVhKS9pKQ0KCQkJCQkJCT8gMA0KCQkJCQkJCTogZWxlbS5ub2RlTmFtZS5tYXRjaCgvXihhfGFyZWEpJC9pKSAmJiBlbGVtLmhyZWYNCgkJCQkJCQkJPyAwDQoJCQkJCQkJCTogdW5kZWZpbmVkOw0KCQkJCX0NCg0KCQkJCXJldHVybiBlbGVtWyBuYW1lIF07DQoJCQl9DQoNCgkJCWlmICggIWpRdWVyeS5zdXBwb3J0LnN0eWxlICYmIG5vdHhtbCAmJiAgbmFtZSA9PSAic3R5bGUiICkNCgkJCQlyZXR1cm4galF1ZXJ5LmF0dHIoIGVsZW0uc3R5bGUsICJjc3NUZXh0IiwgdmFsdWUgKTsNCg0KCQkJaWYgKCBzZXQgKQ0KCQkJCS8vIGNvbnZlcnQgdGhlIHZhbHVlIHRvIGEgc3RyaW5nIChhbGwgYnJvd3NlcnMgZG8gdGhpcyBidXQgSUUpIHNlZSAjMTA3MA0KCQkJCWVsZW0uc2V0QXR0cmlidXRlKCBuYW1lLCAiIiArIHZhbHVlICk7DQoNCgkJCXZhciBhdHRyID0gIWpRdWVyeS5zdXBwb3J0LmhyZWZOb3JtYWxpemVkICYmIG5vdHhtbCAmJiBzcGVjaWFsDQoJCQkJCS8vIFNvbWUgYXR0cmlidXRlcyByZXF1aXJlIGEgc3BlY2lhbCBjYWxsIG9uIElFDQoJCQkJCT8gZWxlbS5nZXRBdHRyaWJ1dGUoIG5hbWUsIDIgKQ0KCQkJCQk6IGVsZW0uZ2V0QXR0cmlidXRlKCBuYW1lICk7DQoNCgkJCS8vIE5vbi1leGlzdGVudCBhdHRyaWJ1dGVzIHJldHVybiBudWxsLCB3ZSBub3JtYWxpemUgdG8gdW5kZWZpbmVkDQoJCQlyZXR1cm4gYXR0ciA9PT0gbnVsbCA/IHVuZGVmaW5lZCA6IGF0dHI7DQoJCX0NCg0KCQkvLyBlbGVtIGlzIGFjdHVhbGx5IGVsZW0uc3R5bGUgLi4uIHNldCB0aGUgc3R5bGUNCg0KCQkvLyBJRSB1c2VzIGZpbHRlcnMgZm9yIG9wYWNpdHkNCgkJaWYgKCAhalF1ZXJ5LnN1cHBvcnQub3BhY2l0eSAmJiBuYW1lID09ICJvcGFjaXR5IiApIHsNCgkJCWlmICggc2V0ICkgew0KCQkJCS8vIElFIGhhcyB0cm91YmxlIHdpdGggb3BhY2l0eSBpZiBpdCBkb2VzIG5vdCBoYXZlIGxheW91dA0KCQkJCS8vIEZvcmNlIGl0IGJ5IHNldHRpbmcgdGhlIHpvb20gbGV2ZWwNCgkJCQllbGVtLnpvb20gPSAxOw0KDQoJCQkJLy8gU2V0IHRoZSBhbHBoYSBmaWx0ZXIgdG8gc2V0IHRoZSBvcGFjaXR5DQoJCQkJZWxlbS5maWx0ZXIgPSAoZWxlbS5maWx0ZXIgfHwgIiIpLnJlcGxhY2UoIC9hbHBoYVwoW14pXSpcKS8sICIiICkgKw0KCQkJCQkocGFyc2VJbnQoIHZhbHVlICkgKyAnJyA9PSAiTmFOIiA/ICIiIDogImFscGhhKG9wYWNpdHk9IiArIHZhbHVlICogMTAwICsgIikiKTsNCgkJCX0NCg0KCQkJcmV0dXJuIGVsZW0uZmlsdGVyICYmIGVsZW0uZmlsdGVyLmluZGV4T2YoIm9wYWNpdHk9IikgPj0gMCA/DQoJCQkJKHBhcnNlRmxvYXQoIGVsZW0uZmlsdGVyLm1hdGNoKC9vcGFjaXR5PShbXildKikvKVsxXSApIC8gMTAwKSArICcnOg0KCQkJCSIiOw0KCQl9DQoNCgkJbmFtZSA9IG5hbWUucmVwbGFjZSgvLShbYS16XSkvaWcsIGZ1bmN0aW9uKGFsbCwgbGV0dGVyKXsNCgkJCXJldHVybiBsZXR0ZXIudG9VcHBlckNhc2UoKTsNCgkJfSk7DQoNCgkJaWYgKCBzZXQgKQ0KCQkJZWxlbVsgbmFtZSBdID0gdmFsdWU7DQoNCgkJcmV0dXJuIGVsZW1bIG5hbWUgXTsNCgl9LA0KDQoJdHJpbTogZnVuY3Rpb24oIHRleHQgKSB7DQoJCS8vLwk8c3VtbWFyeT4NCgkJLy8vCQlSZW1vdmUgdGhlIHdoaXRlc3BhY2UgZnJvbSB0aGUgYmVnaW5uaW5nIGFuZCBlbmQgb2YgYSBzdHJpbmcuDQoJCS8vLwkJUGFydCBvZiBKYXZhU2NyaXB0DQoJCS8vLwk8L3N1bW1hcnk+DQoJCS8vLwk8cmV0dXJucyB0eXBlPSJTdHJpbmciIC8+DQoJCS8vLwk8cGFyYW0gbmFtZT0idGV4dCIgdHlwZT0iU3RyaW5nIj4NCgkJLy8vCQlUaGUgc3RyaW5nIHRvIHRyaW0uDQoJCS8vLwk8L3BhcmFtPg0KDQoJCXJldHVybiAodGV4dCB8fCAiIikucmVwbGFjZSggL15ccyt8XHMrJC9nLCAiIiApOw0KCX0sDQoNCgltYWtlQXJyYXk6IGZ1bmN0aW9uKCBhcnJheSApIHsNCgkJLy8vCTxzdW1tYXJ5Pg0KCQkvLy8JCVR1cm5zIGFueXRoaW5nIGludG8gYSB0cnVlIGFycmF5LiAgVGhpcyBpcyBhbiBpbnRlcm5hbCBtZXRob2QuDQoJCS8vLwk8L3N1bW1hcnk+DQoJCS8vLwk8cGFyYW0gbmFtZT0iYXJyYXkiIHR5cGU9Ik9iamVjdCI+QW55dGhpbmcgdG8gdHVybiBpbnRvIGFuIGFjdHVhbCBBcnJheTwvcGFyYW0+DQoJCS8vLwk8cmV0dXJucyB0eXBlPSJBcnJheSIgLz4NCgkJLy8vCTxwcml2YXRlIC8+DQoNCgkJdmFyIHJldCA9IFtdOw0KDQoJCWlmKCBhcnJheSAhPSBudWxsICl7DQoJCQl2YXIgaSA9IGFycmF5Lmxlbmd0aDsNCgkJCS8vIFRoZSB3aW5kb3csIHN0cmluZ3MgKGFuZCBmdW5jdGlvbnMpIGFsc28gaGF2ZSAnbGVuZ3RoJw0KCQkJaWYoIGkgPT0gbnVsbCB8fCB0eXBlb2YgYXJyYXkgPT09ICJzdHJpbmciIHx8IGpRdWVyeS5pc0Z1bmN0aW9uKGFycmF5KSB8fCBhcnJheS5zZXRJbnRlcnZhbCApDQoJCQkJcmV0WzBdID0gYXJyYXk7DQoJCQllbHNlDQoJCQkJd2hpbGUoIGkgKQ0KCQkJCQlyZXRbLS1pXSA9IGFycmF5W2ldOw0KCQl9DQoNCgkJcmV0dXJuIHJldDsNCgl9LA0KDQoJaW5BcnJheTogZnVuY3Rpb24oIGVsZW0sIGFycmF5ICkgew0KCQkvLy8JPHN1bW1hcnk+DQoJCS8vLwkJRGV0ZXJtaW5lcyB0aGUgaW5kZXggb2YgdGhlIGZpcnN0IHBhcmFtZXRlciBpbiB0aGUgYXJyYXkuDQoJCS8vLwk8L3N1bW1hcnk+DQoJCS8vLwk8cGFyYW0gbmFtZT0iZWxlbSI+VGhlIHZhbHVlIHRvIHNlZSBpZiBpdCBleGlzdHMgaW4gdGhlIGFycmF5LjwvcGFyYW0+DQoJCS8vLwk8cGFyYW0gbmFtZT0iYXJyYXkiIHR5cGU9IkFycmF5Ij5UaGUgYXJyYXkgdG8gbG9vayB0aHJvdWdoIGZvciB0aGUgdmFsdWU8L3BhcmFtPg0KCQkvLy8JPHJldHVybnMgdHlwZT0iTnVtYmVyIiBpbnRlZ2VyPSJ0cnVlIj5UaGUgMC1iYXNlZCBpbmRleCBvZiB0aGUgaXRlbSBpZiBpdCB3YXMgZm91bmQsIG90aGVyd2lzZSAtMS48L3JldHVybnM+DQoNCgkJZm9yICggdmFyIGkgPSAwLCBsZW5ndGggPSBhcnJheS5sZW5ndGg7IGkgPCBsZW5ndGg7IGkrKyApDQoJCS8vIFVzZSA9PT0gYmVjYXVzZSBvbiBJRSwgd2luZG93ID09IGRvY3VtZW50DQoJCQlpZiAoIGFycmF5WyBpIF0gPT09IGVsZW0gKQ0KCQkJCXJldHVybiBpOw0KDQoJCXJldHVybiAtMTsNCgl9LA0KDQoJbWVyZ2U6IGZ1bmN0aW9uKCBmaXJzdCwgc2Vjb25kICkgew0KCQkvLy8JPHN1bW1hcnk+DQoJCS8vLwkJTWVyZ2UgdHdvIGFycmF5cyB0b2dldGhlciwgcmVtb3ZpbmcgYWxsIGR1cGxpY2F0ZXMuDQoJCS8vLwkJVGhlIG5ldyBhcnJheSBpczogQWxsIHRoZSByZXN1bHRzIGZyb20gdGhlIGZpcnN0IGFycmF5LCBmb2xsb3dlZA0KCQkvLy8JCWJ5IHRoZSB1bmlxdWUgcmVzdWx0cyBmcm9tIHRoZSBzZWNvbmQgYXJyYXkuDQoJCS8vLwkJUGFydCBvZiBKYXZhU2NyaXB0DQoJCS8vLwk8L3N1bW1hcnk+DQoJCS8vLwk8cmV0dXJucyB0eXBlPSJBcnJheSIgLz4NCgkJLy8vCTxwYXJhbSBuYW1lPSJmaXJzdCIgdHlwZT0iQXJyYXkiPg0KCQkvLy8JCSBUaGUgZmlyc3QgYXJyYXkgdG8gbWVyZ2UuDQoJCS8vLwk8L3BhcmFtPg0KCQkvLy8JPHBhcmFtIG5hbWU9InNlY29uZCIgdHlwZT0iQXJyYXkiPg0KCQkvLy8JCSBUaGUgc2Vjb25kIGFycmF5IHRvIG1lcmdlLg0KCQkvLy8JPC9wYXJhbT4NCg0KCQkvLyBXZSBoYXZlIHRvIGxvb3AgdGhpcyB3YXkgYmVjYXVzZSBJRSAmIE9wZXJhIG92ZXJ3cml0ZSB0aGUgbGVuZ3RoDQoJCS8vIGV4cGFuZG8gb2YgZ2V0RWxlbWVudHNCeVRhZ05hbWUNCgkJdmFyIGkgPSAwLCBlbGVtLCBwb3MgPSBmaXJzdC5sZW5ndGg7DQoJCS8vIEFsc28sIHdlIG5lZWQgdG8gbWFrZSBzdXJlIHRoYXQgdGhlIGNvcnJlY3QgZWxlbWVudHMgYXJlIGJlaW5nIHJldHVybmVkDQoJCS8vIChJRSByZXR1cm5zIGNvbW1lbnQgbm9kZXMgaW4gYSAnKicgcXVlcnkpDQoJCWlmICggIWpRdWVyeS5zdXBwb3J0LmdldEFsbCApIHsNCgkJCXdoaWxlICggKGVsZW0gPSBzZWNvbmRbIGkrKyBdKSAhPSBudWxsICkNCgkJCQlpZiAoIGVsZW0ubm9kZVR5cGUgIT0gOCApDQoJCQkJCWZpcnN0WyBwb3MrKyBdID0gZWxlbTsNCg0KCQl9IGVsc2UNCgkJCXdoaWxlICggKGVsZW0gPSBzZWNvbmRbIGkrKyBdKSAhPSBudWxsICkNCgkJCQlmaXJzdFsgcG9zKysgXSA9IGVsZW07DQoNCgkJcmV0dXJuIGZpcnN0Ow0KCX0sDQoNCgl1bmlxdWU6IGZ1bmN0aW9uKCBhcnJheSApIHsNCgkJLy8vCTxzdW1tYXJ5Pg0KCQkvLy8JCVJlbW92ZXMgYWxsIGR1cGxpY2F0ZSBlbGVtZW50cyBmcm9tIGFuIGFycmF5IG9mIGVsZW1lbnRzLg0KCQkvLy8JPC9zdW1tYXJ5Pg0KCQkvLy8JPHBhcmFtIG5hbWU9ImFycmF5IiB0eXBlPSJBcnJheSZsdDtFbGVtZW50Jmd0OyI+VGhlIGFycmF5IHRvIHRyYW5zbGF0ZTwvcGFyYW0+DQoJCS8vLwk8cmV0dXJucyB0eXBlPSJBcnJheSZsdDtFbGVtZW50Jmd0OyI+VGhlIGFycmF5IGFmdGVyIHRyYW5zbGF0aW9uLjwvcmV0dXJucz4NCg0KCQl2YXIgcmV0ID0gW10sIGRvbmUgPSB7fTsNCg0KCQl0cnkgew0KDQoJCQlmb3IgKCB2YXIgaSA9IDAsIGxlbmd0aCA9IGFycmF5Lmxlbmd0aDsgaSA8IGxlbmd0aDsgaSsrICkgew0KCQkJCXZhciBpZCA9IGpRdWVyeS5kYXRhKCBhcnJheVsgaSBdICk7DQoNCgkJCQlpZiAoICFkb25lWyBpZCBdICkgew0KCQkJCQlkb25lWyBpZCBdID0gdHJ1ZTsNCgkJCQkJcmV0LnB1c2goIGFycmF5WyBpIF0gKTsNCgkJCQl9DQoJCQl9DQoNCgkJfSBjYXRjaCggZSApIHsNCgkJCXJldCA9IGFycmF5Ow0KCQl9DQoNCgkJcmV0dXJuIHJldDsNCgl9LA0KDQoJZ3JlcDogZnVuY3Rpb24oIGVsZW1zLCBjYWxsYmFjaywgaW52ICkgew0KCQkvLy8JPHN1bW1hcnk+DQoJCS8vLwkJRmlsdGVyIGl0ZW1zIG91dCBvZiBhbiBhcnJheSwgYnkgdXNpbmcgYSBmaWx0ZXIgZnVuY3Rpb24uDQoJCS8vLwkJVGhlIHNwZWNpZmllZCBmdW5jdGlvbiB3aWxsIGJlIHBhc3NlZCB0d28gYXJndW1lbnRzOiBUaGUNCgkJLy8vCQljdXJyZW50IGFycmF5IGl0ZW0gYW5kIHRoZSBpbmRleCBvZiB0aGUgaXRlbSBpbiB0aGUgYXJyYXkuIFRoZQ0KCQkvLy8JCWZ1bmN0aW9uIG11c3QgcmV0dXJuICd0cnVlJyB0byBrZWVwIHRoZSBpdGVtIGluIHRoZSBhcnJheSwgDQoJCS8vLwkJZmFsc2UgdG8gcmVtb3ZlIGl0Lg0KCQkvLy8JCX0pOw0KCQkvLy8JCVBhcnQgb2YgSmF2YVNjcmlwdA0KCQkvLy8JPC9zdW1tYXJ5Pg0KCQkvLy8JPHJldHVybnMgdHlwZT0iQXJyYXkiIC8+DQoJCS8vLwk8cGFyYW0gbmFtZT0iZWxlbXMiIHR5cGU9IkFycmF5Ij4NCgkJLy8vCQlhcnJheSBUaGUgQXJyYXkgdG8gZmluZCBpdGVtcyBpbi4NCgkJLy8vCTwvcGFyYW0+DQoJCS8vLwk8cGFyYW0gbmFtZT0iZm4iIHR5cGU9IkZ1bmN0aW9uIj4NCgkJLy8vCQkgVGhlIGZ1bmN0aW9uIHRvIHByb2Nlc3MgZWFjaCBpdGVtIGFnYWluc3QuDQoJCS8vLwk8L3BhcmFtPg0KCQkvLy8JPHBhcmFtIG5hbWU9ImludiIgdHlwZT0iQm9vbGVhbiI+DQoJCS8vLwkJIEludmVydCB0aGUgc2VsZWN0aW9uIC0gc2VsZWN0IHRoZSBvcHBvc2l0ZSBvZiB0aGUgZnVuY3Rpb24uDQoJCS8vLwk8L3BhcmFtPg0KCQkNCgkJdmFyIHJldCA9IFtdOw0KDQoJCS8vIEdvIHRocm91Z2ggdGhlIGFycmF5LCBvbmx5IHNhdmluZyB0aGUgaXRlbXMNCgkJLy8gdGhhdCBwYXNzIHRoZSB2YWxpZGF0b3IgZnVuY3Rpb24NCgkJZm9yICggdmFyIGkgPSAwLCBsZW5ndGggPSBlbGVtcy5sZW5ndGg7IGkgPCBsZW5ndGg7IGkrKyApDQoJCQlpZiAoICFpbnYgIT0gIWNhbGxiYWNrKCBlbGVtc1sgaSBdLCBpICkgKQ0KCQkJCXJldC5wdXNoKCBlbGVtc1sgaSBdICk7DQoNCgkJcmV0dXJuIHJldDsNCgl9LA0KDQoJbWFwOiBmdW5jdGlvbiggZWxlbXMsIGNhbGxiYWNrICkgew0KCQkvLy8JPHN1bW1hcnk+DQoJCS8vLwkJVHJhbnNsYXRlIGFsbCBpdGVtcyBpbiBhbiBhcnJheSB0byBhbm90aGVyIGFycmF5IG9mIGl0ZW1zLg0KCQkvLy8JCVRoZSB0cmFuc2xhdGlvbiBmdW5jdGlvbiB0aGF0IGlzIHByb3ZpZGVkIHRvIHRoaXMgbWV0aG9kIGlzIA0KCQkvLy8JCWNhbGxlZCBmb3IgZWFjaCBpdGVtIGluIHRoZSBhcnJheSBhbmQgaXMgcGFzc2VkIG9uZSBhcmd1bWVudDogDQoJCS8vLwkJVGhlIGl0ZW0gdG8gYmUgdHJhbnNsYXRlZC4NCgkJLy8vCQlUaGUgZnVuY3Rpb24gY2FuIHRoZW4gcmV0dXJuIHRoZSB0cmFuc2xhdGVkIHZhbHVlLCAnbnVsbCcNCgkJLy8vCQkodG8gcmVtb3ZlIHRoZSBpdGVtKSwgb3IgIGFuIGFycmF5IG9mIHZhbHVlcyAtIHdoaWNoIHdpbGwNCgkJLy8vCQliZSBmbGF0dGVuZWQgaW50byB0aGUgZnVsbCBhcnJheS4NCgkJLy8vCQlQYXJ0IG9mIEphdmFTY3JpcHQNCgkJLy8vCTwvc3VtbWFyeT4NCgkJLy8vCTxyZXR1cm5zIHR5cGU9IkFycmF5IiAvPg0KCQkvLy8JPHBhcmFtIG5hbWU9ImVsZW1zIiB0eXBlPSJBcnJheSI+DQoJCS8vLwkJYXJyYXkgVGhlIEFycmF5IHRvIHRyYW5zbGF0ZS4NCgkJLy8vCTwvcGFyYW0+DQoJCS8vLwk8cGFyYW0gbmFtZT0iZm4iIHR5cGU9IkZ1bmN0aW9uIj4NCgkJLy8vCQkgVGhlIGZ1bmN0aW9uIHRvIHByb2Nlc3MgZWFjaCBpdGVtIGFnYWluc3QuDQoJCS8vLwk8L3BhcmFtPg0KCQkNCgkJdmFyIHJldCA9IFtdOw0KDQoJCS8vIEdvIHRocm91Z2ggdGhlIGFycmF5LCB0cmFuc2xhdGluZyBlYWNoIG9mIHRoZSBpdGVtcyB0byB0aGVpcg0KCQkvLyBuZXcgdmFsdWUgKG9yIHZhbHVlcykuDQoJCWZvciAoIHZhciBpID0gMCwgbGVuZ3RoID0gZWxlbXMubGVuZ3RoOyBpIDwgbGVuZ3RoOyBpKysgKSB7DQoJCQl2YXIgdmFsdWUgPSBjYWxsYmFjayggZWxlbXNbIGkgXSwgaSApOw0KDQoJCQlpZiAoIHZhbHVlICE9IG51bGwgKQ0KCQkJCXJldFsgcmV0Lmxlbmd0aCBdID0gdmFsdWU7DQoJCX0NCg0KCQlyZXR1cm4gcmV0LmNvbmNhdC5hcHBseSggW10sIHJldCApOw0KCX0NCn0pOw0KDQovLyBVc2Ugb2YgalF1ZXJ5LmJyb3dzZXIgaXMgZGVwcmVjYXRlZC4NCi8vIEl0J3MgaW5jbHVkZWQgZm9yIGJhY2t3YXJkcyBjb21wYXRpYmlsaXR5IGFuZCBwbHVnaW5zLA0KLy8gYWx0aG91Z2ggdGhleSBzaG91bGQgd29yayB0byBtaWdyYXRlIGF3YXkuDQoNCnZhciB1c2VyQWdlbnQgPSBuYXZpZ2F0b3IudXNlckFnZW50LnRvTG93ZXJDYXNlKCk7DQoNCi8vIEZpZ3VyZSBvdXQgd2hhdCBicm93c2VyIGlzIGJlaW5nIHVzZWQNCmpRdWVyeS5icm93c2VyID0gew0KCXZlcnNpb246ICh1c2VyQWdlbnQubWF0Y2goIC8uKyg/OnJ2fGl0fHJhfGllKVtcLzogXShbXGQuXSspLyApIHx8IFswLCcwJ10pWzFdLA0KCXNhZmFyaTogL3dlYmtpdC8udGVzdCggdXNlckFnZW50ICksDQoJb3BlcmE6IC9vcGVyYS8udGVzdCggdXNlckFnZW50ICksDQoJbXNpZTogL21zaWUvLnRlc3QoIHVzZXJBZ2VudCApICYmICEvb3BlcmEvLnRlc3QoIHVzZXJBZ2VudCApLA0KCW1vemlsbGE6IC9tb3ppbGxhLy50ZXN0KCB1c2VyQWdlbnQgKSAmJiAhLyhjb21wYXRpYmxlfHdlYmtpdCkvLnRlc3QoIHVzZXJBZ2VudCApDQp9Ow0KDQovLyBbdnNkb2NdIFRoZSBmb2xsb3dpbmcgc2VjdGlvbiBoYXMgYmVlbiBkZW5vcm1hbGl6ZWQgZnJvbSBvcmlnaW5hbCBzb3VyY2VzIGZvciBJbnRlbGxpU2Vuc2UuDQovLyBqUXVlcnkuZWFjaCh7DQovLyAJcGFyZW50OiBmdW5jdGlvbihlbGVtKXtyZXR1cm4gZWxlbS5wYXJlbnROb2RlO30sDQovLyAJcGFyZW50czogZnVuY3Rpb24oZWxlbSl7cmV0dXJuIGpRdWVyeS5kaXIoZWxlbSwicGFyZW50Tm9kZSIpO30sDQovLyAJbmV4dDogZnVuY3Rpb24oZWxlbSl7cmV0dXJuIGpRdWVyeS5udGgoZWxlbSwyLCJuZXh0U2libGluZyIpO30sDQovLyAJcHJldjogZnVuY3Rpb24oZWxlbSl7cmV0dXJuIGpRdWVyeS5udGgoZWxlbSwyLCJwcmV2aW91c1NpYmxpbmciKTt9LA0KLy8gCW5leHRBbGw6IGZ1bmN0aW9uKGVsZW0pe3JldHVybiBqUXVlcnkuZGlyKGVsZW0sIm5leHRTaWJsaW5nIik7fSwNCi8vIAlwcmV2QWxsOiBmdW5jdGlvbihlbGVtKXtyZXR1cm4galF1ZXJ5LmRpcihlbGVtLCJwcmV2aW91c1NpYmxpbmciKTt9LA0KLy8gCXNpYmxpbmdzOiBmdW5jdGlvbihlbGVtKXtyZXR1cm4galF1ZXJ5LnNpYmxpbmcoZWxlbS5wYXJlbnROb2RlLmZpcnN0Q2hpbGQsZWxlbSk7fSwNCi8vIAljaGlsZHJlbjogZnVuY3Rpb24oZWxlbSl7cmV0dXJuIGpRdWVyeS5zaWJsaW5nKGVsZW0uZmlyc3RDaGlsZCk7fSwNCi8vIAljb250ZW50czogZnVuY3Rpb24oZWxlbSl7cmV0dXJuIGpRdWVyeS5ub2RlTmFtZShlbGVtLCJpZnJhbWUiKT9lbGVtLmNvbnRlbnREb2N1bWVudHx8ZWxlbS5jb250ZW50V2luZG93LmRvY3VtZW50OmpRdWVyeS5tYWtlQXJyYXkoZWxlbS5jaGlsZE5vZGVzKTt9DQovLyB9LCBmdW5jdGlvbihuYW1lLCBmbil7DQovLyAJalF1ZXJ5LmZuWyBuYW1lIF0gPSBmdW5jdGlvbiggc2VsZWN0b3IgKSB7DQovLyAJCS8vLwk8c3VtbWFyeT4NCi8vIAkJLy8vCQlHZXQgYSBzZXQgb2YgZWxlbWVudHMgY29udGFpbmluZyB0aGUgdW5pcXVlIHBhcmVudHMgb2YgdGhlIG1hdGNoZWQNCi8vIAkJLy8vCQlzZXQgb2YgZWxlbWVudHMuDQovLyAJCS8vLwkJQ2FuIGJlIGZpbHRlcmVkIHdpdGggYW4gb3B0aW9uYWwgZXhwcmVzc2lvbnMuDQovLyAJCS8vLwkJUGFydCBvZiBET00vVHJhdmVyc2luZw0KLy8gCQkvLy8JPC9zdW1tYXJ5Pg0KLy8gCQkvLy8JPHBhcmFtIG5hbWU9ImV4cHIiIHR5cGU9IlN0cmluZyIgb3B0aW9uYWw9InRydWUiPg0KLy8gCQkvLy8JCShvcHRpb25hbCkgQW4gZXhwcmVzc2lvbiB0byBmaWx0ZXIgdGhlIHBhcmVudHMgd2l0aA0KLy8gCQkvLy8JPC9wYXJhbT4NCi8vIAkJLy8vCTxyZXR1cm5zIHR5cGU9ImpRdWVyeSIgLz4gICANCi8vIAkJDQovLyAJCXZhciByZXQgPSBqUXVlcnkubWFwKCB0aGlzLCBmbiApOw0KLy8gDQovLyAJCWlmICggc2VsZWN0b3IgJiYgdHlwZW9mIHNlbGVjdG9yID09ICJzdHJpbmciICkNCi8vIAkJCXJldCA9IGpRdWVyeS5tdWx0aUZpbHRlciggc2VsZWN0b3IsIHJldCApOw0KLy8gDQovLyAJCXJldHVybiB0aGlzLnB1c2hTdGFjayggalF1ZXJ5LnVuaXF1ZSggcmV0ICksIG5hbWUsIHNlbGVjdG9yICk7DQovLyAJfTsNCi8vIH0pOw0KDQpqUXVlcnkuZWFjaCh7DQoJcGFyZW50OiBmdW5jdGlvbihlbGVtKXtyZXR1cm4gZWxlbS5wYXJlbnROb2RlO30NCn0sIGZ1bmN0aW9uKG5hbWUsIGZuKXsNCglqUXVlcnkuZm5bIG5hbWUgXSA9IGZ1bmN0aW9uKCBzZWxlY3RvciApIHsNCgkJLy8vCTxzdW1tYXJ5Pg0KCQkvLy8JCUdldCBhIHNldCBvZiBlbGVtZW50cyBjb250YWluaW5nIHRoZSB1bmlxdWUgcGFyZW50cyBvZiB0aGUgbWF0Y2hlZA0KCQkvLy8JCXNldCBvZiBlbGVtZW50cy4NCgkJLy8vCQlDYW4gYmUgZmlsdGVyZWQgd2l0aCBhbiBvcHRpb25hbCBleHByZXNzaW9ucy4NCgkJLy8vCQlQYXJ0IG9mIERPTS9UcmF2ZXJzaW5nDQoJCS8vLwk8L3N1bW1hcnk+DQoJCS8vLwk8cGFyYW0gbmFtZT0iZXhwciIgdHlwZT0iU3RyaW5nIiBvcHRpb25hbD0idHJ1ZSI+DQoJCS8vLwkJKG9wdGlvbmFsKSBBbiBleHByZXNzaW9uIHRvIGZpbHRlciB0aGUgcGFyZW50cyB3aXRoDQoJCS8vLwk8L3BhcmFtPg0KCQkvLy8JPHJldHVybnMgdHlwZT0ialF1ZXJ5IiAvPiAgIA0KCQkNCgkJdmFyIHJldCA9IGpRdWVyeS5tYXAoIHRoaXMsIGZuICk7DQoNCgkJaWYgKCBzZWxlY3RvciAmJiB0eXBlb2Ygc2VsZWN0b3IgPT0gInN0cmluZyIgKQ0KCQkJcmV0ID0galF1ZXJ5Lm11bHRpRmlsdGVyKCBzZWxlY3RvciwgcmV0ICk7DQoNCgkJcmV0dXJuIHRoaXMucHVzaFN0YWNrKCBqUXVlcnkudW5pcXVlKCByZXQgKSwgbmFtZSwgc2VsZWN0b3IgKTsNCgl9Ow0KfSk7DQoNCmpRdWVyeS5lYWNoKHsNCglwYXJlbnRzOiBmdW5jdGlvbihlbGVtKXtyZXR1cm4galF1ZXJ5LmRpcihlbGVtLCJwYXJlbnROb2RlIik7fQ0KfSwgZnVuY3Rpb24obmFtZSwgZm4pew0KCWpRdWVyeS5mblsgbmFtZSBdID0gZnVuY3Rpb24oIHNlbGVjdG9yICkgew0KCQkvLy8JPHN1bW1hcnk+DQoJCS8vLwkJR2V0IGEgc2V0IG9mIGVsZW1lbnRzIGNvbnRhaW5pbmcgdGhlIHVuaXF1ZSBhbmNlc3RvcnMgb2YgdGhlIG1hdGNoZWQNCgkJLy8vCQlzZXQgb2YgZWxlbWVudHMgKGV4Y2VwdCBmb3IgdGhlIHJvb3QgZWxlbWVudCkuDQoJCS8vLwkJQ2FuIGJlIGZpbHRlcmVkIHdpdGggYW4gb3B0aW9uYWwgZXhwcmVzc2lvbnMuDQoJCS8vLwkJUGFydCBvZiBET00vVHJhdmVyc2luZw0KCQkvLy8JPC9zdW1tYXJ5Pg0KCQkvLy8JPHBhcmFtIG5hbWU9ImV4cHIiIHR5cGU9IlN0cmluZyIgb3B0aW9uYWw9InRydWUiPg0KCQkvLy8JCShvcHRpb25hbCkgQW4gZXhwcmVzc2lvbiB0byBmaWx0ZXIgdGhlIGFuY2VzdG9ycyB3aXRoDQoJCS8vLwk8L3BhcmFtPg0KCQkvLy8JPHJldHVybnMgdHlwZT0ialF1ZXJ5IiAvPiAgIA0KCQkNCgkJdmFyIHJldCA9IGpRdWVyeS5tYXAoIHRoaXMsIGZuICk7DQoNCgkJaWYgKCBzZWxlY3RvciAmJiB0eXBlb2Ygc2VsZWN0b3IgPT0gInN0cmluZyIgKQ0KCQkJcmV0ID0galF1ZXJ5Lm11bHRpRmlsdGVyKCBzZWxlY3RvciwgcmV0ICk7DQoNCgkJcmV0dXJuIHRoaXMucHVzaFN0YWNrKCBqUXVlcnkudW5pcXVlKCByZXQgKSwgbmFtZSwgc2VsZWN0b3IgKTsNCgl9Ow0KfSk7DQoNCmpRdWVyeS5lYWNoKHsNCgluZXh0OiBmdW5jdGlvbihlbGVtKXtyZXR1cm4galF1ZXJ5Lm50aChlbGVtLDIsIm5leHRTaWJsaW5nIik7fQ0KfSwgZnVuY3Rpb24obmFtZSwgZm4pew0KCWpRdWVyeS5mblsgbmFtZSBdID0gZnVuY3Rpb24oIHNlbGVjdG9yICkgew0KCQkvLy8JPHN1bW1hcnk+DQoJCS8vLwkJR2V0IGEgc2V0IG9mIGVsZW1lbnRzIGNvbnRhaW5pbmcgdGhlIHVuaXF1ZSBuZXh0IHNpYmxpbmdzIG9mIGVhY2ggb2YgdGhlDQoJCS8vLwkJbWF0Y2hlZCBzZXQgb2YgZWxlbWVudHMuDQoJCS8vLwkJSXQgb25seSByZXR1cm5zIHRoZSB2ZXJ5IG5leHQgc2libGluZywgbm90IGFsbCBuZXh0IHNpYmxpbmdzLg0KCQkvLy8JCUNhbiBiZSBmaWx0ZXJlZCB3aXRoIGFuIG9wdGlvbmFsIGV4cHJlc3Npb25zLg0KCQkvLy8JCVBhcnQgb2YgRE9NL1RyYXZlcnNpbmcNCgkJLy8vCTwvc3VtbWFyeT4NCgkJLy8vCTxwYXJhbSBuYW1lPSJleHByIiB0eXBlPSJTdHJpbmciIG9wdGlvbmFsPSJ0cnVlIj4NCgkJLy8vCQkob3B0aW9uYWwpIEFuIGV4cHJlc3Npb24gdG8gZmlsdGVyIHRoZSBuZXh0IEVsZW1lbnRzIHdpdGgNCgkJLy8vCTwvcGFyYW0+DQoJCS8vLwk8cmV0dXJucyB0eXBlPSJqUXVlcnkiIC8+DQoJCQ0KCQl2YXIgcmV0ID0galF1ZXJ5Lm1hcCggdGhpcywgZm4gKTsNCg0KCQlpZiAoIHNlbGVjdG9yICYmIHR5cGVvZiBzZWxlY3RvciA9PSAic3RyaW5nIiApDQoJCQlyZXQgPSBqUXVlcnkubXVsdGlGaWx0ZXIoIHNlbGVjdG9yLCByZXQgKTsNCg0KCQlyZXR1cm4gdGhpcy5wdXNoU3RhY2soIGpRdWVyeS51bmlxdWUoIHJldCApLCBuYW1lLCBzZWxlY3RvciApOw0KCX07DQp9KTsNCg0KalF1ZXJ5LmVhY2goew0KCXByZXY6IGZ1bmN0aW9uKGVsZW0pe3JldHVybiBqUXVlcnkubnRoKGVsZW0sMiwicHJldmlvdXNTaWJsaW5nIik7fQ0KfSwgZnVuY3Rpb24obmFtZSwgZm4pew0KCWpRdWVyeS5mblsgbmFtZSBdID0gZnVuY3Rpb24oIHNlbGVjdG9yICkgew0KCQkvLy8JPHN1bW1hcnk+DQoJCS8vLwkJR2V0IGEgc2V0IG9mIGVsZW1lbnRzIGNvbnRhaW5pbmcgdGhlIHVuaXF1ZSBwcmV2aW91cyBzaWJsaW5ncyBvZiBlYWNoIG9mIHRoZQ0KCQkvLy8JCW1hdGNoZWQgc2V0IG9mIGVsZW1lbnRzLg0KCQkvLy8JCUNhbiBiZSBmaWx0ZXJlZCB3aXRoIGFuIG9wdGlvbmFsIGV4cHJlc3Npb25zLg0KCQkvLy8JCUl0IG9ubHkgcmV0dXJucyB0aGUgaW1tZWRpYXRlbHkgcHJldmlvdXMgc2libGluZywgbm90IGFsbCBwcmV2aW91cyBzaWJsaW5ncy4NCgkJLy8vCQlQYXJ0IG9mIERPTS9UcmF2ZXJzaW5nDQoJCS8vLwk8L3N1bW1hcnk+DQoJCS8vLwk8cGFyYW0gbmFtZT0iZXhwciIgdHlwZT0iU3RyaW5nIiBvcHRpb25hbD0idHJ1ZSI+DQoJCS8vLwkJKG9wdGlvbmFsKSBBbiBleHByZXNzaW9uIHRvIGZpbHRlciB0aGUgcHJldmlvdXMgRWxlbWVudHMgd2l0aA0KCQkvLy8JPC9wYXJhbT4NCgkJLy8vCTxyZXR1cm5zIHR5cGU9ImpRdWVyeSIgLz4NCgkJDQoJCXZhciByZXQgPSBqUXVlcnkubWFwKCB0aGlzLCBmbiApOw0KDQoJCWlmICggc2VsZWN0b3IgJiYgdHlwZW9mIHNlbGVjdG9yID09ICJzdHJpbmciICkNCgkJCXJldCA9IGpRdWVyeS5tdWx0aUZpbHRlciggc2VsZWN0b3IsIHJldCApOw0KDQoJCXJldHVybiB0aGlzLnB1c2hTdGFjayggalF1ZXJ5LnVuaXF1ZSggcmV0ICksIG5hbWUsIHNlbGVjdG9yICk7DQoJfTsNCn0pOw0KDQpqUXVlcnkuZWFjaCh7DQoJbmV4dEFsbDogZnVuY3Rpb24oZWxlbSl7cmV0dXJuIGpRdWVyeS5kaXIoZWxlbSwibmV4dFNpYmxpbmciKTt9DQp9LCBmdW5jdGlvbihuYW1lLCBmbil7DQoJalF1ZXJ5LmZuW25hbWVdID0gZnVuY3Rpb24oc2VsZWN0b3IpIHsNCgkJLy8vCTxzdW1tYXJ5Pg0KCQkvLy8JCUZpbmRzIGFsbCBzaWJsaW5nIGVsZW1lbnRzIGFmdGVyIHRoZSBjdXJyZW50IGVsZW1lbnQuDQoJCS8vLwkJQ2FuIGJlIGZpbHRlcmVkIHdpdGggYW4gb3B0aW9uYWwgZXhwcmVzc2lvbnMuDQoJCS8vLwkJUGFydCBvZiBET00vVHJhdmVyc2luZw0KCQkvLy8JPC9zdW1tYXJ5Pg0KCQkvLy8JPHBhcmFtIG5hbWU9ImV4cHIiIHR5cGU9IlN0cmluZyIgb3B0aW9uYWw9InRydWUiPg0KCQkvLy8JCShvcHRpb25hbCkgQW4gZXhwcmVzc2lvbiB0byBmaWx0ZXIgdGhlIG5leHQgRWxlbWVudHMgd2l0aA0KCQkvLy8JPC9wYXJhbT4NCgkJLy8vCTxyZXR1cm5zIHR5cGU9ImpRdWVyeSIgLz4NCgkJDQoJCXZhciByZXQgPSBqUXVlcnkubWFwKCB0aGlzLCBmbiApOw0KDQoJCWlmICggc2VsZWN0b3IgJiYgdHlwZW9mIHNlbGVjdG9yID09ICJzdHJpbmciICkNCgkJCXJldCA9IGpRdWVyeS5tdWx0aUZpbHRlciggc2VsZWN0b3IsIHJldCApOw0KDQoJCXJldHVybiB0aGlzLnB1c2hTdGFjayggalF1ZXJ5LnVuaXF1ZSggcmV0ICksIG5hbWUsIHNlbGVjdG9yICk7DQoJfTsNCn0pOw0KDQpqUXVlcnkuZWFjaCh7DQoJcHJldkFsbDogZnVuY3Rpb24oZWxlbSl7cmV0dXJuIGpRdWVyeS5kaXIoZWxlbSwicHJldmlvdXNTaWJsaW5nIik7fQ0KfSwgZnVuY3Rpb24obmFtZSwgZm4pew0KCWpRdWVyeS5mblsgbmFtZSBdID0gZnVuY3Rpb24oIHNlbGVjdG9yICkgew0KCQkvLy8JPHN1bW1hcnk+DQoJCS8vLwkJRmluZHMgYWxsIHNpYmxpbmcgZWxlbWVudHMgYmVmb3JlIHRoZSBjdXJyZW50IGVsZW1lbnQuDQoJCS8vLwkJQ2FuIGJlIGZpbHRlcmVkIHdpdGggYW4gb3B0aW9uYWwgZXhwcmVzc2lvbnMuDQoJCS8vLwkJUGFydCBvZiBET00vVHJhdmVyc2luZw0KCQkvLy8JPC9zdW1tYXJ5Pg0KCQkvLy8JPHBhcmFtIG5hbWU9ImV4cHIiIHR5cGU9IlN0cmluZyIgb3B0aW9uYWw9InRydWUiPg0KCQkvLy8JCShvcHRpb25hbCkgQW4gZXhwcmVzc2lvbiB0byBmaWx0ZXIgdGhlIHByZXZpb3VzIEVsZW1lbnRzIHdpdGgNCgkJLy8vCTwvcGFyYW0+DQoJCS8vLwk8cmV0dXJucyB0eXBlPSJqUXVlcnkiIC8+DQoJDQoJCXZhciByZXQgPSBqUXVlcnkubWFwKCB0aGlzLCBmbiApOw0KDQoJCWlmICggc2VsZWN0b3IgJiYgdHlwZW9mIHNlbGVjdG9yID09ICJzdHJpbmciICkNCgkJCXJldCA9IGpRdWVyeS5tdWx0aUZpbHRlciggc2VsZWN0b3IsIHJldCApOw0KDQoJCXJldHVybiB0aGlzLnB1c2hTdGFjayggalF1ZXJ5LnVuaXF1ZSggcmV0ICksIG5hbWUsIHNlbGVjdG9yICk7DQoJfTsNCn0pOw0KDQpqUXVlcnkuZWFjaCh7DQoJc2libGluZ3M6IGZ1bmN0aW9uKGVsZW0pe3JldHVybiBqUXVlcnkuc2libGluZyhlbGVtLnBhcmVudE5vZGUuZmlyc3RDaGlsZCxlbGVtKTt9DQp9LCBmdW5jdGlvbihuYW1lLCBmbil7DQoJalF1ZXJ5LmZuWyBuYW1lIF0gPSBmdW5jdGlvbiggc2VsZWN0b3IgKSB7DQoJCS8vLwk8c3VtbWFyeT4NCgkJLy8vCQlHZXQgYSBzZXQgb2YgZWxlbWVudHMgY29udGFpbmluZyBhbGwgb2YgdGhlIHVuaXF1ZSBzaWJsaW5ncyBvZiBlYWNoIG9mIHRoZQ0KCQkvLy8JCW1hdGNoZWQgc2V0IG9mIGVsZW1lbnRzLg0KCQkvLy8JCUNhbiBiZSBmaWx0ZXJlZCB3aXRoIGFuIG9wdGlvbmFsIGV4cHJlc3Npb25zLg0KCQkvLy8JCVBhcnQgb2YgRE9NL1RyYXZlcnNpbmcNCgkJLy8vCTwvc3VtbWFyeT4NCgkJLy8vCTxwYXJhbSBuYW1lPSJleHByIiB0eXBlPSJTdHJpbmciIG9wdGlvbmFsPSJ0cnVlIj4NCgkJLy8vCQkob3B0aW9uYWwpIEFuIGV4cHJlc3Npb24gdG8gZmlsdGVyIHRoZSBzaWJsaW5nIEVsZW1lbnRzIHdpdGgNCgkJLy8vCTwvcGFyYW0+DQoJCS8vLwk8cmV0dXJucyB0eXBlPSJqUXVlcnkiIC8+DQoJCQ0KCQl2YXIgcmV0ID0galF1ZXJ5Lm1hcCggdGhpcywgZm4gKTsNCg0KCQlpZiAoIHNlbGVjdG9yICYmIHR5cGVvZiBzZWxlY3RvciA9PSAic3RyaW5nIiApDQoJCQlyZXQgPSBqUXVlcnkubXVsdGlGaWx0ZXIoIHNlbGVjdG9yLCByZXQgKTsNCg0KCQlyZXR1cm4gdGhpcy5wdXNoU3RhY2soIGpRdWVyeS51bmlxdWUoIHJldCApLCBuYW1lLCBzZWxlY3RvciApOw0KCX07DQp9KTsNCg0KalF1ZXJ5LmVhY2goew0KCWNoaWxkcmVuOiBmdW5jdGlvbihlbGVtKXtyZXR1cm4galF1ZXJ5LnNpYmxpbmcoZWxlbS5maXJzdENoaWxkKTt9DQp9LCBmdW5jdGlvbihuYW1lLCBmbil7DQoJalF1ZXJ5LmZuWyBuYW1lIF0gPSBmdW5jdGlvbiggc2VsZWN0b3IgKSB7DQoJCS8vLwk8c3VtbWFyeT4NCgkJLy8vCQlHZXQgYSBzZXQgb2YgZWxlbWVudHMgY29udGFpbmluZyBhbGwgb2YgdGhlIHVuaXF1ZSBjaGlsZHJlbiBvZiBlYWNoIG9mIHRoZQ0KCQkvLy8JCW1hdGNoZWQgc2V0IG9mIGVsZW1lbnRzLg0KCQkvLy8JCUNhbiBiZSBmaWx0ZXJlZCB3aXRoIGFuIG9wdGlvbmFsIGV4cHJlc3Npb25zLg0KCQkvLy8JCVBhcnQgb2YgRE9NL1RyYXZlcnNpbmcNCgkJLy8vCTwvc3VtbWFyeT4NCgkJLy8vCTxwYXJhbSBuYW1lPSJleHByIiB0eXBlPSJTdHJpbmciIG9wdGlvbmFsPSJ0cnVlIj4NCgkJLy8vCQkob3B0aW9uYWwpIEFuIGV4cHJlc3Npb24gdG8gZmlsdGVyIHRoZSBjaGlsZCBFbGVtZW50cyB3aXRoDQoJCS8vLwk8L3BhcmFtPg0KCQkvLy8JPHJldHVybnMgdHlwZT0ialF1ZXJ5IiAvPg0KCQkNCgkJdmFyIHJldCA9IGpRdWVyeS5tYXAoIHRoaXMsIGZuICk7DQoNCgkJaWYgKCBzZWxlY3RvciAmJiB0eXBlb2Ygc2VsZWN0b3IgPT0gInN0cmluZyIgKQ0KCQkJcmV0ID0galF1ZXJ5Lm11bHRpRmlsdGVyKCBzZWxlY3RvciwgcmV0ICk7DQoNCgkJcmV0dXJuIHRoaXMucHVzaFN0YWNrKCBqUXVlcnkudW5pcXVlKCByZXQgKSwgbmFtZSwgc2VsZWN0b3IgKTsNCgl9Ow0KfSk7DQoNCmpRdWVyeS5lYWNoKHsNCgljb250ZW50czogZnVuY3Rpb24oZWxlbSl7cmV0dXJuIGpRdWVyeS5ub2RlTmFtZShlbGVtLCJpZnJhbWUiKT9lbGVtLmNvbnRlbnREb2N1bWVudHx8ZWxlbS5jb250ZW50V2luZG93LmRvY3VtZW50OmpRdWVyeS5tYWtlQXJyYXkoZWxlbS5jaGlsZE5vZGVzKTt9DQp9LCBmdW5jdGlvbihuYW1lLCBmbil7DQoJalF1ZXJ5LmZuWyBuYW1lIF0gPSBmdW5jdGlvbiggc2VsZWN0b3IgKSB7DQoJCS8vLwk8c3VtbWFyeT5GaW5kcyBhbGwgdGhlIGNoaWxkIG5vZGVzIGluc2lkZSB0aGUgbWF0Y2hlZCBlbGVtZW50cyBpbmNsdWRpbmcgdGV4dCBub2Rlcywgb3IgdGhlIGNvbnRlbnQgZG9jdW1lbnQgaWYgdGhlIGVsZW1lbnQgaXMgYW4gaWZyYW1lLjwvc3VtbWFyeT4NCgkJLy8vCTxyZXR1cm5zIHR5cGU9ImpRdWVyeSIgLz4NCgkJDQoJCXZhciByZXQgPSBqUXVlcnkubWFwKCB0aGlzLCBmbiApOw0KDQoJCWlmICggc2VsZWN0b3IgJiYgdHlwZW9mIHNlbGVjdG9yID09ICJzdHJpbmciICkNCgkJCXJldCA9IGpRdWVyeS5tdWx0aUZpbHRlciggc2VsZWN0b3IsIHJldCApOw0KDQoJCXJldHVybiB0aGlzLnB1c2hTdGFjayggalF1ZXJ5LnVuaXF1ZSggcmV0ICksIG5hbWUsIHNlbGVjdG9yICk7DQoJfTsNCn0pOw0KDQovLyBbdnNkb2NdIFRoZSBmb2xsb3dpbmcgc2VjdGlvbiBoYXMgYmVlbiBkZW5vcm1hbGl6ZWQgZnJvbSBvcmlnaW5hbCBzb3VyY2VzIGZvciBJbnRlbGxpU2Vuc2UuDQovLyBqUXVlcnkuZWFjaCh7DQovLyAJYXBwZW5kVG86ICJhcHBlbmQiLA0KLy8gCXByZXBlbmRUbzogInByZXBlbmQiLA0KLy8gCWluc2VydEJlZm9yZTogImJlZm9yZSIsDQovLyAJaW5zZXJ0QWZ0ZXI6ICJhZnRlciIsDQovLyAJcmVwbGFjZUFsbDogInJlcGxhY2VXaXRoIg0KLy8gfSwgZnVuY3Rpb24obmFtZSwgb3JpZ2luYWwpew0KLy8gCWpRdWVyeS5mblsgbmFtZSBdID0gZnVuY3Rpb24oKSB7DQovLyAJCXZhciBhcmdzID0gYXJndW1lbnRzOw0KLy8gDQovLyAJCXJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24oKXsNCi8vIAkJCWZvciAoIHZhciBpID0gMCwgbGVuZ3RoID0gYXJncy5sZW5ndGg7IGkgPCBsZW5ndGg7IGkrKyApDQovLyAJCQkJalF1ZXJ5KCBhcmdzWyBpIF0gKVsgb3JpZ2luYWwgXSggdGhpcyApOw0KLy8gCQl9KTsNCi8vIAl9Ow0KLy8gfSk7DQoNCmpRdWVyeS5mbi5hcHBlbmRUbyA9IGZ1bmN0aW9uKCBzZWxlY3RvciApIHsNCgkvLy8JPHN1bW1hcnk+DQoJLy8vCQlBcHBlbmQgYWxsIG9mIHRoZSBtYXRjaGVkIGVsZW1lbnRzIHRvIGFub3RoZXIsIHNwZWNpZmllZCwgc2V0IG9mIGVsZW1lbnRzLg0KCS8vLwkJQXMgb2YgalF1ZXJ5IDEuMy4yLCByZXR1cm5zIGFsbCBvZiB0aGUgaW5zZXJ0ZWQgZWxlbWVudHMuDQoJLy8vCQlUaGlzIG9wZXJhdGlvbiBpcywgZXNzZW50aWFsbHksIHRoZSByZXZlcnNlIG9mIGRvaW5nIGEgcmVndWxhcg0KCS8vLwkJJChBKS5hcHBlbmQoQiksIGluIHRoYXQgaW5zdGVhZCBvZiBhcHBlbmRpbmcgQiB0byBBLCB5b3UncmUgYXBwZW5kaW5nDQoJLy8vCQlBIHRvIEIuDQoJLy8vCTwvc3VtbWFyeT4NCgkvLy8JPHBhcmFtIG5hbWU9InNlbGVjdG9yIiB0eXBlPSJTZWxlY3RvciI+DQoJLy8vCQkgdGFyZ2V0IHRvIHdoaWNoIHRoZSBjb250ZW50IHdpbGwgYmUgYXBwZW5kZWQuDQoJLy8vCTwvcGFyYW0+DQoJLy8vCTxyZXR1cm5zIHR5cGU9ImpRdWVyeSIgLz4NCgl2YXIgcmV0ID0gW10sIGluc2VydCA9IGpRdWVyeSggc2VsZWN0b3IgKTsNCg0KCWZvciAoIHZhciBpID0gMCwgbCA9IGluc2VydC5sZW5ndGg7IGkgPCBsOyBpKysgKSB7DQoJCXZhciBlbGVtcyA9IChpID4gMCA/IHRoaXMuY2xvbmUodHJ1ZSkgOiB0aGlzKS5nZXQoKTsNCgkJalF1ZXJ5LmZuWyAiYXBwZW5kIiBdLmFwcGx5KCBqUXVlcnkoaW5zZXJ0W2ldKSwgZWxlbXMgKTsNCgkJcmV0ID0gcmV0LmNvbmNhdCggZWxlbXMgKTsNCgl9DQoNCglyZXR1cm4gdGhpcy5wdXNoU3RhY2soIHJldCwgImFwcGVuZFRvIiwgc2VsZWN0b3IgKTsNCn07DQoNCmpRdWVyeS5mbi5wcmVwZW5kVG8gPSBmdW5jdGlvbiggc2VsZWN0b3IgKSB7DQoJLy8vCTxzdW1tYXJ5Pg0KCS8vLwkJUHJlcGVuZCBhbGwgb2YgdGhlIG1hdGNoZWQgZWxlbWVudHMgdG8gYW5vdGhlciwgc3BlY2lmaWVkLCBzZXQgb2YgZWxlbWVudHMuDQoJLy8vCQlBcyBvZiBqUXVlcnkgMS4zLjIsIHJldHVybnMgYWxsIG9mIHRoZSBpbnNlcnRlZCBlbGVtZW50cy4NCgkvLy8JCVRoaXMgb3BlcmF0aW9uIGlzLCBlc3NlbnRpYWxseSwgdGhlIHJldmVyc2Ugb2YgZG9pbmcgYSByZWd1bGFyDQoJLy8vCQkkKEEpLnByZXBlbmQoQiksIGluIHRoYXQgaW5zdGVhZCBvZiBwcmVwZW5kaW5nIEIgdG8gQSwgeW91J3JlIHByZXBlbmRpbmcNCgkvLy8JCUEgdG8gQi4NCgkvLy8JPC9zdW1tYXJ5Pg0KCS8vLwk8cGFyYW0gbmFtZT0ic2VsZWN0b3IiIHR5cGU9IlNlbGVjdG9yIj4NCgkvLy8JCSB0YXJnZXQgdG8gd2hpY2ggdGhlIGNvbnRlbnQgd2lsbCBiZSBhcHBlbmRlZC4NCgkvLy8JPC9wYXJhbT4NCgkvLy8JPHJldHVybnMgdHlwZT0ialF1ZXJ5IiAvPg0KCXZhciByZXQgPSBbXSwgaW5zZXJ0ID0galF1ZXJ5KCBzZWxlY3RvciApOw0KDQoJZm9yICggdmFyIGkgPSAwLCBsID0gaW5zZXJ0Lmxlbmd0aDsgaSA8IGw7IGkrKyApIHsNCgkJdmFyIGVsZW1zID0gKGkgPiAwID8gdGhpcy5jbG9uZSh0cnVlKSA6IHRoaXMpLmdldCgpOw0KCQlqUXVlcnkuZm5bICJwcmVwZW5kIiBdLmFwcGx5KCBqUXVlcnkoaW5zZXJ0W2ldKSwgZWxlbXMgKTsNCgkJcmV0ID0gcmV0LmNvbmNhdCggZWxlbXMgKTsNCgl9DQoNCglyZXR1cm4gdGhpcy5wdXNoU3RhY2soIHJldCwgInByZXBlbmRUbyIsIHNlbGVjdG9yICk7DQp9Ow0KDQpqUXVlcnkuZm4uaW5zZXJ0QmVmb3JlID0gZnVuY3Rpb24oIHNlbGVjdG9yICkgew0KCS8vLwk8c3VtbWFyeT4NCgkvLy8JCUluc2VydCBhbGwgb2YgdGhlIG1hdGNoZWQgZWxlbWVudHMgYmVmb3JlIGFub3RoZXIsIHNwZWNpZmllZCwgc2V0IG9mIGVsZW1lbnRzLg0KCS8vLwkJQXMgb2YgalF1ZXJ5IDEuMy4yLCByZXR1cm5zIGFsbCBvZiB0aGUgaW5zZXJ0ZWQgZWxlbWVudHMuDQoJLy8vCQlUaGlzIG9wZXJhdGlvbiBpcywgZXNzZW50aWFsbHksIHRoZSByZXZlcnNlIG9mIGRvaW5nIGEgcmVndWxhcg0KCS8vLwkJJChBKS5iZWZvcmUoQiksIGluIHRoYXQgaW5zdGVhZCBvZiBpbnNlcnRpbmcgQiBiZWZvcmUgQSwgeW91J3JlIGluc2VydGluZw0KCS8vLwkJQSBiZWZvcmUgQi4NCgkvLy8JPC9zdW1tYXJ5Pg0KCS8vLwk8cGFyYW0gbmFtZT0iY29udGVudCIgdHlwZT0iU3RyaW5nIj4NCgkvLy8JCSBDb250ZW50IGFmdGVyIHdoaWNoIHRoZSBzZWxlY3RlZCBlbGVtZW50KHMpIGlzIGluc2VydGVkLg0KCS8vLwk8L3BhcmFtPg0KCS8vLwk8cmV0dXJucyB0eXBlPSJqUXVlcnkiIC8+DQoJdmFyIHJldCA9IFtdLCBpbnNlcnQgPSBqUXVlcnkoIHNlbGVjdG9yICk7DQoNCglmb3IgKCB2YXIgaSA9IDAsIGwgPSBpbnNlcnQubGVuZ3RoOyBpIDwgbDsgaSsrICkgew0KCQl2YXIgZWxlbXMgPSAoaSA+IDAgPyB0aGlzLmNsb25lKHRydWUpIDogdGhpcykuZ2V0KCk7DQoJCWpRdWVyeS5mblsgImJlZm9yZSIgXS5hcHBseSggalF1ZXJ5KGluc2VydFtpXSksIGVsZW1zICk7DQoJCXJldCA9IHJldC5jb25jYXQoIGVsZW1zICk7DQoJfQ0KDQoJcmV0dXJuIHRoaXMucHVzaFN0YWNrKCByZXQsICJpbnNlcnRCZWZvcmUiLCBzZWxlY3RvciApOw0KfTsNCg0KalF1ZXJ5LmZuLmluc2VydEFmdGVyID0gZnVuY3Rpb24oIHNlbGVjdG9yICkgew0KCS8vLwk8c3VtbWFyeT4NCgkvLy8JCUluc2VydCBhbGwgb2YgdGhlIG1hdGNoZWQgZWxlbWVudHMgYWZ0ZXIgYW5vdGhlciwgc3BlY2lmaWVkLCBzZXQgb2YgZWxlbWVudHMuDQoJLy8vCQlBcyBvZiBqUXVlcnkgMS4zLjIsIHJldHVybnMgYWxsIG9mIHRoZSBpbnNlcnRlZCBlbGVtZW50cy4NCgkvLy8JCVRoaXMgb3BlcmF0aW9uIGlzLCBlc3NlbnRpYWxseSwgdGhlIHJldmVyc2Ugb2YgZG9pbmcgYSByZWd1bGFyDQoJLy8vCQkkKEEpLmFmdGVyKEIpLCBpbiB0aGF0IGluc3RlYWQgb2YgaW5zZXJ0aW5nIEIgYWZ0ZXIgQSwgeW91J3JlIGluc2VydGluZw0KCS8vLwkJQSBhZnRlciBCLg0KCS8vLwk8L3N1bW1hcnk+DQoJLy8vCTxwYXJhbSBuYW1lPSJjb250ZW50IiB0eXBlPSJTdHJpbmciPg0KCS8vLwkJIENvbnRlbnQgYWZ0ZXIgd2hpY2ggdGhlIHNlbGVjdGVkIGVsZW1lbnQocykgaXMgaW5zZXJ0ZWQuDQoJLy8vCTwvcGFyYW0+DQoJLy8vCTxyZXR1cm5zIHR5cGU9ImpRdWVyeSIgLz4NCgl2YXIgcmV0ID0gW10sIGluc2VydCA9IGpRdWVyeSggc2VsZWN0b3IgKTsNCg0KCWZvciAoIHZhciBpID0gMCwgbCA9IGluc2VydC5sZW5ndGg7IGkgPCBsOyBpKysgKSB7DQoJCXZhciBlbGVtcyA9IChpID4gMCA/IHRoaXMuY2xvbmUodHJ1ZSkgOiB0aGlzKS5nZXQoKTsNCgkJalF1ZXJ5LmZuWyAiYWZ0ZXIiIF0uYXBwbHkoIGpRdWVyeShpbnNlcnRbaV0pLCBlbGVtcyApOw0KCQlyZXQgPSByZXQuY29uY2F0KCBlbGVtcyApOw0KCX0NCg0KCXJldHVybiB0aGlzLnB1c2hTdGFjayggcmV0LCAiaW5zZXJ0QWZ0ZXIiLCBzZWxlY3RvciApOw0KfTsNCg0KalF1ZXJ5LmZuLnJlcGxhY2VBbGwgPSBmdW5jdGlvbiggc2VsZWN0b3IgKSB7DQoJLy8vCTxzdW1tYXJ5Pg0KCS8vLwkJUmVwbGFjZXMgdGhlIGVsZW1lbnRzIG1hdGNoZWQgYnkgdGhlIHNwZWNpZmllZCBzZWxlY3RvciB3aXRoIHRoZSBtYXRjaGVkIGVsZW1lbnRzLg0KCS8vLwkJQXMgb2YgalF1ZXJ5IDEuMy4yLCByZXR1cm5zIGFsbCBvZiB0aGUgaW5zZXJ0ZWQgZWxlbWVudHMuDQoJLy8vCTwvc3VtbWFyeT4NCgkvLy8JPHBhcmFtIG5hbWU9InNlbGVjdG9yIiB0eXBlPSJTZWxlY3RvciI+VGhlIGVsZW1lbnRzIHRvIGZpbmQgYW5kIHJlcGxhY2UgdGhlIG1hdGNoZWQgZWxlbWVudHMgd2l0aC48L3BhcmFtPg0KCS8vLwk8cmV0dXJucyB0eXBlPSJqUXVlcnkiIC8+DQoJdmFyIHJldCA9IFtdLCBpbnNlcnQgPSBqUXVlcnkoIHNlbGVjdG9yICk7DQoNCglmb3IgKCB2YXIgaSA9IDAsIGwgPSBpbnNlcnQubGVuZ3RoOyBpIDwgbDsgaSsrICkgew0KCQl2YXIgZWxlbXMgPSAoaSA+IDAgPyB0aGlzLmNsb25lKHRydWUpIDogdGhpcykuZ2V0KCk7DQoJCWpRdWVyeS5mblsgInJlcGxhY2VXaXRoIiBdLmFwcGx5KCBqUXVlcnkoaW5zZXJ0W2ldKSwgZWxlbXMgKTsNCgkJcmV0ID0gcmV0LmNvbmNhdCggZWxlbXMgKTsNCgl9DQoNCglyZXR1cm4gdGhpcy5wdXNoU3RhY2soIHJldCwgInJlcGxhY2VBbGwiLCBzZWxlY3RvciApOw0KfTsNCg0KLy8gW3ZzZG9jXSBUaGUgZm9sbG93aW5nIHNlY3Rpb24gaGFzIGJlZW4gZGVub3JtYWxpemVkIGZyb20gb3JpZ2luYWwgc291cmNlcyBmb3IgSW50ZWxsaVNlbnNlLg0KLy8galF1ZXJ5LmVhY2goew0KLy8gCXJlbW92ZUF0dHI6IGZ1bmN0aW9uKCBuYW1lICkgew0KLy8gCQlqUXVlcnkuYXR0ciggdGhpcywgbmFtZSwgIiIgKTsNCi8vIAkJaWYgKHRoaXMubm9kZVR5cGUgPT0gMSkNCi8vIAkJCXRoaXMucmVtb3ZlQXR0cmlidXRlKCBuYW1lICk7DQovLyAJfSwNCi8vIA0KLy8gCWFkZENsYXNzOiBmdW5jdGlvbiggY2xhc3NOYW1lcyApIHsNCi8vIAkJalF1ZXJ5LmNsYXNzTmFtZS5hZGQoIHRoaXMsIGNsYXNzTmFtZXMgKTsNCi8vIAl9LA0KLy8gDQovLyAJcmVtb3ZlQ2xhc3M6IGZ1bmN0aW9uKCBjbGFzc05hbWVzICkgew0KLy8gCQlqUXVlcnkuY2xhc3NOYW1lLnJlbW92ZSggdGhpcywgY2xhc3NOYW1lcyApOw0KLy8gCX0sDQovLyANCi8vIAl0b2dnbGVDbGFzczogZnVuY3Rpb24oIGNsYXNzTmFtZXMsIHN0YXRlICkgew0KLy8gCQlpZiggdHlwZW9mIHN0YXRlICE9PSAiYm9vbGVhbiIgKQ0KLy8gCQkJc3RhdGUgPSAhalF1ZXJ5LmNsYXNzTmFtZS5oYXMoIHRoaXMsIGNsYXNzTmFtZXMgKTsNCi8vIAkJalF1ZXJ5LmNsYXNzTmFtZVsgc3RhdGUgPyAiYWRkIiA6ICJyZW1vdmUiIF0oIHRoaXMsIGNsYXNzTmFtZXMgKTsNCi8vIAl9LA0KLy8gDQovLyAJcmVtb3ZlOiBmdW5jdGlvbiggc2VsZWN0b3IgKSB7DQovLyAJCWlmICggIXNlbGVjdG9yIHx8IGpRdWVyeS5maWx0ZXIoIHNlbGVjdG9yLCBbIHRoaXMgXSApLmxlbmd0aCApIHsNCi8vIAkJCS8vIFByZXZlbnQgbWVtb3J5IGxlYWtzDQovLyAJCQlqUXVlcnkoICIqIiwgdGhpcyApLmFkZChbdGhpc10pLmVhY2goZnVuY3Rpb24oKXsNCi8vIAkJCQlqUXVlcnkuZXZlbnQucmVtb3ZlKHRoaXMpOw0KLy8gCQkJCWpRdWVyeS5yZW1vdmVEYXRhKHRoaXMpOw0KLy8gCQkJfSk7DQovLyAJCQlpZiAodGhpcy5wYXJlbnROb2RlKQ0KLy8gCQkJCXRoaXMucGFyZW50Tm9kZS5yZW1vdmVDaGlsZCggdGhpcyApOw0KLy8gCQl9DQovLyAJfSwNCi8vIA0KLy8gCWVtcHR5OiBmdW5jdGlvbigpIHsNCi8vIAkJLy8gUmVtb3ZlIGVsZW1lbnQgbm9kZXMgYW5kIHByZXZlbnQgbWVtb3J5IGxlYWtzDQovLyAJCWpRdWVyeSggIj4qIiwgdGhpcyApLnJlbW92ZSgpOw0KLy8gDQovLyAJCS8vIFJlbW92ZSBhbnkgcmVtYWluaW5nIG5vZGVzDQovLyAJCXdoaWxlICggdGhpcy5maXJzdENoaWxkICkNCi8vIAkJCXRoaXMucmVtb3ZlQ2hpbGQoIHRoaXMuZmlyc3RDaGlsZCApOw0KLy8gCX0NCi8vIH0sIGZ1bmN0aW9uKG5hbWUsIGZuKXsNCi8vIAlqUXVlcnkuZm5bIG5hbWUgXSA9IGZ1bmN0aW9uKCl7DQovLyAJCXJldHVybiB0aGlzLmVhY2goIGZuLCBhcmd1bWVudHMgKTsNCi8vIAl9Ow0KLy8gfSk7DQoNCmpRdWVyeS5mbi5yZW1vdmVBdHRyID0gZnVuY3Rpb24oKXsNCgkvLy8JPHN1bW1hcnk+DQoJLy8vCQlSZW1vdmUgYW4gYXR0cmlidXRlIGZyb20gZWFjaCBvZiB0aGUgbWF0Y2hlZCBlbGVtZW50cy4NCgkvLy8JCVBhcnQgb2YgRE9NL0F0dHJpYnV0ZXMNCgkvLy8JPC9zdW1tYXJ5Pg0KCS8vLwk8cGFyYW0gbmFtZT0ia2V5IiB0eXBlPSJTdHJpbmciPg0KCS8vLwkJbmFtZSBUaGUgbmFtZSBvZiB0aGUgYXR0cmlidXRlIHRvIHJlbW92ZS4NCgkvLy8JPC9wYXJhbT4NCgkvLy8JPHJldHVybnMgdHlwZT0ialF1ZXJ5IiAvPg0KCXJldHVybiB0aGlzLmVhY2goIGZ1bmN0aW9uKCBuYW1lICkgew0KCQlqUXVlcnkuYXR0ciggdGhpcywgbmFtZSwgIiIgKTsNCgkJaWYgKHRoaXMubm9kZVR5cGUgPT0gMSkNCgkJCXRoaXMucmVtb3ZlQXR0cmlidXRlKCBuYW1lICk7DQoJfSwgYXJndW1lbnRzICk7DQp9Ow0KDQpqUXVlcnkuZm4uYWRkQ2xhc3MgPSBmdW5jdGlvbigpew0KCS8vLwk8c3VtbWFyeT4NCgkvLy8JCUFkZHMgdGhlIHNwZWNpZmllZCBjbGFzcyhlcykgdG8gZWFjaCBvZiB0aGUgc2V0IG9mIG1hdGNoZWQgZWxlbWVudHMuDQoJLy8vCQlQYXJ0IG9mIERPTS9BdHRyaWJ1dGVzDQoJLy8vCTwvc3VtbWFyeT4NCgkvLy8JPHBhcmFtIG5hbWU9ImNsYXNzTmFtZXMiIHR5cGU9IlN0cmluZyI+DQoJLy8vCQlsYXNzIE9uZSBvciBtb3JlIENTUyBjbGFzc2VzIHRvIGFkZCB0byB0aGUgZWxlbWVudHMNCgkvLy8JPC9wYXJhbT4NCgkvLy8JPHJldHVybnMgdHlwZT0ialF1ZXJ5IiAvPg0KCXJldHVybiB0aGlzLmVhY2goIGZ1bmN0aW9uKCBjbGFzc05hbWVzICkgew0KCQlqUXVlcnkuY2xhc3NOYW1lLmFkZCggdGhpcywgY2xhc3NOYW1lcyApOw0KCX0sIGFyZ3VtZW50cyApOw0KfTsNCg0KalF1ZXJ5LmZuLnJlbW92ZUNsYXNzID0gZnVuY3Rpb24oKXsNCgkvLy8JPHN1bW1hcnk+DQoJLy8vCQlSZW1vdmVzIGFsbCBvciB0aGUgc3BlY2lmaWVkIGNsYXNzKGVzKSBmcm9tIHRoZSBzZXQgb2YgbWF0Y2hlZCBlbGVtZW50cy4NCgkvLy8JCVBhcnQgb2YgRE9NL0F0dHJpYnV0ZXMNCgkvLy8JPC9zdW1tYXJ5Pg0KCS8vLwk8cGFyYW0gbmFtZT0iY3NzQ2xhc3NlcyIgdHlwZT0iU3RyaW5nIiBvcHRpb25hbD0idHJ1ZSI+DQoJLy8vCQkoT3B0aW9uYWwpIE9uZSBvciBtb3JlIENTUyBjbGFzc2VzIHRvIHJlbW92ZSBmcm9tIHRoZSBlbGVtZW50cw0KCS8vLwk8L3BhcmFtPg0KCS8vLwk8cmV0dXJucyB0eXBlPSJqUXVlcnkiIC8+DQoJcmV0dXJuIHRoaXMuZWFjaCggZnVuY3Rpb24oIGNsYXNzTmFtZXMgKSB7DQoJCWpRdWVyeS5jbGFzc05hbWUucmVtb3ZlKCB0aGlzLCBjbGFzc05hbWVzICk7DQoJfSwgYXJndW1lbnRzICk7DQp9Ow0KDQpqUXVlcnkuZm4udG9nZ2xlQ2xhc3MgPSBmdW5jdGlvbigpew0KCS8vLwk8c3VtbWFyeT4NCgkvLy8JCUFkZHMgdGhlIHNwZWNpZmllZCBjbGFzcyBpZiBpdCBpcyBub3QgcHJlc2VudCwgcmVtb3ZlcyBpdCBpZiBpdCBpcw0KCS8vLwkJcHJlc2VudC4NCgkvLy8JCVBhcnQgb2YgRE9NL0F0dHJpYnV0ZXMNCgkvLy8JPC9zdW1tYXJ5Pg0KCS8vLwk8cGFyYW0gbmFtZT0iY3NzQ2xhc3MiIHR5cGU9IlN0cmluZyI+DQoJLy8vCQlBIENTUyBjbGFzcyB3aXRoIHdoaWNoIHRvIHRvZ2dsZSB0aGUgZWxlbWVudHMNCgkvLy8JPC9wYXJhbT4NCgkvLy8JPHJldHVybnMgdHlwZT0ialF1ZXJ5IiAvPg0KCXJldHVybiB0aGlzLmVhY2goIGZ1bmN0aW9uKCBjbGFzc05hbWVzLCBzdGF0ZSApIHsNCgkJaWYoIHR5cGVvZiBzdGF0ZSAhPT0gImJvb2xlYW4iICkNCgkJCXN0YXRlID0gIWpRdWVyeS5jbGFzc05hbWUuaGFzKCB0aGlzLCBjbGFzc05hbWVzICk7DQoJCWpRdWVyeS5jbGFzc05hbWVbIHN0YXRlID8gImFkZCIgOiAicmVtb3ZlIiBdKCB0aGlzLCBjbGFzc05hbWVzICk7DQoJfSwgYXJndW1lbnRzICk7DQp9Ow0KDQpqUXVlcnkuZm4ucmVtb3ZlID0gZnVuY3Rpb24oKXsNCgkvLy8JPHN1bW1hcnk+DQoJLy8vCQlSZW1vdmVzIGFsbCBtYXRjaGVkIGVsZW1lbnRzIGZyb20gdGhlIERPTS4gVGhpcyBkb2VzIE5PVCByZW1vdmUgdGhlbSBmcm9tIHRoZQ0KCS8vLwkJalF1ZXJ5IG9iamVjdCwgYWxsb3dpbmcgeW91IHRvIHVzZSB0aGUgbWF0Y2hlZCBlbGVtZW50cyBmdXJ0aGVyLg0KCS8vLwkJQ2FuIGJlIGZpbHRlcmVkIHdpdGggYW4gb3B0aW9uYWwgZXhwcmVzc2lvbnMuDQoJLy8vCQlQYXJ0IG9mIERPTS9NYW5pcHVsYXRpb24NCgkvLy8JPC9zdW1tYXJ5Pg0KCS8vLwk8cGFyYW0gbmFtZT0iZXhwciIgdHlwZT0iU3RyaW5nIiBvcHRpb25hbD0idHJ1ZSI+DQoJLy8vCQkob3B0aW9uYWwpIEEgalF1ZXJ5IGV4cHJlc3Npb24gdG8gZmlsdGVyIGVsZW1lbnRzIGJ5Lg0KCS8vLwk8L3BhcmFtPg0KCS8vLwk8cmV0dXJucyB0eXBlPSJqUXVlcnkiIC8+DQoJcmV0dXJuIHRoaXMuZWFjaCggZnVuY3Rpb24oIHNlbGVjdG9yICkgew0KCQlpZiAoICFzZWxlY3RvciB8fCBqUXVlcnkuZmlsdGVyKCBzZWxlY3RvciwgWyB0aGlzIF0gKS5sZW5ndGggKSB7DQoJCQkvLyBQcmV2ZW50IG1lbW9yeSBsZWFrcw0KCQkJalF1ZXJ5KCAiKiIsIHRoaXMgKS5hZGQoW3RoaXNdKS5lYWNoKGZ1bmN0aW9uKCl7DQoJCQkJalF1ZXJ5LmV2ZW50LnJlbW92ZSh0aGlzKTsNCgkJCQlqUXVlcnkucmVtb3ZlRGF0YSh0aGlzKTsNCgkJCX0pOw0KCQkJaWYgKHRoaXMucGFyZW50Tm9kZSkNCgkJCQl0aGlzLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoIHRoaXMgKTsNCgkJfQ0KCX0sIGFyZ3VtZW50cyApOw0KfTsNCg0KalF1ZXJ5LmZuLmVtcHR5ID0gZnVuY3Rpb24oKXsNCgkvLy8JPHN1bW1hcnk+DQoJLy8vCQlSZW1vdmVzIGFsbCBjaGlsZCBub2RlcyBmcm9tIHRoZSBzZXQgb2YgbWF0Y2hlZCBlbGVtZW50cy4NCgkvLy8JCVBhcnQgb2YgRE9NL01hbmlwdWxhdGlvbg0KCS8vLwk8L3N1bW1hcnk+DQoJLy8vCTxyZXR1cm5zIHR5cGU9ImpRdWVyeSIgLz4NCglyZXR1cm4gdGhpcy5lYWNoKCBmdW5jdGlvbigpIHsNCgkJLy8gUmVtb3ZlIGVsZW1lbnQgbm9kZXMgYW5kIHByZXZlbnQgbWVtb3J5IGxlYWtzDQoJCWpRdWVyeSh0aGlzKS5jaGlsZHJlbigpLnJlbW92ZSgpOw0KDQoJCS8vIFJlbW92ZSBhbnkgcmVtYWluaW5nIG5vZGVzDQoJCXdoaWxlICggdGhpcy5maXJzdENoaWxkICkNCgkJCXRoaXMucmVtb3ZlQ2hpbGQoIHRoaXMuZmlyc3RDaGlsZCApOw0KCX0sIGFyZ3VtZW50cyApOw0KfTsNCg0KLy8gSGVscGVyIGZ1bmN0aW9uIHVzZWQgYnkgdGhlIGRpbWVuc2lvbnMgYW5kIG9mZnNldCBtb2R1bGVzDQpmdW5jdGlvbiBudW0oZWxlbSwgcHJvcCkgew0KCXJldHVybiBlbGVtWzBdICYmIHBhcnNlSW50KCBqUXVlcnkuY3VyQ1NTKGVsZW1bMF0sIHByb3AsIHRydWUpLCAxMCApIHx8IDA7DQp9DQp2YXIgZXhwYW5kbyA9ICJqUXVlcnkiICsgbm93KCksIHV1aWQgPSAwLCB3aW5kb3dEYXRhID0ge307DQoNCmpRdWVyeS5leHRlbmQoew0KCWNhY2hlOiB7fSwNCg0KCWRhdGE6IGZ1bmN0aW9uKCBlbGVtLCBuYW1lLCBkYXRhICkgew0KCQllbGVtID0gZWxlbSA9PSB3aW5kb3cgPw0KCQkJd2luZG93RGF0YSA6DQoJCQllbGVtOw0KDQoJCXZhciBpZCA9IGVsZW1bIGV4cGFuZG8gXTsNCg0KCQkvLyBDb21wdXRlIGEgdW5pcXVlIElEIGZvciB0aGUgZWxlbWVudA0KCQlpZiAoICFpZCApDQoJCQlpZCA9IGVsZW1bIGV4cGFuZG8gXSA9ICsrdXVpZDsNCg0KCQkvLyBPbmx5IGdlbmVyYXRlIHRoZSBkYXRhIGNhY2hlIGlmIHdlJ3JlDQoJCS8vIHRyeWluZyB0byBhY2Nlc3Mgb3IgbWFuaXB1bGF0ZSBpdA0KCQlpZiAoIG5hbWUgJiYgIWpRdWVyeS5jYWNoZVsgaWQgXSApDQoJCQlqUXVlcnkuY2FjaGVbIGlkIF0gPSB7fTsNCg0KCQkvLyBQcmV2ZW50IG92ZXJyaWRpbmcgdGhlIG5hbWVkIGNhY2hlIHdpdGggdW5kZWZpbmVkIHZhbHVlcw0KCQlpZiAoIGRhdGEgIT09IHVuZGVmaW5lZCApDQoJCQlqUXVlcnkuY2FjaGVbIGlkIF1bIG5hbWUgXSA9IGRhdGE7DQoNCgkJLy8gUmV0dXJuIHRoZSBuYW1lZCBjYWNoZSBkYXRhLCBvciB0aGUgSUQgZm9yIHRoZSBlbGVtZW50DQoJCXJldHVybiBuYW1lID8NCgkJCWpRdWVyeS5jYWNoZVsgaWQgXVsgbmFtZSBdIDoNCgkJCWlkOw0KCX0sDQoNCglyZW1vdmVEYXRhOiBmdW5jdGlvbiggZWxlbSwgbmFtZSApIHsNCgkJZWxlbSA9IGVsZW0gPT0gd2luZG93ID8NCgkJCXdpbmRvd0RhdGEgOg0KCQkJZWxlbTsNCg0KCQl2YXIgaWQgPSBlbGVtWyBleHBhbmRvIF07DQoNCgkJLy8gSWYgd2Ugd2FudCB0byByZW1vdmUgYSBzcGVjaWZpYyBzZWN0aW9uIG9mIHRoZSBlbGVtZW50J3MgZGF0YQ0KCQlpZiAoIG5hbWUgKSB7DQoJCQlpZiAoIGpRdWVyeS5jYWNoZVsgaWQgXSApIHsNCgkJCQkvLyBSZW1vdmUgdGhlIHNlY3Rpb24gb2YgY2FjaGUgZGF0YQ0KCQkJCWRlbGV0ZSBqUXVlcnkuY2FjaGVbIGlkIF1bIG5hbWUgXTsNCg0KCQkJCS8vIElmIHdlJ3ZlIHJlbW92ZWQgYWxsIHRoZSBkYXRhLCByZW1vdmUgdGhlIGVsZW1lbnQncyBjYWNoZQ0KCQkJCW5hbWUgPSAiIjsNCg0KCQkJCWZvciAoIG5hbWUgaW4galF1ZXJ5LmNhY2hlWyBpZCBdICkNCgkJCQkJYnJlYWs7DQoNCgkJCQlpZiAoICFuYW1lICkNCgkJCQkJalF1ZXJ5LnJlbW92ZURhdGEoIGVsZW0gKTsNCgkJCX0NCg0KCQkvLyBPdGhlcndpc2UsIHdlIHdhbnQgdG8gcmVtb3ZlIGFsbCBvZiB0aGUgZWxlbWVudCdzIGRhdGENCgkJfSBlbHNlIHsNCgkJCS8vIENsZWFuIHVwIHRoZSBlbGVtZW50IGV4cGFuZG8NCgkJCXRyeSB7DQoJCQkJZGVsZXRlIGVsZW1bIGV4cGFuZG8gXTsNCgkJCX0gY2F0Y2goZSl7DQoJCQkJLy8gSUUgaGFzIHRyb3VibGUgZGlyZWN0bHkgcmVtb3ZpbmcgdGhlIGV4cGFuZG8NCgkJCQkvLyBidXQgaXQncyBvayB3aXRoIHVzaW5nIHJlbW92ZUF0dHJpYnV0ZQ0KCQkJCWlmICggZWxlbS5yZW1vdmVBdHRyaWJ1dGUgKQ0KCQkJCQllbGVtLnJlbW92ZUF0dHJpYnV0ZSggZXhwYW5kbyApOw0KCQkJfQ0KDQoJCQkvLyBDb21wbGV0ZWx5IHJlbW92ZSB0aGUgZGF0YSBjYWNoZQ0KCQkJZGVsZXRlIGpRdWVyeS5jYWNoZVsgaWQgXTsNCgkJfQ0KCX0sDQoJcXVldWU6IGZ1bmN0aW9uKCBlbGVtLCB0eXBlLCBkYXRhICkgew0KCQlpZiAoIGVsZW0gKXsNCgkNCgkJCXR5cGUgPSAodHlwZSB8fCAiZngiKSArICJxdWV1ZSI7DQoJDQoJCQl2YXIgcSA9IGpRdWVyeS5kYXRhKCBlbGVtLCB0eXBlICk7DQoJDQoJCQlpZiAoICFxIHx8IGpRdWVyeS5pc0FycmF5KGRhdGEpICkNCgkJCQlxID0galF1ZXJ5LmRhdGEoIGVsZW0sIHR5cGUsIGpRdWVyeS5tYWtlQXJyYXkoZGF0YSkgKTsNCgkJCWVsc2UgaWYoIGRhdGEgKQ0KCQkJCXEucHVzaCggZGF0YSApOw0KCQ0KCQl9DQoJCXJldHVybiBxOw0KCX0sDQoNCglkZXF1ZXVlOiBmdW5jdGlvbiggZWxlbSwgdHlwZSApew0KCQl2YXIgcXVldWUgPSBqUXVlcnkucXVldWUoIGVsZW0sIHR5cGUgKSwNCgkJCWZuID0gcXVldWUuc2hpZnQoKTsNCgkJDQoJCWlmKCAhdHlwZSB8fCB0eXBlID09PSAiZngiICkNCgkJCWZuID0gcXVldWVbMF07DQoJCQkNCgkJaWYoIGZuICE9PSB1bmRlZmluZWQgKQ0KCQkJZm4uY2FsbChlbGVtKTsNCgl9DQp9KTsNCg0KalF1ZXJ5LmZuLmV4dGVuZCh7DQoJZGF0YTogZnVuY3Rpb24oIGtleSwgdmFsdWUgKXsNCgkJdmFyIHBhcnRzID0ga2V5LnNwbGl0KCIuIik7DQoJCXBhcnRzWzFdID0gcGFydHNbMV0gPyAiLiIgKyBwYXJ0c1sxXSA6ICIiOw0KDQoJCWlmICggdmFsdWUgPT09IHVuZGVmaW5lZCApIHsNCgkJCXZhciBkYXRhID0gdGhpcy50cmlnZ2VySGFuZGxlcigiZ2V0RGF0YSIgKyBwYXJ0c1sxXSArICIhIiwgW3BhcnRzWzBdXSk7DQoNCgkJCWlmICggZGF0YSA9PT0gdW5kZWZpbmVkICYmIHRoaXMubGVuZ3RoICkNCgkJCQlkYXRhID0galF1ZXJ5LmRhdGEoIHRoaXNbMF0sIGtleSApOw0KDQoJCQlyZXR1cm4gZGF0YSA9PT0gdW5kZWZpbmVkICYmIHBhcnRzWzFdID8NCgkJCQl0aGlzLmRhdGEoIHBhcnRzWzBdICkgOg0KCQkJCWRhdGE7DQoJCX0gZWxzZQ0KCQkJcmV0dXJuIHRoaXMudHJpZ2dlcigic2V0RGF0YSIgKyBwYXJ0c1sxXSArICIhIiwgW3BhcnRzWzBdLCB2YWx1ZV0pLmVhY2goZnVuY3Rpb24oKXsNCgkJCQlqUXVlcnkuZGF0YSggdGhpcywga2V5LCB2YWx1ZSApOw0KCQkJfSk7DQoJfSwNCg0KCXJlbW92ZURhdGE6IGZ1bmN0aW9uKCBrZXkgKXsNCgkJcmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbigpew0KCQkJalF1ZXJ5LnJlbW92ZURhdGEoIHRoaXMsIGtleSApOw0KCQl9KTsNCgl9LA0KCXF1ZXVlOiBmdW5jdGlvbih0eXBlLCBkYXRhKXsNCgkJLy8vCTxzdW1tYXJ5Pg0KCQkvLy8JCTE6IHF1ZXVlKCkgLSBSZXR1cm5zIGEgcmVmZXJlbmNlIHRvIHRoZSBmaXJzdCBlbGVtZW50J3MgcXVldWUgKHdoaWNoIGlzIGFuIGFycmF5IG9mIGZ1bmN0aW9ucykuDQoJCS8vLwkJMjogcXVldWUoY2FsbGJhY2spIC0gQWRkcyBhIG5ldyBmdW5jdGlvbiwgdG8gYmUgZXhlY3V0ZWQsIG9udG8gdGhlIGVuZCBvZiB0aGUgcXVldWUgb2YgYWxsIG1hdGNoZWQgZWxlbWVudHMuDQoJCS8vLwkJMzogcXVldWUocXVldWUpIC0gUmVwbGFjZXMgdGhlIHF1ZXVlIG9mIGFsbCBtYXRjaGVkIGVsZW1lbnQgd2l0aCB0aGlzIG5ldyBxdWV1ZSAodGhlIGFycmF5IG9mIGZ1bmN0aW9ucykuDQoJCS8vLwk8L3N1bW1hcnk+DQoJCS8vLwk8cGFyYW0gbmFtZT0idHlwZSIgdHlwZT0iRnVuY3Rpb24iPlRoZSBmdW5jdGlvbiB0byBhZGQgdG8gdGhlIHF1ZXVlLjwvcGFyYW0+DQoJCS8vLwk8cmV0dXJucyB0eXBlPSJqUXVlcnkiIC8+DQoNCgkJaWYgKCB0eXBlb2YgdHlwZSAhPT0gInN0cmluZyIgKSB7DQoJCQlkYXRhID0gdHlwZTsNCgkJCXR5cGUgPSAiZngiOw0KCQl9DQoNCgkJaWYgKCBkYXRhID09PSB1bmRlZmluZWQgKQ0KCQkJcmV0dXJuIGpRdWVyeS5xdWV1ZSggdGhpc1swXSwgdHlwZSApOw0KDQoJCXJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24oKXsNCgkJCXZhciBxdWV1ZSA9IGpRdWVyeS5xdWV1ZSggdGhpcywgdHlwZSwgZGF0YSApOw0KCQkJDQoJCQkgaWYoIHR5cGUgPT0gImZ4IiAmJiBxdWV1ZS5sZW5ndGggPT0gMSApDQoJCQkJcXVldWVbMF0uY2FsbCh0aGlzKTsNCgkJfSk7DQoJfSwNCglkZXF1ZXVlOiBmdW5jdGlvbih0eXBlKXsNCgkJLy8vCTxzdW1tYXJ5Pg0KCQkvLy8JCVJlbW92ZXMgYSBxdWV1ZWQgZnVuY3Rpb24gZnJvbSB0aGUgZnJvbnQgb2YgdGhlIHF1ZXVlIGFuZCBleGVjdXRlcyBpdC4NCgkJLy8vCTwvc3VtbWFyeT4NCgkJLy8vCTxwYXJhbSBuYW1lPSJ0eXBlIiB0eXBlPSJTdHJpbmciIG9wdGlvbmFsPSJ0cnVlIj5UaGUgdHlwZSBvZiBxdWV1ZSB0byBhY2Nlc3MuPC9wYXJhbT4NCgkJLy8vCTxyZXR1cm5zIHR5cGU9ImpRdWVyeSIgLz4NCgkJDQoJCXJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24oKXsNCgkJCWpRdWVyeS5kZXF1ZXVlKCB0aGlzLCB0eXBlICk7DQoJCX0pOw0KCX0NCn0pOy8qIQ0KICogU2l6emxlIENTUyBTZWxlY3RvciBFbmdpbmUgLSB2MC45LjMNCiAqICBDb3B5cmlnaHQgMjAwOSwgVGhlIERvam8gRm91bmRhdGlvbg0KICogIFJlbGVhc2VkIHVuZGVyIHRoZSBNSVQsIEJTRCwgYW5kIEdQTCBMaWNlbnNlcy4NCiAqICBNb3JlIGluZm9ybWF0aW9uOiBodHRwOi8vc2l6emxlanMuY29tLw0KICovDQooZnVuY3Rpb24oKXsNCg0KdmFyIGNodW5rZXIgPSAvKCg/OlwoKD86XChbXigpXStcKXxbXigpXSspK1wpfFxbKD86XFtbXltcXV0qXF18WyciXVteJyJdKlsnIl18W15bXF0nIl0rKStcXXxcXC58W14gPit+LChcW1xcXSspK3xbPit+XSkoXHMqLFxzKik/L2csDQoJZG9uZSA9IDAsDQoJdG9TdHJpbmcgPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nOw0KDQp2YXIgU2l6emxlID0gZnVuY3Rpb24oc2VsZWN0b3IsIGNvbnRleHQsIHJlc3VsdHMsIHNlZWQpIHsNCglyZXN1bHRzID0gcmVzdWx0cyB8fCBbXTsNCgljb250ZXh0ID0gY29udGV4dCB8fCBkb2N1bWVudDsNCg0KCWlmICggY29udGV4dC5ub2RlVHlwZSAhPT0gMSAmJiBjb250ZXh0Lm5vZGVUeXBlICE9PSA5ICkNCgkJcmV0dXJuIFtdOw0KCQ0KCWlmICggIXNlbGVjdG9yIHx8IHR5cGVvZiBzZWxlY3RvciAhPT0gInN0cmluZyIgKSB7DQoJCXJldHVybiByZXN1bHRzOw0KCX0NCg0KCXZhciBwYXJ0cyA9IFtdLCBtLCBzZXQsIGNoZWNrU2V0LCBjaGVjaywgbW9kZSwgZXh0cmEsIHBydW5lID0gdHJ1ZTsNCgkNCgkvLyBSZXNldCB0aGUgcG9zaXRpb24gb2YgdGhlIGNodW5rZXIgcmVnZXhwIChzdGFydCBmcm9tIGhlYWQpDQoJY2h1bmtlci5sYXN0SW5kZXggPSAwOw0KCQ0KCXdoaWxlICggKG0gPSBjaHVua2VyLmV4ZWMoc2VsZWN0b3IpKSAhPT0gbnVsbCApIHsNCgkJcGFydHMucHVzaCggbVsxXSApOw0KCQkNCgkJaWYgKCBtWzJdICkgew0KCQkJZXh0cmEgPSBSZWdFeHAucmlnaHRDb250ZXh0Ow0KCQkJYnJlYWs7DQoJCX0NCgl9DQoNCglpZiAoIHBhcnRzLmxlbmd0aCA+IDEgJiYgb3JpZ1BPUy5leGVjKCBzZWxlY3RvciApICkgew0KCQlpZiAoIHBhcnRzLmxlbmd0aCA9PT0gMiAmJiBFeHByLnJlbGF0aXZlWyBwYXJ0c1swXSBdICkgew0KCQkJc2V0ID0gcG9zUHJvY2VzcyggcGFydHNbMF0gKyBwYXJ0c1sxXSwgY29udGV4dCApOw0KCQl9IGVsc2Ugew0KCQkJc2V0ID0gRXhwci5yZWxhdGl2ZVsgcGFydHNbMF0gXSA/DQoJCQkJWyBjb250ZXh0IF0gOg0KCQkJCVNpenpsZSggcGFydHMuc2hpZnQoKSwgY29udGV4dCApOw0KDQoJCQl3aGlsZSAoIHBhcnRzLmxlbmd0aCApIHsNCgkJCQlzZWxlY3RvciA9IHBhcnRzLnNoaWZ0KCk7DQoNCgkJCQlpZiAoIEV4cHIucmVsYXRpdmVbIHNlbGVjdG9yIF0gKQ0KCQkJCQlzZWxlY3RvciArPSBwYXJ0cy5zaGlmdCgpOw0KDQoJCQkJc2V0ID0gcG9zUHJvY2Vzcyggc2VsZWN0b3IsIHNldCApOw0KCQkJfQ0KCQl9DQoJfSBlbHNlIHsNCgkJdmFyIHJldCA9IHNlZWQgPw0KCQkJeyBleHByOiBwYXJ0cy5wb3AoKSwgc2V0OiBtYWtlQXJyYXkoc2VlZCkgfSA6DQoJCQlTaXp6bGUuZmluZCggcGFydHMucG9wKCksIHBhcnRzLmxlbmd0aCA9PT0gMSAmJiBjb250ZXh0LnBhcmVudE5vZGUgPyBjb250ZXh0LnBhcmVudE5vZGUgOiBjb250ZXh0LCBpc1hNTChjb250ZXh0KSApOw0KCQlzZXQgPSBTaXp6bGUuZmlsdGVyKCByZXQuZXhwciwgcmV0LnNldCApOw0KDQoJCWlmICggcGFydHMubGVuZ3RoID4gMCApIHsNCgkJCWNoZWNrU2V0ID0gbWFrZUFycmF5KHNldCk7DQoJCX0gZWxzZSB7DQoJCQlwcnVuZSA9IGZhbHNlOw0KCQl9DQoNCgkJd2hpbGUgKCBwYXJ0cy5sZW5ndGggKSB7DQoJCQl2YXIgY3VyID0gcGFydHMucG9wKCksIHBvcCA9IGN1cjsNCg0KCQkJaWYgKCAhRXhwci5yZWxhdGl2ZVsgY3VyIF0gKSB7DQoJCQkJY3VyID0gIiI7DQoJCQl9IGVsc2Ugew0KCQkJCXBvcCA9IHBhcnRzLnBvcCgpOw0KCQkJfQ0KDQoJCQlpZiAoIHBvcCA9PSBudWxsICkgew0KCQkJCXBvcCA9IGNvbnRleHQ7DQoJCQl9DQoNCgkJCUV4cHIucmVsYXRpdmVbIGN1ciBdKCBjaGVja1NldCwgcG9wLCBpc1hNTChjb250ZXh0KSApOw0KCQl9DQoJfQ0KDQoJaWYgKCAhY2hlY2tTZXQgKSB7DQoJCWNoZWNrU2V0ID0gc2V0Ow0KCX0NCg0KCWlmICggIWNoZWNrU2V0ICkgew0KCQl0aHJvdyAiU3ludGF4IGVycm9yLCB1bnJlY29nbml6ZWQgZXhwcmVzc2lvbjogIiArIChjdXIgfHwgc2VsZWN0b3IpOw0KCX0NCg0KCWlmICggdG9TdHJpbmcuY2FsbChjaGVja1NldCkgPT09ICJbb2JqZWN0IEFycmF5XSIgKSB7DQoJCWlmICggIXBydW5lICkgew0KCQkJcmVzdWx0cy5wdXNoLmFwcGx5KCByZXN1bHRzLCBjaGVja1NldCApOw0KCQl9IGVsc2UgaWYgKCBjb250ZXh0Lm5vZGVUeXBlID09PSAxICkgew0KCQkJZm9yICggdmFyIGkgPSAwOyBjaGVja1NldFtpXSAhPSBudWxsOyBpKysgKSB7DQoJCQkJaWYgKCBjaGVja1NldFtpXSAmJiAoY2hlY2tTZXRbaV0gPT09IHRydWUgfHwgY2hlY2tTZXRbaV0ubm9kZVR5cGUgPT09IDEgJiYgY29udGFpbnMoY29udGV4dCwgY2hlY2tTZXRbaV0pKSApIHsNCgkJCQkJcmVzdWx0cy5wdXNoKCBzZXRbaV0gKTsNCgkJCQl9DQoJCQl9DQoJCX0gZWxzZSB7DQoJCQlmb3IgKCB2YXIgaSA9IDA7IGNoZWNrU2V0W2ldICE9IG51bGw7IGkrKyApIHsNCgkJCQlpZiAoIGNoZWNrU2V0W2ldICYmIGNoZWNrU2V0W2ldLm5vZGVUeXBlID09PSAxICkgew0KCQkJCQlyZXN1bHRzLnB1c2goIHNldFtpXSApOw0KCQkJCX0NCgkJCX0NCgkJfQ0KCX0gZWxzZSB7DQoJCW1ha2VBcnJheSggY2hlY2tTZXQsIHJlc3VsdHMgKTsNCgl9DQoNCglpZiAoIGV4dHJhICkgew0KCQlTaXp6bGUoIGV4dHJhLCBjb250ZXh0LCByZXN1bHRzLCBzZWVkICk7DQoNCgkJaWYgKCBzb3J0T3JkZXIgKSB7DQoJCQloYXNEdXBsaWNhdGUgPSBmYWxzZTsNCgkJCXJlc3VsdHMuc29ydChzb3J0T3JkZXIpOw0KDQoJCQlpZiAoIGhhc0R1cGxpY2F0ZSApIHsNCgkJCQlmb3IgKCB2YXIgaSA9IDE7IGkgPCByZXN1bHRzLmxlbmd0aDsgaSsrICkgew0KCQkJCQlpZiAoIHJlc3VsdHNbaV0gPT09IHJlc3VsdHNbaS0xXSApIHsNCgkJCQkJCXJlc3VsdHMuc3BsaWNlKGktLSwgMSk7DQoJCQkJCX0NCgkJCQl9DQoJCQl9DQoJCX0NCgl9DQoNCglyZXR1cm4gcmVzdWx0czsNCn07DQoNClNpenpsZS5tYXRjaGVzID0gZnVuY3Rpb24oZXhwciwgc2V0KXsNCglyZXR1cm4gU2l6emxlKGV4cHIsIG51bGwsIG51bGwsIHNldCk7DQp9Ow0KDQpTaXp6bGUuZmluZCA9IGZ1bmN0aW9uKGV4cHIsIGNvbnRleHQsIGlzWE1MKXsNCgl2YXIgc2V0LCBtYXRjaDsNCg0KCWlmICggIWV4cHIgKSB7DQoJCXJldHVybiBbXTsNCgl9DQoNCglmb3IgKCB2YXIgaSA9IDAsIGwgPSBFeHByLm9yZGVyLmxlbmd0aDsgaSA8IGw7IGkrKyApIHsNCgkJdmFyIHR5cGUgPSBFeHByLm9yZGVyW2ldLCBtYXRjaDsNCgkJDQoJCWlmICggKG1hdGNoID0gRXhwci5tYXRjaFsgdHlwZSBdLmV4ZWMoIGV4cHIgKSkgKSB7DQoJCQl2YXIgbGVmdCA9IFJlZ0V4cC5sZWZ0Q29udGV4dDsNCg0KCQkJaWYgKCBsZWZ0LnN1YnN0ciggbGVmdC5sZW5ndGggLSAxICkgIT09ICJcXCIgKSB7DQoJCQkJbWF0Y2hbMV0gPSAobWF0Y2hbMV0gfHwgIiIpLnJlcGxhY2UoL1xcL2csICIiKTsNCgkJCQlzZXQgPSBFeHByLmZpbmRbIHR5cGUgXSggbWF0Y2gsIGNvbnRleHQsIGlzWE1MICk7DQoJCQkJaWYgKCBzZXQgIT0gbnVsbCApIHsNCgkJCQkJZXhwciA9IGV4cHIucmVwbGFjZSggRXhwci5tYXRjaFsgdHlwZSBdLCAiIiApOw0KCQkJCQlicmVhazsNCgkJCQl9DQoJCQl9DQoJCX0NCgl9DQoNCglpZiAoICFzZXQgKSB7DQoJCXNldCA9IGNvbnRleHQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoIioiKTsNCgl9DQoNCglyZXR1cm4ge3NldDogc2V0LCBleHByOiBleHByfTsNCn07DQoNClNpenpsZS5maWx0ZXIgPSBmdW5jdGlvbihleHByLCBzZXQsIGlucGxhY2UsIG5vdCl7DQoJdmFyIG9sZCA9IGV4cHIsIHJlc3VsdCA9IFtdLCBjdXJMb29wID0gc2V0LCBtYXRjaCwgYW55Rm91bmQsDQoJCWlzWE1MRmlsdGVyID0gc2V0ICYmIHNldFswXSAmJiBpc1hNTChzZXRbMF0pOw0KDQoJd2hpbGUgKCBleHByICYmIHNldC5sZW5ndGggKSB7DQoJCWZvciAoIHZhciB0eXBlIGluIEV4cHIuZmlsdGVyICkgew0KCQkJaWYgKCAobWF0Y2ggPSBFeHByLm1hdGNoWyB0eXBlIF0uZXhlYyggZXhwciApKSAhPSBudWxsICkgew0KCQkJCXZhciBmaWx0ZXIgPSBFeHByLmZpbHRlclsgdHlwZSBdLCBmb3VuZCwgaXRlbTsNCgkJCQlhbnlGb3VuZCA9IGZhbHNlOw0KDQoJCQkJaWYgKCBjdXJMb29wID09IHJlc3VsdCApIHsNCgkJCQkJcmVzdWx0ID0gW107DQoJCQkJfQ0KDQoJCQkJaWYgKCBFeHByLnByZUZpbHRlclsgdHlwZSBdICkgew0KCQkJCQltYXRjaCA9IEV4cHIucHJlRmlsdGVyWyB0eXBlIF0oIG1hdGNoLCBjdXJMb29wLCBpbnBsYWNlLCByZXN1bHQsIG5vdCwgaXNYTUxGaWx0ZXIgKTsNCg0KCQkJCQlpZiAoICFtYXRjaCApIHsNCgkJCQkJCWFueUZvdW5kID0gZm91bmQgPSB0cnVlOw0KCQkJCQl9IGVsc2UgaWYgKCBtYXRjaCA9PT0gdHJ1ZSApIHsNCgkJCQkJCWNvbnRpbnVlOw0KCQkJCQl9DQoJCQkJfQ0KDQoJCQkJaWYgKCBtYXRjaCApIHsNCgkJCQkJZm9yICggdmFyIGkgPSAwOyAoaXRlbSA9IGN1ckxvb3BbaV0pICE9IG51bGw7IGkrKyApIHsNCgkJCQkJCWlmICggaXRlbSApIHsNCgkJCQkJCQlmb3VuZCA9IGZpbHRlciggaXRlbSwgbWF0Y2gsIGksIGN1ckxvb3AgKTsNCgkJCQkJCQl2YXIgcGFzcyA9IG5vdCBeICEhZm91bmQ7DQoNCgkJCQkJCQlpZiAoIGlucGxhY2UgJiYgZm91bmQgIT0gbnVsbCApIHsNCgkJCQkJCQkJaWYgKCBwYXNzICkgew0KCQkJCQkJCQkJYW55Rm91bmQgPSB0cnVlOw0KCQkJCQkJCQl9IGVsc2Ugew0KCQkJCQkJCQkJY3VyTG9vcFtpXSA9IGZhbHNlOw0KCQkJCQkJCQl9DQoJCQkJCQkJfSBlbHNlIGlmICggcGFzcyApIHsNCgkJCQkJCQkJcmVzdWx0LnB1c2goIGl0ZW0gKTsNCgkJCQkJCQkJYW55Rm91bmQgPSB0cnVlOw0KCQkJCQkJCX0NCgkJCQkJCX0NCgkJCQkJfQ0KCQkJCX0NCg0KCQkJCWlmICggZm91bmQgIT09IHVuZGVmaW5lZCApIHsNCgkJCQkJaWYgKCAhaW5wbGFjZSApIHsNCgkJCQkJCWN1ckxvb3AgPSByZXN1bHQ7DQoJCQkJCX0NCg0KCQkJCQlleHByID0gZXhwci5yZXBsYWNlKCBFeHByLm1hdGNoWyB0eXBlIF0sICIiICk7DQoNCgkJCQkJaWYgKCAhYW55Rm91bmQgKSB7DQoJCQkJCQlyZXR1cm4gW107DQoJCQkJCX0NCg0KCQkJCQlicmVhazsNCgkJCQl9DQoJCQl9DQoJCX0NCg0KCQkvLyBJbXByb3BlciBleHByZXNzaW9uDQoJCWlmICggZXhwciA9PSBvbGQgKSB7DQoJCQlpZiAoIGFueUZvdW5kID09IG51bGwgKSB7DQoJCQkJdGhyb3cgIlN5bnRheCBlcnJvciwgdW5yZWNvZ25pemVkIGV4cHJlc3Npb246ICIgKyBleHByOw0KCQkJfSBlbHNlIHsNCgkJCQlicmVhazsNCgkJCX0NCgkJfQ0KDQoJCW9sZCA9IGV4cHI7DQoJfQ0KDQoJcmV0dXJuIGN1ckxvb3A7DQp9Ow0KDQp2YXIgRXhwciA9IFNpenpsZS5zZWxlY3RvcnMgPSB7DQoJb3JkZXI6IFsgIklEIiwgIk5BTUUiLCAiVEFHIiBdLA0KCW1hdGNoOiB7DQoJCUlEOiAvIygoPzpbXHdcdTAwYzAtXHVGRkZGXy1dfFxcLikrKS8sDQoJCUNMQVNTOiAvXC4oKD86W1x3XHUwMGMwLVx1RkZGRl8tXXxcXC4pKykvLA0KCQlOQU1FOiAvXFtuYW1lPVsnIl0qKCg/Oltcd1x1MDBjMC1cdUZGRkZfLV18XFwuKSspWyciXSpcXS8sDQoJCUFUVFI6IC9cW1xzKigoPzpbXHdcdTAwYzAtXHVGRkZGXy1dfFxcLikrKVxzKig/OihcUz89KVxzKihbJyJdKikoLio/KVwzfClccypcXS8sDQoJCVRBRzogL14oKD86W1x3XHUwMGMwLVx1RkZGRlwqXy1dfFxcLikrKS8sDQoJCUNISUxEOiAvOihvbmx5fG50aHxsYXN0fGZpcnN0KS1jaGlsZCg/OlwoKGV2ZW58b2RkfFtcZG4rLV0qKVwpKT8vLA0KCQlQT1M6IC86KG50aHxlcXxndHxsdHxmaXJzdHxsYXN0fGV2ZW58b2RkKSg/OlwoKFxkKilcKSk/KD89W14tXXwkKS8sDQoJCVBTRVVETzogLzooKD86W1x3XHUwMGMwLVx1RkZGRl8tXXxcXC4pKykoPzpcKChbJyJdKikoKD86XChbXlwpXStcKXxbXlwyXChcKV0qKSspXDJcKSk/Lw0KCX0sDQoJYXR0ck1hcDogew0KCQkiY2xhc3MiOiAiY2xhc3NOYW1lIiwNCgkJImZvciI6ICJodG1sRm9yIg0KCX0sDQoJYXR0ckhhbmRsZTogew0KCQlocmVmOiBmdW5jdGlvbihlbGVtKXsNCgkJCXJldHVybiBlbGVtLmdldEF0dHJpYnV0ZSgiaHJlZiIpOw0KCQl9DQoJfSwNCglyZWxhdGl2ZTogew0KCQkiKyI6IGZ1bmN0aW9uKGNoZWNrU2V0LCBwYXJ0LCBpc1hNTCl7DQoJCQl2YXIgaXNQYXJ0U3RyID0gdHlwZW9mIHBhcnQgPT09ICJzdHJpbmciLA0KCQkJCWlzVGFnID0gaXNQYXJ0U3RyICYmICEvXFcvLnRlc3QocGFydCksDQoJCQkJaXNQYXJ0U3RyTm90VGFnID0gaXNQYXJ0U3RyICYmICFpc1RhZzsNCg0KCQkJaWYgKCBpc1RhZyAmJiAhaXNYTUwgKSB7DQoJCQkJcGFydCA9IHBhcnQudG9VcHBlckNhc2UoKTsNCgkJCX0NCg0KCQkJZm9yICggdmFyIGkgPSAwLCBsID0gY2hlY2tTZXQubGVuZ3RoLCBlbGVtOyBpIDwgbDsgaSsrICkgew0KCQkJCWlmICggKGVsZW0gPSBjaGVja1NldFtpXSkgKSB7DQoJCQkJCXdoaWxlICggKGVsZW0gPSBlbGVtLnByZXZpb3VzU2libGluZykgJiYgZWxlbS5ub2RlVHlwZSAhPT0gMSApIHt9DQoNCgkJCQkJY2hlY2tTZXRbaV0gPSBpc1BhcnRTdHJOb3RUYWcgfHwgZWxlbSAmJiBlbGVtLm5vZGVOYW1lID09PSBwYXJ0ID8NCgkJCQkJCWVsZW0gfHwgZmFsc2UgOg0KCQkJCQkJZWxlbSA9PT0gcGFydDsNCgkJCQl9DQoJCQl9DQoNCgkJCWlmICggaXNQYXJ0U3RyTm90VGFnICkgew0KCQkJCVNpenpsZS5maWx0ZXIoIHBhcnQsIGNoZWNrU2V0LCB0cnVlICk7DQoJCQl9DQoJCX0sDQoJCSI+IjogZnVuY3Rpb24oY2hlY2tTZXQsIHBhcnQsIGlzWE1MKXsNCgkJCXZhciBpc1BhcnRTdHIgPSB0eXBlb2YgcGFydCA9PT0gInN0cmluZyI7DQoNCgkJCWlmICggaXNQYXJ0U3RyICYmICEvXFcvLnRlc3QocGFydCkgKSB7DQoJCQkJcGFydCA9IGlzWE1MID8gcGFydCA6IHBhcnQudG9VcHBlckNhc2UoKTsNCg0KCQkJCWZvciAoIHZhciBpID0gMCwgbCA9IGNoZWNrU2V0Lmxlbmd0aDsgaSA8IGw7IGkrKyApIHsNCgkJCQkJdmFyIGVsZW0gPSBjaGVja1NldFtpXTsNCgkJCQkJaWYgKCBlbGVtICkgew0KCQkJCQkJdmFyIHBhcmVudCA9IGVsZW0ucGFyZW50Tm9kZTsNCgkJCQkJCWNoZWNrU2V0W2ldID0gcGFyZW50Lm5vZGVOYW1lID09PSBwYXJ0ID8gcGFyZW50IDogZmFsc2U7DQoJCQkJCX0NCgkJCQl9DQoJCQl9IGVsc2Ugew0KCQkJCWZvciAoIHZhciBpID0gMCwgbCA9IGNoZWNrU2V0Lmxlbmd0aDsgaSA8IGw7IGkrKyApIHsNCgkJCQkJdmFyIGVsZW0gPSBjaGVja1NldFtpXTsNCgkJCQkJaWYgKCBlbGVtICkgew0KCQkJCQkJY2hlY2tTZXRbaV0gPSBpc1BhcnRTdHIgPw0KCQkJCQkJCWVsZW0ucGFyZW50Tm9kZSA6DQoJCQkJCQkJZWxlbS5wYXJlbnROb2RlID09PSBwYXJ0Ow0KCQkJCQl9DQoJCQkJfQ0KDQoJCQkJaWYgKCBpc1BhcnRTdHIgKSB7DQoJCQkJCVNpenpsZS5maWx0ZXIoIHBhcnQsIGNoZWNrU2V0LCB0cnVlICk7DQoJCQkJfQ0KCQkJfQ0KCQl9LA0KCQkiIjogZnVuY3Rpb24oY2hlY2tTZXQsIHBhcnQsIGlzWE1MKXsNCgkJCXZhciBkb25lTmFtZSA9IGRvbmUrKywgY2hlY2tGbiA9IGRpckNoZWNrOw0KDQoJCQlpZiAoICFwYXJ0Lm1hdGNoKC9cVy8pICkgew0KCQkJCXZhciBub2RlQ2hlY2sgPSBwYXJ0ID0gaXNYTUwgPyBwYXJ0IDogcGFydC50b1VwcGVyQ2FzZSgpOw0KCQkJCWNoZWNrRm4gPSBkaXJOb2RlQ2hlY2s7DQoJCQl9DQoNCgkJCWNoZWNrRm4oInBhcmVudE5vZGUiLCBwYXJ0LCBkb25lTmFtZSwgY2hlY2tTZXQsIG5vZGVDaGVjaywgaXNYTUwpOw0KCQl9LA0KCQkifiI6IGZ1bmN0aW9uKGNoZWNrU2V0LCBwYXJ0LCBpc1hNTCl7DQoJCQl2YXIgZG9uZU5hbWUgPSBkb25lKyssIGNoZWNrRm4gPSBkaXJDaGVjazsNCg0KCQkJaWYgKCB0eXBlb2YgcGFydCA9PT0gInN0cmluZyIgJiYgIXBhcnQubWF0Y2goL1xXLykgKSB7DQoJCQkJdmFyIG5vZGVDaGVjayA9IHBhcnQgPSBpc1hNTCA/IHBhcnQgOiBwYXJ0LnRvVXBwZXJDYXNlKCk7DQoJCQkJY2hlY2tGbiA9IGRpck5vZGVDaGVjazsNCgkJCX0NCg0KCQkJY2hlY2tGbigicHJldmlvdXNTaWJsaW5nIiwgcGFydCwgZG9uZU5hbWUsIGNoZWNrU2V0LCBub2RlQ2hlY2ssIGlzWE1MKTsNCgkJfQ0KCX0sDQoJZmluZDogew0KCQlJRDogZnVuY3Rpb24obWF0Y2gsIGNvbnRleHQsIGlzWE1MKXsNCgkJCWlmICggdHlwZW9mIGNvbnRleHQuZ2V0RWxlbWVudEJ5SWQgIT09ICJ1bmRlZmluZWQiICYmICFpc1hNTCApIHsNCgkJCQl2YXIgbSA9IGNvbnRleHQuZ2V0RWxlbWVudEJ5SWQobWF0Y2hbMV0pOw0KCQkJCXJldHVybiBtID8gW21dIDogW107DQoJCQl9DQoJCX0sDQoJCU5BTUU6IGZ1bmN0aW9uKG1hdGNoLCBjb250ZXh0LCBpc1hNTCl7DQoJCQlpZiAoIHR5cGVvZiBjb250ZXh0LmdldEVsZW1lbnRzQnlOYW1lICE9PSAidW5kZWZpbmVkIiApIHsNCgkJCQl2YXIgcmV0ID0gW10sIHJlc3VsdHMgPSBjb250ZXh0LmdldEVsZW1lbnRzQnlOYW1lKG1hdGNoWzFdKTsNCg0KCQkJCWZvciAoIHZhciBpID0gMCwgbCA9IHJlc3VsdHMubGVuZ3RoOyBpIDwgbDsgaSsrICkgew0KCQkJCQlpZiAoIHJlc3VsdHNbaV0uZ2V0QXR0cmlidXRlKCJuYW1lIikgPT09IG1hdGNoWzFdICkgew0KCQkJCQkJcmV0LnB1c2goIHJlc3VsdHNbaV0gKTsNCgkJCQkJfQ0KCQkJCX0NCg0KCQkJCXJldHVybiByZXQubGVuZ3RoID09PSAwID8gbnVsbCA6IHJldDsNCgkJCX0NCgkJfSwNCgkJVEFHOiBmdW5jdGlvbihtYXRjaCwgY29udGV4dCl7DQoJCQlyZXR1cm4gY29udGV4dC5nZXRFbGVtZW50c0J5VGFnTmFtZShtYXRjaFsxXSk7DQoJCX0NCgl9LA0KCXByZUZpbHRlcjogew0KCQlDTEFTUzogZnVuY3Rpb24obWF0Y2gsIGN1ckxvb3AsIGlucGxhY2UsIHJlc3VsdCwgbm90LCBpc1hNTCl7DQoJCQltYXRjaCA9ICIgIiArIG1hdGNoWzFdLnJlcGxhY2UoL1xcL2csICIiKSArICIgIjsNCg0KCQkJaWYgKCBpc1hNTCApIHsNCgkJCQlyZXR1cm4gbWF0Y2g7DQoJCQl9DQoNCgkJCWZvciAoIHZhciBpID0gMCwgZWxlbTsgKGVsZW0gPSBjdXJMb29wW2ldKSAhPSBudWxsOyBpKysgKSB7DQoJCQkJaWYgKCBlbGVtICkgew0KCQkJCQlpZiAoIG5vdCBeIChlbGVtLmNsYXNzTmFtZSAmJiAoIiAiICsgZWxlbS5jbGFzc05hbWUgKyAiICIpLmluZGV4T2YobWF0Y2gpID49IDApICkgew0KCQkJCQkJaWYgKCAhaW5wbGFjZSApDQoJCQkJCQkJcmVzdWx0LnB1c2goIGVsZW0gKTsNCgkJCQkJfSBlbHNlIGlmICggaW5wbGFjZSApIHsNCgkJCQkJCWN1ckxvb3BbaV0gPSBmYWxzZTsNCgkJCQkJfQ0KCQkJCX0NCgkJCX0NCg0KCQkJcmV0dXJuIGZhbHNlOw0KCQl9LA0KCQlJRDogZnVuY3Rpb24obWF0Y2gpew0KCQkJcmV0dXJuIG1hdGNoWzFdLnJlcGxhY2UoL1xcL2csICIiKTsNCgkJfSwNCgkJVEFHOiBmdW5jdGlvbihtYXRjaCwgY3VyTG9vcCl7DQoJCQlmb3IgKCB2YXIgaSA9IDA7IGN1ckxvb3BbaV0gPT09IGZhbHNlOyBpKysgKXt9DQoJCQlyZXR1cm4gY3VyTG9vcFtpXSAmJiBpc1hNTChjdXJMb29wW2ldKSA/IG1hdGNoWzFdIDogbWF0Y2hbMV0udG9VcHBlckNhc2UoKTsNCgkJfSwNCgkJQ0hJTEQ6IGZ1bmN0aW9uKG1hdGNoKXsNCgkJCWlmICggbWF0Y2hbMV0gPT0gIm50aCIgKSB7DQoJCQkJLy8gcGFyc2UgZXF1YXRpb25zIGxpa2UgJ2V2ZW4nLCAnb2RkJywgJzUnLCAnMm4nLCAnM24rMicsICc0bi0xJywgJy1uKzYnDQoJCQkJdmFyIHRlc3QgPSAvKC0/KShcZCopbigoPzpcK3wtKT9cZCopLy5leGVjKA0KCQkJCQltYXRjaFsyXSA9PSAiZXZlbiIgJiYgIjJuIiB8fCBtYXRjaFsyXSA9PSAib2RkIiAmJiAiMm4rMSIgfHwNCgkJCQkJIS9cRC8udGVzdCggbWF0Y2hbMl0gKSAmJiAiMG4rIiArIG1hdGNoWzJdIHx8IG1hdGNoWzJdKTsNCg0KCQkJCS8vIGNhbGN1bGF0ZSB0aGUgbnVtYmVycyAoZmlyc3QpbisobGFzdCkgaW5jbHVkaW5nIGlmIHRoZXkgYXJlIG5lZ2F0aXZlDQoJCQkJbWF0Y2hbMl0gPSAodGVzdFsxXSArICh0ZXN0WzJdIHx8IDEpKSAtIDA7DQoJCQkJbWF0Y2hbM10gPSB0ZXN0WzNdIC0gMDsNCgkJCX0NCg0KCQkJLy8gVE9ETzogTW92ZSB0byBub3JtYWwgY2FjaGluZyBzeXN0ZW0NCgkJCW1hdGNoWzBdID0gZG9uZSsrOw0KDQoJCQlyZXR1cm4gbWF0Y2g7DQoJCX0sDQoJCUFUVFI6IGZ1bmN0aW9uKG1hdGNoLCBjdXJMb29wLCBpbnBsYWNlLCByZXN1bHQsIG5vdCwgaXNYTUwpew0KCQkJdmFyIG5hbWUgPSBtYXRjaFsxXS5yZXBsYWNlKC9cXC9nLCAiIik7DQoJCQkNCgkJCWlmICggIWlzWE1MICYmIEV4cHIuYXR0ck1hcFtuYW1lXSApIHsNCgkJCQltYXRjaFsxXSA9IEV4cHIuYXR0ck1hcFtuYW1lXTsNCgkJCX0NCg0KCQkJaWYgKCBtYXRjaFsyXSA9PT0gIn49IiApIHsNCgkJCQltYXRjaFs0XSA9ICIgIiArIG1hdGNoWzRdICsgIiAiOw0KCQkJfQ0KDQoJCQlyZXR1cm4gbWF0Y2g7DQoJCX0sDQoJCVBTRVVETzogZnVuY3Rpb24obWF0Y2gsIGN1ckxvb3AsIGlucGxhY2UsIHJlc3VsdCwgbm90KXsNCgkJCWlmICggbWF0Y2hbMV0gPT09ICJub3QiICkgew0KCQkJCS8vIElmIHdlJ3JlIGRlYWxpbmcgd2l0aCBhIGNvbXBsZXggZXhwcmVzc2lvbiwgb3IgYSBzaW1wbGUgb25lDQoJCQkJaWYgKCBtYXRjaFszXS5tYXRjaChjaHVua2VyKS5sZW5ndGggPiAxIHx8IC9eXHcvLnRlc3QobWF0Y2hbM10pICkgew0KCQkJCQltYXRjaFszXSA9IFNpenpsZShtYXRjaFszXSwgbnVsbCwgbnVsbCwgY3VyTG9vcCk7DQoJCQkJfSBlbHNlIHsNCgkJCQkJdmFyIHJldCA9IFNpenpsZS5maWx0ZXIobWF0Y2hbM10sIGN1ckxvb3AsIGlucGxhY2UsIHRydWUgXiBub3QpOw0KCQkJCQlpZiAoICFpbnBsYWNlICkgew0KCQkJCQkJcmVzdWx0LnB1c2guYXBwbHkoIHJlc3VsdCwgcmV0ICk7DQoJCQkJCX0NCgkJCQkJcmV0dXJuIGZhbHNlOw0KCQkJCX0NCgkJCX0gZWxzZSBpZiAoIEV4cHIubWF0Y2guUE9TLnRlc3QoIG1hdGNoWzBdICkgfHwgRXhwci5tYXRjaC5DSElMRC50ZXN0KCBtYXRjaFswXSApICkgew0KCQkJCXJldHVybiB0cnVlOw0KCQkJfQ0KCQkJDQoJCQlyZXR1cm4gbWF0Y2g7DQoJCX0sDQoJCVBPUzogZnVuY3Rpb24obWF0Y2gpew0KCQkJbWF0Y2gudW5zaGlmdCggdHJ1ZSApOw0KCQkJcmV0dXJuIG1hdGNoOw0KCQl9DQoJfSwNCglmaWx0ZXJzOiB7DQoJCWVuYWJsZWQ6IGZ1bmN0aW9uKGVsZW0pew0KCQkJcmV0dXJuIGVsZW0uZGlzYWJsZWQgPT09IGZhbHNlICYmIGVsZW0udHlwZSAhPT0gImhpZGRlbiI7DQoJCX0sDQoJCWRpc2FibGVkOiBmdW5jdGlvbihlbGVtKXsNCgkJCXJldHVybiBlbGVtLmRpc2FibGVkID09PSB0cnVlOw0KCQl9LA0KCQljaGVja2VkOiBmdW5jdGlvbihlbGVtKXsNCgkJCXJldHVybiBlbGVtLmNoZWNrZWQgPT09IHRydWU7DQoJCX0sDQoJCXNlbGVjdGVkOiBmdW5jdGlvbihlbGVtKXsNCgkJCS8vIEFjY2Vzc2luZyB0aGlzIHByb3BlcnR5IG1ha2VzIHNlbGVjdGVkLWJ5LWRlZmF1bHQNCgkJCS8vIG9wdGlvbnMgaW4gU2FmYXJpIHdvcmsgcHJvcGVybHkNCgkJCWVsZW0ucGFyZW50Tm9kZS5zZWxlY3RlZEluZGV4Ow0KCQkJcmV0dXJuIGVsZW0uc2VsZWN0ZWQgPT09IHRydWU7DQoJCX0sDQoJCXBhcmVudDogZnVuY3Rpb24oZWxlbSl7DQoJCQlyZXR1cm4gISFlbGVtLmZpcnN0Q2hpbGQ7DQoJCX0sDQoJCWVtcHR5OiBmdW5jdGlvbihlbGVtKXsNCgkJCXJldHVybiAhZWxlbS5maXJzdENoaWxkOw0KCQl9LA0KCQloYXM6IGZ1bmN0aW9uKGVsZW0sIGksIG1hdGNoKXsNCgkJCXJldHVybiAhIVNpenpsZSggbWF0Y2hbM10sIGVsZW0gKS5sZW5ndGg7DQoJCX0sDQoJCWhlYWRlcjogZnVuY3Rpb24oZWxlbSl7DQoJCQlyZXR1cm4gL2hcZC9pLnRlc3QoIGVsZW0ubm9kZU5hbWUgKTsNCgkJfSwNCgkJdGV4dDogZnVuY3Rpb24oZWxlbSl7DQoJCQlyZXR1cm4gInRleHQiID09PSBlbGVtLnR5cGU7DQoJCX0sDQoJCXJhZGlvOiBmdW5jdGlvbihlbGVtKXsNCgkJCXJldHVybiAicmFkaW8iID09PSBlbGVtLnR5cGU7DQoJCX0sDQoJCWNoZWNrYm94OiBmdW5jdGlvbihlbGVtKXsNCgkJCXJldHVybiAiY2hlY2tib3giID09PSBlbGVtLnR5cGU7DQoJCX0sDQoJCWZpbGU6IGZ1bmN0aW9uKGVsZW0pew0KCQkJcmV0dXJuICJmaWxlIiA9PT0gZWxlbS50eXBlOw0KCQl9LA0KCQlwYXNzd29yZDogZnVuY3Rpb24oZWxlbSl7DQoJCQlyZXR1cm4gInBhc3N3b3JkIiA9PT0gZWxlbS50eXBlOw0KCQl9LA0KCQlzdWJtaXQ6IGZ1bmN0aW9uKGVsZW0pew0KCQkJcmV0dXJuICJzdWJtaXQiID09PSBlbGVtLnR5cGU7DQoJCX0sDQoJCWltYWdlOiBmdW5jdGlvbihlbGVtKXsNCgkJCXJldHVybiAiaW1hZ2UiID09PSBlbGVtLnR5cGU7DQoJCX0sDQoJCXJlc2V0OiBmdW5jdGlvbihlbGVtKXsNCgkJCXJldHVybiAicmVzZXQiID09PSBlbGVtLnR5cGU7DQoJCX0sDQoJCWJ1dHRvbjogZnVuY3Rpb24oZWxlbSl7DQoJCQlyZXR1cm4gImJ1dHRvbiIgPT09IGVsZW0udHlwZSB8fCBlbGVtLm5vZGVOYW1lLnRvVXBwZXJDYXNlKCkgPT09ICJCVVRUT04iOw0KCQl9LA0KCQlpbnB1dDogZnVuY3Rpb24oZWxlbSl7DQoJCQlyZXR1cm4gL2lucHV0fHNlbGVjdHx0ZXh0YXJlYXxidXR0b24vaS50ZXN0KGVsZW0ubm9kZU5hbWUpOw0KCQl9DQoJfSwNCglzZXRGaWx0ZXJzOiB7DQoJCWZpcnN0OiBmdW5jdGlvbihlbGVtLCBpKXsNCgkJCXJldHVybiBpID09PSAwOw0KCQl9LA0KCQlsYXN0OiBmdW5jdGlvbihlbGVtLCBpLCBtYXRjaCwgYXJyYXkpew0KCQkJcmV0dXJuIGkgPT09IGFycmF5Lmxlbmd0aCAtIDE7DQoJCX0sDQoJCWV2ZW46IGZ1bmN0aW9uKGVsZW0sIGkpew0KCQkJcmV0dXJuIGkgJSAyID09PSAwOw0KCQl9LA0KCQlvZGQ6IGZ1bmN0aW9uKGVsZW0sIGkpew0KCQkJcmV0dXJuIGkgJSAyID09PSAxOw0KCQl9LA0KCQlsdDogZnVuY3Rpb24oZWxlbSwgaSwgbWF0Y2gpew0KCQkJcmV0dXJuIGkgPCBtYXRjaFszXSAtIDA7DQoJCX0sDQoJCWd0OiBmdW5jdGlvbihlbGVtLCBpLCBtYXRjaCl7DQoJCQlyZXR1cm4gaSA+IG1hdGNoWzNdIC0gMDsNCgkJfSwNCgkJbnRoOiBmdW5jdGlvbihlbGVtLCBpLCBtYXRjaCl7DQoJCQlyZXR1cm4gbWF0Y2hbM10gLSAwID09IGk7DQoJCX0sDQoJCWVxOiBmdW5jdGlvbihlbGVtLCBpLCBtYXRjaCl7DQoJCQlyZXR1cm4gbWF0Y2hbM10gLSAwID09IGk7DQoJCX0NCgl9LA0KCWZpbHRlcjogew0KCQlQU0VVRE86IGZ1bmN0aW9uKGVsZW0sIG1hdGNoLCBpLCBhcnJheSl7DQoJCQl2YXIgbmFtZSA9IG1hdGNoWzFdLCBmaWx0ZXIgPSBFeHByLmZpbHRlcnNbIG5hbWUgXTsNCg0KCQkJaWYgKCBmaWx0ZXIgKSB7DQoJCQkJcmV0dXJuIGZpbHRlciggZWxlbSwgaSwgbWF0Y2gsIGFycmF5ICk7DQoJCQl9IGVsc2UgaWYgKCBuYW1lID09PSAiY29udGFpbnMiICkgew0KCQkJCXJldHVybiAoZWxlbS50ZXh0Q29udGVudCB8fCBlbGVtLmlubmVyVGV4dCB8fCAiIikuaW5kZXhPZihtYXRjaFszXSkgPj0gMDsNCgkJCX0gZWxzZSBpZiAoIG5hbWUgPT09ICJub3QiICkgew0KCQkJCXZhciBub3QgPSBtYXRjaFszXTsNCg0KCQkJCWZvciAoIHZhciBpID0gMCwgbCA9IG5vdC5sZW5ndGg7IGkgPCBsOyBpKysgKSB7DQoJCQkJCWlmICggbm90W2ldID09PSBlbGVtICkgew0KCQkJCQkJcmV0dXJuIGZhbHNlOw0KCQkJCQl9DQoJCQkJfQ0KDQoJCQkJcmV0dXJuIHRydWU7DQoJCQl9DQoJCX0sDQoJCUNISUxEOiBmdW5jdGlvbihlbGVtLCBtYXRjaCl7DQoJCQl2YXIgdHlwZSA9IG1hdGNoWzFdLCBub2RlID0gZWxlbTsNCgkJCXN3aXRjaCAodHlwZSkgew0KCQkJCWNhc2UgJ29ubHknOg0KCQkJCWNhc2UgJ2ZpcnN0JzoNCgkJCQkJd2hpbGUgKG5vZGUgPSBub2RlLnByZXZpb3VzU2libGluZykgIHsNCgkJCQkJCWlmICggbm9kZS5ub2RlVHlwZSA9PT0gMSApIHJldHVybiBmYWxzZTsNCgkJCQkJfQ0KCQkJCQlpZiAoIHR5cGUgPT0gJ2ZpcnN0JykgcmV0dXJuIHRydWU7DQoJCQkJCW5vZGUgPSBlbGVtOw0KCQkJCWNhc2UgJ2xhc3QnOg0KCQkJCQl3aGlsZSAobm9kZSA9IG5vZGUubmV4dFNpYmxpbmcpICB7DQoJCQkJCQlpZiAoIG5vZGUubm9kZVR5cGUgPT09IDEgKSByZXR1cm4gZmFsc2U7DQoJCQkJCX0NCgkJCQkJcmV0dXJuIHRydWU7DQoJCQkJY2FzZSAnbnRoJzoNCgkJCQkJdmFyIGZpcnN0ID0gbWF0Y2hbMl0sIGxhc3QgPSBtYXRjaFszXTsNCg0KCQkJCQlpZiAoIGZpcnN0ID09IDEgJiYgbGFzdCA9PSAwICkgew0KCQkJCQkJcmV0dXJuIHRydWU7DQoJCQkJCX0NCgkJCQkJDQoJCQkJCXZhciBkb25lTmFtZSA9IG1hdGNoWzBdLA0KCQkJCQkJcGFyZW50ID0gZWxlbS5wYXJlbnROb2RlOw0KCQ0KCQkJCQlpZiAoIHBhcmVudCAmJiAocGFyZW50LnNpemNhY2hlICE9PSBkb25lTmFtZSB8fCAhZWxlbS5ub2RlSW5kZXgpICkgew0KCQkJCQkJdmFyIGNvdW50ID0gMDsNCgkJCQkJCWZvciAoIG5vZGUgPSBwYXJlbnQuZmlyc3RDaGlsZDsgbm9kZTsgbm9kZSA9IG5vZGUubmV4dFNpYmxpbmcgKSB7DQoJCQkJCQkJaWYgKCBub2RlLm5vZGVUeXBlID09PSAxICkgew0KCQkJCQkJCQlub2RlLm5vZGVJbmRleCA9ICsrY291bnQ7DQoJCQkJCQkJfQ0KCQkJCQkJfSANCgkJCQkJCXBhcmVudC5zaXpjYWNoZSA9IGRvbmVOYW1lOw0KCQkJCQl9DQoJCQkJCQ0KCQkJCQl2YXIgZGlmZiA9IGVsZW0ubm9kZUluZGV4IC0gbGFzdDsNCgkJCQkJaWYgKCBmaXJzdCA9PSAwICkgew0KCQkJCQkJcmV0dXJuIGRpZmYgPT0gMDsNCgkJCQkJfSBlbHNlIHsNCgkJCQkJCXJldHVybiAoIGRpZmYgJSBmaXJzdCA9PSAwICYmIGRpZmYgLyBmaXJzdCA+PSAwICk7DQoJCQkJCX0NCgkJCX0NCgkJfSwNCgkJSUQ6IGZ1bmN0aW9uKGVsZW0sIG1hdGNoKXsNCgkJCXJldHVybiBlbGVtLm5vZGVUeXBlID09PSAxICYmIGVsZW0uZ2V0QXR0cmlidXRlKCJpZCIpID09PSBtYXRjaDsNCgkJfSwNCgkJVEFHOiBmdW5jdGlvbihlbGVtLCBtYXRjaCl7DQoJCQlyZXR1cm4gKG1hdGNoID09PSAiKiIgJiYgZWxlbS5ub2RlVHlwZSA9PT0gMSkgfHwgZWxlbS5ub2RlTmFtZSA9PT0gbWF0Y2g7DQoJCX0sDQoJCUNMQVNTOiBmdW5jdGlvbihlbGVtLCBtYXRjaCl7DQoJCQlyZXR1cm4gKCIgIiArIChlbGVtLmNsYXNzTmFtZSB8fCBlbGVtLmdldEF0dHJpYnV0ZSgiY2xhc3MiKSkgKyAiICIpDQoJCQkJLmluZGV4T2YoIG1hdGNoICkgPiAtMTsNCgkJfSwNCgkJQVRUUjogZnVuY3Rpb24oZWxlbSwgbWF0Y2gpew0KCQkJdmFyIG5hbWUgPSBtYXRjaFsxXSwNCgkJCQlyZXN1bHQgPSBFeHByLmF0dHJIYW5kbGVbIG5hbWUgXSA/DQoJCQkJCUV4cHIuYXR0ckhhbmRsZVsgbmFtZSBdKCBlbGVtICkgOg0KCQkJCQllbGVtWyBuYW1lIF0gIT0gbnVsbCA/DQoJCQkJCQllbGVtWyBuYW1lIF0gOg0KCQkJCQkJZWxlbS5nZXRBdHRyaWJ1dGUoIG5hbWUgKSwNCgkJCQl2YWx1ZSA9IHJlc3VsdCArICIiLA0KCQkJCXR5cGUgPSBtYXRjaFsyXSwNCgkJCQljaGVjayA9IG1hdGNoWzRdOw0KDQoJCQlyZXR1cm4gcmVzdWx0ID09IG51bGwgPw0KCQkJCXR5cGUgPT09ICIhPSIgOg0KCQkJCXR5cGUgPT09ICI9IiA/DQoJCQkJdmFsdWUgPT09IGNoZWNrIDoNCgkJCQl0eXBlID09PSAiKj0iID8NCgkJCQl2YWx1ZS5pbmRleE9mKGNoZWNrKSA+PSAwIDoNCgkJCQl0eXBlID09PSAifj0iID8NCgkJCQkoIiAiICsgdmFsdWUgKyAiICIpLmluZGV4T2YoY2hlY2spID49IDAgOg0KCQkJCSFjaGVjayA/DQoJCQkJdmFsdWUgJiYgcmVzdWx0ICE9PSBmYWxzZSA6DQoJCQkJdHlwZSA9PT0gIiE9IiA/DQoJCQkJdmFsdWUgIT0gY2hlY2sgOg0KCQkJCXR5cGUgPT09ICJePSIgPw0KCQkJCXZhbHVlLmluZGV4T2YoY2hlY2spID09PSAwIDoNCgkJCQl0eXBlID09PSAiJD0iID8NCgkJCQl2YWx1ZS5zdWJzdHIodmFsdWUubGVuZ3RoIC0gY2hlY2subGVuZ3RoKSA9PT0gY2hlY2sgOg0KCQkJCXR5cGUgPT09ICJ8PSIgPw0KCQkJCXZhbHVlID09PSBjaGVjayB8fCB2YWx1ZS5zdWJzdHIoMCwgY2hlY2subGVuZ3RoICsgMSkgPT09IGNoZWNrICsgIi0iIDoNCgkJCQlmYWxzZTsNCgkJfSwNCgkJUE9TOiBmdW5jdGlvbihlbGVtLCBtYXRjaCwgaSwgYXJyYXkpew0KCQkJdmFyIG5hbWUgPSBtYXRjaFsyXSwgZmlsdGVyID0gRXhwci5zZXRGaWx0ZXJzWyBuYW1lIF07DQoNCgkJCWlmICggZmlsdGVyICkgew0KCQkJCXJldHVybiBmaWx0ZXIoIGVsZW0sIGksIG1hdGNoLCBhcnJheSApOw0KCQkJfQ0KCQl9DQoJfQ0KfTsNCg0KdmFyIG9yaWdQT1MgPSBFeHByLm1hdGNoLlBPUzsNCg0KZm9yICggdmFyIHR5cGUgaW4gRXhwci5tYXRjaCApIHsNCglFeHByLm1hdGNoWyB0eXBlIF0gPSBSZWdFeHAoIEV4cHIubWF0Y2hbIHR5cGUgXS5zb3VyY2UgKyAvKD8hW15cW10qXF0pKD8hW15cKF0qXCkpLy5zb3VyY2UgKTsNCn0NCg0KdmFyIG1ha2VBcnJheSA9IGZ1bmN0aW9uKGFycmF5LCByZXN1bHRzKSB7DQoJYXJyYXkgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbCggYXJyYXkgKTsNCg0KCWlmICggcmVzdWx0cyApIHsNCgkJcmVzdWx0cy5wdXNoLmFwcGx5KCByZXN1bHRzLCBhcnJheSApOw0KCQlyZXR1cm4gcmVzdWx0czsNCgl9DQoJDQoJcmV0dXJuIGFycmF5Ow0KfTsNCg0KLy8gUGVyZm9ybSBhIHNpbXBsZSBjaGVjayB0byBkZXRlcm1pbmUgaWYgdGhlIGJyb3dzZXIgaXMgY2FwYWJsZSBvZg0KLy8gY29udmVydGluZyBhIE5vZGVMaXN0IHRvIGFuIGFycmF5IHVzaW5nIGJ1aWx0aW4gbWV0aG9kcy4NCnRyeSB7DQoJQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5jaGlsZE5vZGVzICk7DQoNCi8vIFByb3ZpZGUgYSBmYWxsYmFjayBtZXRob2QgaWYgaXQgZG9lcyBub3Qgd29yaw0KfSBjYXRjaChlKXsNCgltYWtlQXJyYXkgPSBmdW5jdGlvbihhcnJheSwgcmVzdWx0cykgew0KCQl2YXIgcmV0ID0gcmVzdWx0cyB8fCBbXTsNCg0KCQlpZiAoIHRvU3RyaW5nLmNhbGwoYXJyYXkpID09PSAiW29iamVjdCBBcnJheV0iICkgew0KCQkJQXJyYXkucHJvdG90eXBlLnB1c2guYXBwbHkoIHJldCwgYXJyYXkgKTsNCgkJfSBlbHNlIHsNCgkJCWlmICggdHlwZW9mIGFycmF5Lmxlbmd0aCA9PT0gIm51bWJlciIgKSB7DQoJCQkJZm9yICggdmFyIGkgPSAwLCBsID0gYXJyYXkubGVuZ3RoOyBpIDwgbDsgaSsrICkgew0KCQkJCQlyZXQucHVzaCggYXJyYXlbaV0gKTsNCgkJCQl9DQoJCQl9IGVsc2Ugew0KCQkJCWZvciAoIHZhciBpID0gMDsgYXJyYXlbaV07IGkrKyApIHsNCgkJCQkJcmV0LnB1c2goIGFycmF5W2ldICk7DQoJCQkJfQ0KCQkJfQ0KCQl9DQoNCgkJcmV0dXJuIHJldDsNCgl9Ow0KfQ0KDQp2YXIgc29ydE9yZGVyOw0KDQppZiAoIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5jb21wYXJlRG9jdW1lbnRQb3NpdGlvbiApIHsNCglzb3J0T3JkZXIgPSBmdW5jdGlvbiggYSwgYiApIHsNCgkJdmFyIHJldCA9IGEuY29tcGFyZURvY3VtZW50UG9zaXRpb24oYikgJiA0ID8gLTEgOiBhID09PSBiID8gMCA6IDE7DQoJCWlmICggcmV0ID09PSAwICkgew0KCQkJaGFzRHVwbGljYXRlID0gdHJ1ZTsNCgkJfQ0KCQlyZXR1cm4gcmV0Ow0KCX07DQp9IGVsc2UgaWYgKCAic291cmNlSW5kZXgiIGluIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCApIHsNCglzb3J0T3JkZXIgPSBmdW5jdGlvbiggYSwgYiApIHsNCgkJdmFyIHJldCA9IGEuc291cmNlSW5kZXggLSBiLnNvdXJjZUluZGV4Ow0KCQlpZiAoIHJldCA9PT0gMCApIHsNCgkJCWhhc0R1cGxpY2F0ZSA9IHRydWU7DQoJCX0NCgkJcmV0dXJuIHJldDsNCgl9Ow0KfSBlbHNlIGlmICggZG9jdW1lbnQuY3JlYXRlUmFuZ2UgKSB7DQoJc29ydE9yZGVyID0gZnVuY3Rpb24oIGEsIGIgKSB7DQoJCXZhciBhUmFuZ2UgPSBhLm93bmVyRG9jdW1lbnQuY3JlYXRlUmFuZ2UoKSwgYlJhbmdlID0gYi5vd25lckRvY3VtZW50LmNyZWF0ZVJhbmdlKCk7DQoJCWFSYW5nZS5zZWxlY3ROb2RlKGEpOw0KCQlhUmFuZ2UuY29sbGFwc2UodHJ1ZSk7DQoJCWJSYW5nZS5zZWxlY3ROb2RlKGIpOw0KCQliUmFuZ2UuY29sbGFwc2UodHJ1ZSk7DQoJCXZhciByZXQgPSBhUmFuZ2UuY29tcGFyZUJvdW5kYXJ5UG9pbnRzKFJhbmdlLlNUQVJUX1RPX0VORCwgYlJhbmdlKTsNCgkJaWYgKCByZXQgPT09IDAgKSB7DQoJCQloYXNEdXBsaWNhdGUgPSB0cnVlOw0KCQl9DQoJCXJldHVybiByZXQ7DQoJfTsNCn0NCg0KLy8gW3ZzZG9jXSBUaGUgZm9sbG93aW5nIGZ1bmN0aW9uIGhhcyBiZWVuIG1vZGlmaWVkIGZvciBJbnRlbGxpU2Vuc2UuDQovLyBDaGVjayB0byBzZWUgaWYgdGhlIGJyb3dzZXIgcmV0dXJucyBlbGVtZW50cyBieSBuYW1lIHdoZW4NCi8vIHF1ZXJ5aW5nIGJ5IGdldEVsZW1lbnRCeUlkIChhbmQgcHJvdmlkZSBhIHdvcmthcm91bmQpDQooZnVuY3Rpb24oKXsNCgkvLyBXZSdyZSBnb2luZyB0byBpbmplY3QgYSBmYWtlIGlucHV0IGVsZW1lbnQgd2l0aCBhIHNwZWNpZmllZCBuYW1lDQoJLy8vL3ZhciBmb3JtID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiZm9ybSIpLA0KCS8vLy8JaWQgPSAic2NyaXB0IiArIChuZXcgRGF0ZSkuZ2V0VGltZSgpOw0KCS8vLy9mb3JtLmlubmVySFRNTCA9ICI8aW5wdXQgbmFtZT0nIiArIGlkICsgIicvPiI7DQoNCgkvLyBJbmplY3QgaXQgaW50byB0aGUgcm9vdCBlbGVtZW50LCBjaGVjayBpdHMgc3RhdHVzLCBhbmQgcmVtb3ZlIGl0IHF1aWNrbHkNCgkvLy8vdmFyIHJvb3QgPSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQ7DQoJLy8vL3Jvb3QuaW5zZXJ0QmVmb3JlKCBmb3JtLCByb290LmZpcnN0Q2hpbGQgKTsNCg0KCS8vIFRoZSB3b3JrYXJvdW5kIGhhcyB0byBkbyBhZGRpdGlvbmFsIGNoZWNrcyBhZnRlciBhIGdldEVsZW1lbnRCeUlkDQoJLy8gV2hpY2ggc2xvd3MgdGhpbmdzIGRvd24gZm9yIG90aGVyIGJyb3dzZXJzIChoZW5jZSB0aGUgYnJhbmNoaW5nKQ0KCS8vLy9pZiAoICEhZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoIGlkICkgKSB7DQoJCUV4cHIuZmluZC5JRCA9IGZ1bmN0aW9uKG1hdGNoLCBjb250ZXh0LCBpc1hNTCl7DQoJCQlpZiAoIHR5cGVvZiBjb250ZXh0LmdldEVsZW1lbnRCeUlkICE9PSAidW5kZWZpbmVkIiAmJiAhaXNYTUwgKSB7DQoJCQkJdmFyIG0gPSBjb250ZXh0LmdldEVsZW1lbnRCeUlkKG1hdGNoWzFdKTsNCgkJCQlyZXR1cm4gbSA/IG0uaWQgPT09IG1hdGNoWzFdIHx8IHR5cGVvZiBtLmdldEF0dHJpYnV0ZU5vZGUgIT09ICJ1bmRlZmluZWQiICYmIG0uZ2V0QXR0cmlidXRlTm9kZSgiaWQiKS5ub2RlVmFsdWUgPT09IG1hdGNoWzFdID8gW21dIDogdW5kZWZpbmVkIDogW107DQoJCQl9DQoJCX07DQoNCgkJRXhwci5maWx0ZXIuSUQgPSBmdW5jdGlvbihlbGVtLCBtYXRjaCl7DQoJCQl2YXIgbm9kZSA9IHR5cGVvZiBlbGVtLmdldEF0dHJpYnV0ZU5vZGUgIT09ICJ1bmRlZmluZWQiICYmIGVsZW0uZ2V0QXR0cmlidXRlTm9kZSgiaWQiKTsNCgkJCXJldHVybiBlbGVtLm5vZGVUeXBlID09PSAxICYmIG5vZGUgJiYgbm9kZS5ub2RlVmFsdWUgPT09IG1hdGNoOw0KCQl9Ow0KCS8vLy99DQoNCgkvLy8vcm9vdC5yZW1vdmVDaGlsZCggZm9ybSApOw0KfSkoKTsNCg0KLy8gW3ZzZG9jXSBUaGUgZm9sbG93aW5nIGZ1bmN0aW9uIGhhcyBiZWVuIG1vZGlmaWVkIGZvciBJbnRlbGxpU2Vuc2UuDQooZnVuY3Rpb24oKXsNCgkvLyBDaGVjayB0byBzZWUgaWYgdGhlIGJyb3dzZXIgcmV0dXJucyBvbmx5IGVsZW1lbnRzDQoJLy8gd2hlbiBkb2luZyBnZXRFbGVtZW50c0J5VGFnTmFtZSgiKiIpDQoNCgkvLyBDcmVhdGUgYSBmYWtlIGVsZW1lbnQNCgkvLy8vdmFyIGRpdiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoImRpdiIpOw0KCS8vLy9kaXYuYXBwZW5kQ2hpbGQoIGRvY3VtZW50LmNyZWF0ZUNvbW1lbnQoIiIpICk7DQoNCgkvLyBNYWtlIHN1cmUgbm8gY29tbWVudHMgYXJlIGZvdW5kDQoJLy8vL2lmICggZGl2LmdldEVsZW1lbnRzQnlUYWdOYW1lKCIqIikubGVuZ3RoID4gMCApIHsNCgkJRXhwci5maW5kLlRBRyA9IGZ1bmN0aW9uKG1hdGNoLCBjb250ZXh0KXsNCgkJCXZhciByZXN1bHRzID0gY29udGV4dC5nZXRFbGVtZW50c0J5VGFnTmFtZShtYXRjaFsxXSk7DQoNCgkJCS8vIEZpbHRlciBvdXQgcG9zc2libGUgY29tbWVudHMNCgkJCWlmICggbWF0Y2hbMV0gPT09ICIqIiApIHsNCgkJCQl2YXIgdG1wID0gW107DQoNCgkJCQlmb3IgKCB2YXIgaSA9IDA7IHJlc3VsdHNbaV07IGkrKyApIHsNCgkJCQkJaWYgKCByZXN1bHRzW2ldLm5vZGVUeXBlID09PSAxICkgew0KCQkJCQkJdG1wLnB1c2goIHJlc3VsdHNbaV0gKTsNCgkJCQkJfQ0KCQkJCX0NCg0KCQkJCXJlc3VsdHMgPSB0bXA7DQoJCQl9DQoNCgkJCXJldHVybiByZXN1bHRzOw0KCQl9Ow0KCS8vLy99DQoNCgkvLyBDaGVjayB0byBzZWUgaWYgYW4gYXR0cmlidXRlIHJldHVybnMgbm9ybWFsaXplZCBocmVmIGF0dHJpYnV0ZXMNCgkvLy8vZGl2LmlubmVySFRNTCA9ICI8YSBocmVmPScjJz48L2E+IjsNCgkvLy8vaWYgKCBkaXYuZmlyc3RDaGlsZCAmJiB0eXBlb2YgZGl2LmZpcnN0Q2hpbGQuZ2V0QXR0cmlidXRlICE9PSAidW5kZWZpbmVkIiAmJg0KCS8vLy8JCWRpdi5maXJzdENoaWxkLmdldEF0dHJpYnV0ZSgiaHJlZiIpICE9PSAiIyIgKSB7DQoJCUV4cHIuYXR0ckhhbmRsZS5ocmVmID0gZnVuY3Rpb24oZWxlbSl7DQoJCQlyZXR1cm4gZWxlbS5nZXRBdHRyaWJ1dGUoImhyZWYiLCAyKTsNCgkJfTsNCgkvLy8vfQ0KfSkoKTsNCg0KaWYgKCBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsICkgKGZ1bmN0aW9uKCl7DQoJdmFyIG9sZFNpenpsZSA9IFNpenpsZSwgZGl2ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiZGl2Iik7DQoJZGl2LmlubmVySFRNTCA9ICI8cCBjbGFzcz0nVEVTVCc+PC9wPiI7DQoNCgkvLyBTYWZhcmkgY2FuJ3QgaGFuZGxlIHVwcGVyY2FzZSBvciB1bmljb2RlIGNoYXJhY3RlcnMgd2hlbg0KCS8vIGluIHF1aXJrcyBtb2RlLg0KCWlmICggZGl2LnF1ZXJ5U2VsZWN0b3JBbGwgJiYgZGl2LnF1ZXJ5U2VsZWN0b3JBbGwoIi5URVNUIikubGVuZ3RoID09PSAwICkgew0KCQlyZXR1cm47DQoJfQ0KCQ0KCVNpenpsZSA9IGZ1bmN0aW9uKHF1ZXJ5LCBjb250ZXh0LCBleHRyYSwgc2VlZCl7DQoJCWNvbnRleHQgPSBjb250ZXh0IHx8IGRvY3VtZW50Ow0KDQoJCS8vIE9ubHkgdXNlIHF1ZXJ5U2VsZWN0b3JBbGwgb24gbm9uLVhNTCBkb2N1bWVudHMNCgkJLy8gKElEIHNlbGVjdG9ycyBkb24ndCB3b3JrIGluIG5vbi1IVE1MIGRvY3VtZW50cykNCgkJaWYgKCAhc2VlZCAmJiBjb250ZXh0Lm5vZGVUeXBlID09PSA5ICYmICFpc1hNTChjb250ZXh0KSApIHsNCgkJCXRyeSB7DQoJCQkJcmV0dXJuIG1ha2VBcnJheSggY29udGV4dC5xdWVyeVNlbGVjdG9yQWxsKHF1ZXJ5KSwgZXh0cmEgKTsNCgkJCX0gY2F0Y2goZSl7fQ0KCQl9DQoJCQ0KCQlyZXR1cm4gb2xkU2l6emxlKHF1ZXJ5LCBjb250ZXh0LCBleHRyYSwgc2VlZCk7DQoJfTsNCg0KCVNpenpsZS5maW5kID0gb2xkU2l6emxlLmZpbmQ7DQoJU2l6emxlLmZpbHRlciA9IG9sZFNpenpsZS5maWx0ZXI7DQoJU2l6emxlLnNlbGVjdG9ycyA9IG9sZFNpenpsZS5zZWxlY3RvcnM7DQoJU2l6emxlLm1hdGNoZXMgPSBvbGRTaXp6bGUubWF0Y2hlczsNCn0pKCk7DQoNCmlmICggZG9jdW1lbnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSAmJiBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSApIChmdW5jdGlvbigpew0KCXZhciBkaXYgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJkaXYiKTsNCglkaXYuaW5uZXJIVE1MID0gIjxkaXYgY2xhc3M9J3Rlc3QgZSc+PC9kaXY+PGRpdiBjbGFzcz0ndGVzdCc+PC9kaXY+IjsNCg0KCS8vIE9wZXJhIGNhbid0IGZpbmQgYSBzZWNvbmQgY2xhc3NuYW1lIChpbiA5LjYpDQoJaWYgKCBkaXYuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSgiZSIpLmxlbmd0aCA9PT0gMCApDQoJCXJldHVybjsNCg0KCS8vIFNhZmFyaSBjYWNoZXMgY2xhc3MgYXR0cmlidXRlcywgZG9lc24ndCBjYXRjaCBjaGFuZ2VzIChpbiAzLjIpDQoJZGl2Lmxhc3RDaGlsZC5jbGFzc05hbWUgPSAiZSI7DQoNCglpZiAoIGRpdi5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKCJlIikubGVuZ3RoID09PSAxICkNCgkJcmV0dXJuOw0KDQoJRXhwci5vcmRlci5zcGxpY2UoMSwgMCwgIkNMQVNTIik7DQoJRXhwci5maW5kLkNMQVNTID0gZnVuY3Rpb24obWF0Y2gsIGNvbnRleHQsIGlzWE1MKSB7DQoJCWlmICggdHlwZW9mIGNvbnRleHQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSAhPT0gInVuZGVmaW5lZCIgJiYgIWlzWE1MICkgew0KCQkJcmV0dXJuIGNvbnRleHQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZShtYXRjaFsxXSk7DQoJCX0NCgl9Ow0KfSkoKTsNCg0KZnVuY3Rpb24gZGlyTm9kZUNoZWNrKCBkaXIsIGN1ciwgZG9uZU5hbWUsIGNoZWNrU2V0LCBub2RlQ2hlY2ssIGlzWE1MICkgew0KCXZhciBzaWJEaXIgPSBkaXIgPT0gInByZXZpb3VzU2libGluZyIgJiYgIWlzWE1MOw0KCWZvciAoIHZhciBpID0gMCwgbCA9IGNoZWNrU2V0Lmxlbmd0aDsgaSA8IGw7IGkrKyApIHsNCgkJdmFyIGVsZW0gPSBjaGVja1NldFtpXTsNCgkJaWYgKCBlbGVtICkgew0KCQkJaWYgKCBzaWJEaXIgJiYgZWxlbS5ub2RlVHlwZSA9PT0gMSApew0KCQkJCWVsZW0uc2l6Y2FjaGUgPSBkb25lTmFtZTsNCgkJCQllbGVtLnNpenNldCA9IGk7DQoJCQl9DQoJCQllbGVtID0gZWxlbVtkaXJdOw0KCQkJdmFyIG1hdGNoID0gZmFsc2U7DQoNCgkJCXdoaWxlICggZWxlbSApIHsNCgkJCQlpZiAoIGVsZW0uc2l6Y2FjaGUgPT09IGRvbmVOYW1lICkgew0KCQkJCQltYXRjaCA9IGNoZWNrU2V0W2VsZW0uc2l6c2V0XTsNCgkJCQkJYnJlYWs7DQoJCQkJfQ0KDQoJCQkJaWYgKCBlbGVtLm5vZGVUeXBlID09PSAxICYmICFpc1hNTCApew0KCQkJCQllbGVtLnNpemNhY2hlID0gZG9uZU5hbWU7DQoJCQkJCWVsZW0uc2l6c2V0ID0gaTsNCgkJCQl9DQoNCgkJCQlpZiAoIGVsZW0ubm9kZU5hbWUgPT09IGN1ciApIHsNCgkJCQkJbWF0Y2ggPSBlbGVtOw0KCQkJCQlicmVhazsNCgkJCQl9DQoNCgkJCQllbGVtID0gZWxlbVtkaXJdOw0KCQkJfQ0KDQoJCQljaGVja1NldFtpXSA9IG1hdGNoOw0KCQl9DQoJfQ0KfQ0KDQpmdW5jdGlvbiBkaXJDaGVjayggZGlyLCBjdXIsIGRvbmVOYW1lLCBjaGVja1NldCwgbm9kZUNoZWNrLCBpc1hNTCApIHsNCgl2YXIgc2liRGlyID0gZGlyID09ICJwcmV2aW91c1NpYmxpbmciICYmICFpc1hNTDsNCglmb3IgKCB2YXIgaSA9IDAsIGwgPSBjaGVja1NldC5sZW5ndGg7IGkgPCBsOyBpKysgKSB7DQoJCXZhciBlbGVtID0gY2hlY2tTZXRbaV07DQoJCWlmICggZWxlbSApIHsNCgkJCWlmICggc2liRGlyICYmIGVsZW0ubm9kZVR5cGUgPT09IDEgKSB7DQoJCQkJZWxlbS5zaXpjYWNoZSA9IGRvbmVOYW1lOw0KCQkJCWVsZW0uc2l6c2V0ID0gaTsNCgkJCX0NCgkJCWVsZW0gPSBlbGVtW2Rpcl07DQoJCQl2YXIgbWF0Y2ggPSBmYWxzZTsNCg0KCQkJd2hpbGUgKCBlbGVtICkgew0KCQkJCWlmICggZWxlbS5zaXpjYWNoZSA9PT0gZG9uZU5hbWUgKSB7DQoJCQkJCW1hdGNoID0gY2hlY2tTZXRbZWxlbS5zaXpzZXRdOw0KCQkJCQlicmVhazsNCgkJCQl9DQoNCgkJCQlpZiAoIGVsZW0ubm9kZVR5cGUgPT09IDEgKSB7DQoJCQkJCWlmICggIWlzWE1MICkgew0KCQkJCQkJZWxlbS5zaXpjYWNoZSA9IGRvbmVOYW1lOw0KCQkJCQkJZWxlbS5zaXpzZXQgPSBpOw0KCQkJCQl9DQoJCQkJCWlmICggdHlwZW9mIGN1ciAhPT0gInN0cmluZyIgKSB7DQoJCQkJCQlpZiAoIGVsZW0gPT09IGN1ciApIHsNCgkJCQkJCQltYXRjaCA9IHRydWU7DQoJCQkJCQkJYnJlYWs7DQoJCQkJCQl9DQoNCgkJCQkJfSBlbHNlIGlmICggU2l6emxlLmZpbHRlciggY3VyLCBbZWxlbV0gKS5sZW5ndGggPiAwICkgew0KCQkJCQkJbWF0Y2ggPSBlbGVtOw0KCQkJCQkJYnJlYWs7DQoJCQkJCX0NCgkJCQl9DQoNCgkJCQllbGVtID0gZWxlbVtkaXJdOw0KCQkJfQ0KDQoJCQljaGVja1NldFtpXSA9IG1hdGNoOw0KCQl9DQoJfQ0KfQ0KDQp2YXIgY29udGFpbnMgPSBkb2N1bWVudC5jb21wYXJlRG9jdW1lbnRQb3NpdGlvbiA/ICBmdW5jdGlvbihhLCBiKXsNCglyZXR1cm4gYS5jb21wYXJlRG9jdW1lbnRQb3NpdGlvbihiKSAmIDE2Ow0KfSA6IGZ1bmN0aW9uKGEsIGIpew0KCXJldHVybiBhICE9PSBiICYmIChhLmNvbnRhaW5zID8gYS5jb250YWlucyhiKSA6IHRydWUpOw0KfTsNCg0KdmFyIGlzWE1MID0gZnVuY3Rpb24oZWxlbSl7DQoJcmV0dXJuIGVsZW0ubm9kZVR5cGUgPT09IDkgJiYgZWxlbS5kb2N1bWVudEVsZW1lbnQubm9kZU5hbWUgIT09ICJIVE1MIiB8fA0KCQkhIWVsZW0ub3duZXJEb2N1bWVudCAmJiBpc1hNTCggZWxlbS5vd25lckRvY3VtZW50ICk7DQp9Ow0KDQp2YXIgcG9zUHJvY2VzcyA9IGZ1bmN0aW9uKHNlbGVjdG9yLCBjb250ZXh0KXsNCgl2YXIgdG1wU2V0ID0gW10sIGxhdGVyID0gIiIsIG1hdGNoLA0KCQlyb290ID0gY29udGV4dC5ub2RlVHlwZSA/IFtjb250ZXh0XSA6IGNvbnRleHQ7DQoNCgkvLyBQb3NpdGlvbiBzZWxlY3RvcnMgbXVzdCBiZSBkb25lIGFmdGVyIHRoZSBmaWx0ZXINCgkvLyBBbmQgc28gbXVzdCA6bm90KHBvc2l0aW9uYWwpIHNvIHdlIG1vdmUgYWxsIFBTRVVET3MgdG8gdGhlIGVuZA0KCXdoaWxlICggKG1hdGNoID0gRXhwci5tYXRjaC5QU0VVRE8uZXhlYyggc2VsZWN0b3IgKSkgKSB7DQoJCWxhdGVyICs9IG1hdGNoWzBdOw0KCQlzZWxlY3RvciA9IHNlbGVjdG9yLnJlcGxhY2UoIEV4cHIubWF0Y2guUFNFVURPLCAiIiApOw0KCX0NCg0KCXNlbGVjdG9yID0gRXhwci5yZWxhdGl2ZVtzZWxlY3Rvcl0gPyBzZWxlY3RvciArICIqIiA6IHNlbGVjdG9yOw0KDQoJZm9yICggdmFyIGkgPSAwLCBsID0gcm9vdC5sZW5ndGg7IGkgPCBsOyBpKysgKSB7DQoJCVNpenpsZSggc2VsZWN0b3IsIHJvb3RbaV0sIHRtcFNldCApOw0KCX0NCg0KCXJldHVybiBTaXp6bGUuZmlsdGVyKCBsYXRlciwgdG1wU2V0ICk7DQp9Ow0KDQovLyBFWFBPU0UNCmpRdWVyeS5maW5kID0gU2l6emxlOw0KalF1ZXJ5LmZpbHRlciA9IFNpenpsZS5maWx0ZXI7DQpqUXVlcnkuZXhwciA9IFNpenpsZS5zZWxlY3RvcnM7DQpqUXVlcnkuZXhwclsiOiJdID0galF1ZXJ5LmV4cHIuZmlsdGVyczsNCg0KU2l6emxlLnNlbGVjdG9ycy5maWx0ZXJzLmhpZGRlbiA9IGZ1bmN0aW9uKGVsZW0pew0KCXJldHVybiBlbGVtLm9mZnNldFdpZHRoID09PSAwIHx8IGVsZW0ub2Zmc2V0SGVpZ2h0ID09PSAwOw0KfTsNCg0KU2l6emxlLnNlbGVjdG9ycy5maWx0ZXJzLnZpc2libGUgPSBmdW5jdGlvbihlbGVtKXsNCglyZXR1cm4gZWxlbS5vZmZzZXRXaWR0aCA+IDAgfHwgZWxlbS5vZmZzZXRIZWlnaHQgPiAwOw0KfTsNCg0KU2l6emxlLnNlbGVjdG9ycy5maWx0ZXJzLmFuaW1hdGVkID0gZnVuY3Rpb24oZWxlbSl7DQoJcmV0dXJuIGpRdWVyeS5ncmVwKGpRdWVyeS50aW1lcnMsIGZ1bmN0aW9uKGZuKXsNCgkJcmV0dXJuIGVsZW0gPT09IGZuLmVsZW07DQoJfSkubGVuZ3RoOw0KfTsNCg0KalF1ZXJ5Lm11bHRpRmlsdGVyID0gZnVuY3Rpb24oIGV4cHIsIGVsZW1zLCBub3QgKSB7DQoJLy8vCTxzdW1tYXJ5Pg0KCS8vLwkJVGhpcyBtZW1iZXIgaXMgaW50ZXJuYWwgb25seS4NCgkvLy8JPC9zdW1tYXJ5Pg0KCS8vLwk8cHJpdmF0ZSAvPg0KDQoJaWYgKCBub3QgKSB7DQoJCWV4cHIgPSAiOm5vdCgiICsgZXhwciArICIpIjsNCgl9DQoNCglyZXR1cm4gU2l6emxlLm1hdGNoZXMoZXhwciwgZWxlbXMpOw0KfTsNCg0KalF1ZXJ5LmRpciA9IGZ1bmN0aW9uKCBlbGVtLCBkaXIgKXsNCgkvLy8JPHN1bW1hcnk+DQoJLy8vCQlUaGlzIG1lbWJlciBpcyBpbnRlcm5hbCBvbmx5Lg0KCS8vLwk8L3N1bW1hcnk+DQoJLy8vCTxwcml2YXRlIC8+DQoJLy8gVGhpcyBtZW1iZXIgaXMgbm90IGRvY3VtZW50ZWQgaW4gdGhlIGpRdWVyeSBBUEk6IGh0dHA6Ly9kb2NzLmpxdWVyeS5jb20vU3BlY2lhbDpTZWFyY2g/bnMwPTEmc2VhcmNoPWRpcg0KCXZhciBtYXRjaGVkID0gW10sIGN1ciA9IGVsZW1bZGlyXTsNCgl3aGlsZSAoIGN1ciAmJiBjdXIgIT0gZG9jdW1lbnQgKSB7DQoJCWlmICggY3VyLm5vZGVUeXBlID09IDEgKQ0KCQkJbWF0Y2hlZC5wdXNoKCBjdXIgKTsNCgkJY3VyID0gY3VyW2Rpcl07DQoJfQ0KCXJldHVybiBtYXRjaGVkOw0KfTsNCg0KalF1ZXJ5Lm50aCA9IGZ1bmN0aW9uKGN1ciwgcmVzdWx0LCBkaXIsIGVsZW0pew0KCS8vLwk8c3VtbWFyeT4NCgkvLy8JCVRoaXMgbWVtYmVyIGlzIGludGVybmFsIG9ubHkuDQoJLy8vCTwvc3VtbWFyeT4NCgkvLy8JPHByaXZhdGUgLz4NCgkvLyBUaGlzIG1lbWJlciBpcyBub3QgZG9jdW1lbnRlZCBpbiB0aGUgalF1ZXJ5IEFQSTogaHR0cDovL2RvY3MuanF1ZXJ5LmNvbS9TcGVjaWFsOlNlYXJjaD9uczA9MSZzZWFyY2g9bnRoDQoJcmVzdWx0ID0gcmVzdWx0IHx8IDE7DQoJdmFyIG51bSA9IDA7DQoNCglmb3IgKCA7IGN1cjsgY3VyID0gY3VyW2Rpcl0gKQ0KCQlpZiAoIGN1ci5ub2RlVHlwZSA9PSAxICYmICsrbnVtID09IHJlc3VsdCApDQoJCQlicmVhazsNCg0KCXJldHVybiBjdXI7DQp9Ow0KDQpqUXVlcnkuc2libGluZyA9IGZ1bmN0aW9uKG4sIGVsZW0pew0KCS8vLwk8c3VtbWFyeT4NCgkvLy8JCVRoaXMgbWVtYmVyIGlzIGludGVybmFsIG9ubHkuDQoJLy8vCTwvc3VtbWFyeT4NCgkvLy8JPHByaXZhdGUgLz4NCgkvLyBUaGlzIG1lbWJlciBpcyBub3QgZG9jdW1lbnRlZCBpbiB0aGUgalF1ZXJ5IEFQSTogaHR0cDovL2RvY3MuanF1ZXJ5LmNvbS9TcGVjaWFsOlNlYXJjaD9uczA9MSZzZWFyY2g9bnRoDQoJdmFyIHIgPSBbXTsNCg0KCWZvciAoIDsgbjsgbiA9IG4ubmV4dFNpYmxpbmcgKSB7DQoJCWlmICggbi5ub2RlVHlwZSA9PSAxICYmIG4gIT0gZWxlbSApDQoJCQlyLnB1c2goIG4gKTsNCgl9DQoNCglyZXR1cm4gcjsNCn07DQoNCnJldHVybjsNCg0Kd2luZG93LlNpenpsZSA9IFNpenpsZTsNCg0KfSkoKTsNCi8qDQogKiBBIG51bWJlciBvZiBoZWxwZXIgZnVuY3Rpb25zIHVzZWQgZm9yIG1hbmFnaW5nIGV2ZW50cy4NCiAqIE1hbnkgb2YgdGhlIGlkZWFzIGJlaGluZCB0aGlzIGNvZGUgb3JpZ2luYXRlZCBmcm9tDQogKiBEZWFuIEVkd2FyZHMnIGFkZEV2ZW50IGxpYnJhcnkuDQogKi8NCmpRdWVyeS5ldmVudCA9IHsNCg0KCS8vIEJpbmQgYW4gZXZlbnQgdG8gYW4gZWxlbWVudA0KCS8vIE9yaWdpbmFsIGJ5IERlYW4gRWR3YXJkcw0KCWFkZDogZnVuY3Rpb24oZWxlbSwgdHlwZXMsIGhhbmRsZXIsIGRhdGEpIHsNCgkJLy8vCTxzdW1tYXJ5Pg0KCQkvLy8JCVRoaXMgbWV0aG9kIGlzIGludGVybmFsLg0KCQkvLy8JPC9zdW1tYXJ5Pg0KCQkvLy8JPHByaXZhdGUgLz4NCgkJaWYgKCBlbGVtLm5vZGVUeXBlID09IDMgfHwgZWxlbS5ub2RlVHlwZSA9PSA4ICkNCgkJCXJldHVybjsNCg0KCQkvLyBGb3Igd2hhdGV2ZXIgcmVhc29uLCBJRSBoYXMgdHJvdWJsZSBwYXNzaW5nIHRoZSB3aW5kb3cgb2JqZWN0DQoJCS8vIGFyb3VuZCwgY2F1c2luZyBpdCB0byBiZSBjbG9uZWQgaW4gdGhlIHByb2Nlc3MNCgkJaWYgKCBlbGVtLnNldEludGVydmFsICYmIGVsZW0gIT0gd2luZG93ICkNCgkJCWVsZW0gPSB3aW5kb3c7DQoNCgkJLy8gTWFrZSBzdXJlIHRoYXQgdGhlIGZ1bmN0aW9uIGJlaW5nIGV4ZWN1dGVkIGhhcyBhIHVuaXF1ZSBJRA0KCQlpZiAoICFoYW5kbGVyLmd1aWQgKQ0KCQkJaGFuZGxlci5ndWlkID0gdGhpcy5ndWlkKys7DQoNCgkJLy8gaWYgZGF0YSBpcyBwYXNzZWQsIGJpbmQgdG8gaGFuZGxlcg0KCQlpZiAoIGRhdGEgIT09IHVuZGVmaW5lZCApIHsNCgkJCS8vIENyZWF0ZSB0ZW1wb3JhcnkgZnVuY3Rpb24gcG9pbnRlciB0byBvcmlnaW5hbCBoYW5kbGVyDQoJCQl2YXIgZm4gPSBoYW5kbGVyOw0KDQoJCQkvLyBDcmVhdGUgdW5pcXVlIGhhbmRsZXIgZnVuY3Rpb24sIHdyYXBwZWQgYXJvdW5kIG9yaWdpbmFsIGhhbmRsZXINCgkJCWhhbmRsZXIgPSB0aGlzLnByb3h5KCBmbiApOw0KDQoJCQkvLyBTdG9yZSBkYXRhIGluIHVuaXF1ZSBoYW5kbGVyDQoJCQloYW5kbGVyLmRhdGEgPSBkYXRhOw0KCQl9DQoNCgkJLy8gSW5pdCB0aGUgZWxlbWVudCdzIGV2ZW50IHN0cnVjdHVyZQ0KCQl2YXIgZXZlbnRzID0galF1ZXJ5LmRhdGEoZWxlbSwgImV2ZW50cyIpIHx8IGpRdWVyeS5kYXRhKGVsZW0sICJldmVudHMiLCB7fSksDQoJCQloYW5kbGUgPSBqUXVlcnkuZGF0YShlbGVtLCAiaGFuZGxlIikgfHwgalF1ZXJ5LmRhdGEoZWxlbSwgImhhbmRsZSIsIGZ1bmN0aW9uKCl7DQoJCQkJLy8gSGFuZGxlIHRoZSBzZWNvbmQgZXZlbnQgb2YgYSB0cmlnZ2VyIGFuZCB3aGVuDQoJCQkJLy8gYW4gZXZlbnQgaXMgY2FsbGVkIGFmdGVyIGEgcGFnZSBoYXMgdW5sb2FkZWQNCgkJCQlyZXR1cm4gdHlwZW9mIGpRdWVyeSAhPT0gInVuZGVmaW5lZCIgJiYgIWpRdWVyeS5ldmVudC50cmlnZ2VyZWQgPw0KCQkJCQlqUXVlcnkuZXZlbnQuaGFuZGxlLmFwcGx5KGFyZ3VtZW50cy5jYWxsZWUuZWxlbSwgYXJndW1lbnRzKSA6DQoJCQkJCXVuZGVmaW5lZDsNCgkJCX0pOw0KCQkvLyBBZGQgZWxlbSBhcyBhIHByb3BlcnR5IG9mIHRoZSBoYW5kbGUgZnVuY3Rpb24NCgkJLy8gVGhpcyBpcyB0byBwcmV2ZW50IGEgbWVtb3J5IGxlYWsgd2l0aCBub24tbmF0aXZlDQoJCS8vIGV2ZW50IGluIElFLg0KCQloYW5kbGUuZWxlbSA9IGVsZW07DQoNCgkJLy8gSGFuZGxlIG11bHRpcGxlIGV2ZW50cyBzZXBhcmF0ZWQgYnkgYSBzcGFjZQ0KCQkvLyBqUXVlcnkoLi4uKS5iaW5kKCJtb3VzZW92ZXIgbW91c2VvdXQiLCBmbik7DQoJCWpRdWVyeS5lYWNoKHR5cGVzLnNwbGl0KC9ccysvKSwgZnVuY3Rpb24oaW5kZXgsIHR5cGUpIHsNCgkJCS8vIE5hbWVzcGFjZWQgZXZlbnQgaGFuZGxlcnMNCgkJCXZhciBuYW1lc3BhY2VzID0gdHlwZS5zcGxpdCgiLiIpOw0KCQkJdHlwZSA9IG5hbWVzcGFjZXMuc2hpZnQoKTsNCgkJCWhhbmRsZXIudHlwZSA9IG5hbWVzcGFjZXMuc2xpY2UoKS5zb3J0KCkuam9pbigiLiIpOw0KDQoJCQkvLyBHZXQgdGhlIGN1cnJlbnQgbGlzdCBvZiBmdW5jdGlvbnMgYm91bmQgdG8gdGhpcyBldmVudA0KCQkJdmFyIGhhbmRsZXJzID0gZXZlbnRzW3R5cGVdOw0KCQkJDQoJCQlpZiAoIGpRdWVyeS5ldmVudC5zcGVjaWFsQWxsW3R5cGVdICkNCgkJCQlqUXVlcnkuZXZlbnQuc3BlY2lhbEFsbFt0eXBlXS5zZXR1cC5jYWxsKGVsZW0sIGRhdGEsIG5hbWVzcGFjZXMpOw0KDQoJCQkvLyBJbml0IHRoZSBldmVudCBoYW5kbGVyIHF1ZXVlDQoJCQlpZiAoIWhhbmRsZXJzKSB7DQoJCQkJaGFuZGxlcnMgPSBldmVudHNbdHlwZV0gPSB7fTsNCg0KCQkJCS8vIENoZWNrIGZvciBhIHNwZWNpYWwgZXZlbnQgaGFuZGxlcg0KCQkJCS8vIE9ubHkgdXNlIGFkZEV2ZW50TGlzdGVuZXIvYXR0YWNoRXZlbnQgaWYgdGhlIHNwZWNpYWwNCgkJCQkvLyBldmVudHMgaGFuZGxlciByZXR1cm5zIGZhbHNlDQoJCQkJaWYgKCAhalF1ZXJ5LmV2ZW50LnNwZWNpYWxbdHlwZV0gfHwgalF1ZXJ5LmV2ZW50LnNwZWNpYWxbdHlwZV0uc2V0dXAuY2FsbChlbGVtLCBkYXRhLCBuYW1lc3BhY2VzKSA9PT0gZmFsc2UgKSB7DQoJCQkJCS8vIEJpbmQgdGhlIGdsb2JhbCBldmVudCBoYW5kbGVyIHRvIHRoZSBlbGVtZW50DQoJCQkJCWlmIChlbGVtLmFkZEV2ZW50TGlzdGVuZXIpDQoJCQkJCQllbGVtLmFkZEV2ZW50TGlzdGVuZXIodHlwZSwgaGFuZGxlLCBmYWxzZSk7DQoJCQkJCWVsc2UgaWYgKGVsZW0uYXR0YWNoRXZlbnQpDQoJCQkJCQllbGVtLmF0dGFjaEV2ZW50KCJvbiIgKyB0eXBlLCBoYW5kbGUpOw0KCQkJCX0NCgkJCX0NCg0KCQkJLy8gQWRkIHRoZSBmdW5jdGlvbiB0byB0aGUgZWxlbWVudCdzIGhhbmRsZXIgbGlzdA0KCQkJaGFuZGxlcnNbaGFuZGxlci5ndWlkXSA9IGhhbmRsZXI7DQoNCgkJCS8vIEtlZXAgdHJhY2sgb2Ygd2hpY2ggZXZlbnRzIGhhdmUgYmVlbiB1c2VkLCBmb3IgZ2xvYmFsIHRyaWdnZXJpbmcNCgkJCWpRdWVyeS5ldmVudC5nbG9iYWxbdHlwZV0gPSB0cnVlOw0KCQl9KTsNCg0KCQkvLyBOdWxsaWZ5IGVsZW0gdG8gcHJldmVudCBtZW1vcnkgbGVha3MgaW4gSUUNCgkJZWxlbSA9IG51bGw7DQoJfSwNCg0KCWd1aWQ6IDEsDQoJZ2xvYmFsOiB7fSwNCg0KCS8vIERldGFjaCBhbiBldmVudCBvciBzZXQgb2YgZXZlbnRzIGZyb20gYW4gZWxlbWVudA0KCXJlbW92ZTogZnVuY3Rpb24oZWxlbSwgdHlwZXMsIGhhbmRsZXIpIHsNCgkJLy8vCTxzdW1tYXJ5Pg0KCQkvLy8JCVRoaXMgbWV0aG9kIGlzIGludGVybmFsLg0KCQkvLy8JPC9zdW1tYXJ5Pg0KCQkvLy8JPHByaXZhdGUgLz4NCgkJDQoJCS8vIGRvbid0IGRvIGV2ZW50cyBvbiB0ZXh0IGFuZCBjb21tZW50IG5vZGVzDQoJCWlmICggZWxlbS5ub2RlVHlwZSA9PSAzIHx8IGVsZW0ubm9kZVR5cGUgPT0gOCApDQoJCQlyZXR1cm47DQoNCgkJdmFyIGV2ZW50cyA9IGpRdWVyeS5kYXRhKGVsZW0sICJldmVudHMiKSwgcmV0LCBpbmRleDsNCg0KCQlpZiAoIGV2ZW50cyApIHsNCgkJCS8vIFVuYmluZCBhbGwgZXZlbnRzIGZvciB0aGUgZWxlbWVudA0KCQkJaWYgKCB0eXBlcyA9PT0gdW5kZWZpbmVkIHx8ICh0eXBlb2YgdHlwZXMgPT09ICJzdHJpbmciICYmIHR5cGVzLmNoYXJBdCgwKSA9PSAiLiIpICkNCgkJCQlmb3IgKCB2YXIgdHlwZSBpbiBldmVudHMgKQ0KCQkJCQl0aGlzLnJlbW92ZSggZWxlbSwgdHlwZSArICh0eXBlcyB8fCAiIikgKTsNCgkJCWVsc2Ugew0KCQkJCS8vIHR5cGVzIGlzIGFjdHVhbGx5IGFuIGV2ZW50IG9iamVjdCBoZXJlDQoJCQkJaWYgKCB0eXBlcy50eXBlICkgew0KCQkJCQloYW5kbGVyID0gdHlwZXMuaGFuZGxlcjsNCgkJCQkJdHlwZXMgPSB0eXBlcy50eXBlOw0KCQkJCX0NCg0KCQkJCS8vIEhhbmRsZSBtdWx0aXBsZSBldmVudHMgc2VwZXJhdGVkIGJ5IGEgc3BhY2UNCgkJCQkvLyBqUXVlcnkoLi4uKS51bmJpbmQoIm1vdXNlb3ZlciBtb3VzZW91dCIsIGZuKTsNCgkJCQlqUXVlcnkuZWFjaCh0eXBlcy5zcGxpdCgvXHMrLyksIGZ1bmN0aW9uKGluZGV4LCB0eXBlKXsNCgkJCQkJLy8gTmFtZXNwYWNlZCBldmVudCBoYW5kbGVycw0KCQkJCQl2YXIgbmFtZXNwYWNlcyA9IHR5cGUuc3BsaXQoIi4iKTsNCgkJCQkJdHlwZSA9IG5hbWVzcGFjZXMuc2hpZnQoKTsNCgkJCQkJdmFyIG5hbWVzcGFjZSA9IFJlZ0V4cCgiKF58XFwuKSIgKyBuYW1lc3BhY2VzLnNsaWNlKCkuc29ydCgpLmpvaW4oIi4qXFwuIikgKyAiKFxcLnwkKSIpOw0KDQoJCQkJCWlmICggZXZlbnRzW3R5cGVdICkgew0KCQkJCQkJLy8gcmVtb3ZlIHRoZSBnaXZlbiBoYW5kbGVyIGZvciB0aGUgZ2l2ZW4gdHlwZQ0KCQkJCQkJaWYgKCBoYW5kbGVyICkNCgkJCQkJCQlkZWxldGUgZXZlbnRzW3R5cGVdW2hhbmRsZXIuZ3VpZF07DQoNCgkJCQkJCS8vIHJlbW92ZSBhbGwgaGFuZGxlcnMgZm9yIHRoZSBnaXZlbiB0eXBlDQoJCQkJCQllbHNlDQoJCQkJCQkJZm9yICggdmFyIGhhbmRsZSBpbiBldmVudHNbdHlwZV0gKQ0KCQkJCQkJCQkvLyBIYW5kbGUgdGhlIHJlbW92YWwgb2YgbmFtZXNwYWNlZCBldmVudHMNCgkJCQkJCQkJaWYgKCBuYW1lc3BhY2UudGVzdChldmVudHNbdHlwZV1baGFuZGxlXS50eXBlKSApDQoJCQkJCQkJCQlkZWxldGUgZXZlbnRzW3R5cGVdW2hhbmRsZV07DQoJCQkJCQkJCQkNCgkJCQkJCWlmICggalF1ZXJ5LmV2ZW50LnNwZWNpYWxBbGxbdHlwZV0gKQ0KCQkJCQkJCWpRdWVyeS5ldmVudC5zcGVjaWFsQWxsW3R5cGVdLnRlYXJkb3duLmNhbGwoZWxlbSwgbmFtZXNwYWNlcyk7DQoNCgkJCQkJCS8vIHJlbW92ZSBnZW5lcmljIGV2ZW50IGhhbmRsZXIgaWYgbm8gbW9yZSBoYW5kbGVycyBleGlzdA0KCQkJCQkJZm9yICggcmV0IGluIGV2ZW50c1t0eXBlXSApIGJyZWFrOw0KCQkJCQkJaWYgKCAhcmV0ICkgew0KCQkJCQkJCWlmICggIWpRdWVyeS5ldmVudC5zcGVjaWFsW3R5cGVdIHx8IGpRdWVyeS5ldmVudC5zcGVjaWFsW3R5cGVdLnRlYXJkb3duLmNhbGwoZWxlbSwgbmFtZXNwYWNlcykgPT09IGZhbHNlICkgew0KCQkJCQkJCQlpZiAoZWxlbS5yZW1vdmVFdmVudExpc3RlbmVyKQ0KCQkJCQkJCQkJZWxlbS5yZW1vdmVFdmVudExpc3RlbmVyKHR5cGUsIGpRdWVyeS5kYXRhKGVsZW0sICJoYW5kbGUiKSwgZmFsc2UpOw0KCQkJCQkJCQllbHNlIGlmIChlbGVtLmRldGFjaEV2ZW50KQ0KCQkJCQkJCQkJZWxlbS5kZXRhY2hFdmVudCgib24iICsgdHlwZSwgalF1ZXJ5LmRhdGEoZWxlbSwgImhhbmRsZSIpKTsNCgkJCQkJCQl9DQoJCQkJCQkJcmV0ID0gbnVsbDsNCgkJCQkJCQlkZWxldGUgZXZlbnRzW3R5cGVdOw0KCQkJCQkJfQ0KCQkJCQl9DQoJCQkJfSk7DQoJCQl9DQoNCgkJCS8vIFJlbW92ZSB0aGUgZXhwYW5kbyBpZiBpdCdzIG5vIGxvbmdlciB1c2VkDQoJCQlmb3IgKCByZXQgaW4gZXZlbnRzICkgYnJlYWs7DQoJCQlpZiAoICFyZXQgKSB7DQoJCQkJdmFyIGhhbmRsZSA9IGpRdWVyeS5kYXRhKCBlbGVtLCAiaGFuZGxlIiApOw0KCQkJCWlmICggaGFuZGxlICkgaGFuZGxlLmVsZW0gPSBudWxsOw0KCQkJCWpRdWVyeS5yZW1vdmVEYXRhKCBlbGVtLCAiZXZlbnRzIiApOw0KCQkJCWpRdWVyeS5yZW1vdmVEYXRhKCBlbGVtLCAiaGFuZGxlIiApOw0KCQkJfQ0KCQl9DQoJfSwNCg0KCS8vIGJ1YmJsaW5nIGlzIGludGVybmFsDQoJdHJpZ2dlcjogZnVuY3Rpb24oIGV2ZW50LCBkYXRhLCBlbGVtLCBidWJibGluZyApIHsNCgkJLy8vCTxzdW1tYXJ5Pg0KCQkvLy8JCVRoaXMgbWV0aG9kIGlzIGludGVybmFsLg0KCQkvLy8JPC9zdW1tYXJ5Pg0KCQkvLy8JPHByaXZhdGUgLz4NCgkJDQoJCS8vIEV2ZW50IG9iamVjdCBvciBldmVudCB0eXBlDQoJCXZhciB0eXBlID0gZXZlbnQudHlwZSB8fCBldmVudDsNCg0KCQlpZiggIWJ1YmJsaW5nICl7DQoJCQlldmVudCA9IHR5cGVvZiBldmVudCA9PT0gIm9iamVjdCIgPw0KCQkJCS8vIGpRdWVyeS5FdmVudCBvYmplY3QNCgkJCQlldmVudFtleHBhbmRvXSA/IGV2ZW50IDoNCgkJCQkvLyBPYmplY3QgbGl0ZXJhbA0KCQkJCWpRdWVyeS5leHRlbmQoIGpRdWVyeS5FdmVudCh0eXBlKSwgZXZlbnQgKSA6DQoJCQkJLy8gSnVzdCB0aGUgZXZlbnQgdHlwZSAoc3RyaW5nKQ0KCQkJCWpRdWVyeS5FdmVudCh0eXBlKTsNCg0KCQkJaWYgKCB0eXBlLmluZGV4T2YoIiEiKSA+PSAwICkgew0KCQkJCWV2ZW50LnR5cGUgPSB0eXBlID0gdHlwZS5zbGljZSgwLCAtMSk7DQoJCQkJZXZlbnQuZXhjbHVzaXZlID0gdHJ1ZTsNCgkJCX0NCg0KCQkJLy8gSGFuZGxlIGEgZ2xvYmFsIHRyaWdnZXINCgkJCWlmICggIWVsZW0gKSB7DQoJCQkJLy8gRG9uJ3QgYnViYmxlIGN1c3RvbSBldmVudHMgd2hlbiBnbG9iYWwgKHRvIGF2b2lkIHRvbyBtdWNoIG92ZXJoZWFkKQ0KCQkJCWV2ZW50LnN0b3BQcm9wYWdhdGlvbigpOw0KCQkJCS8vIE9ubHkgdHJpZ2dlciBpZiB3ZSd2ZSBldmVyIGJvdW5kIGFuIGV2ZW50IGZvciBpdA0KCQkJCWlmICggdGhpcy5nbG9iYWxbdHlwZV0gKQ0KCQkJCQlqUXVlcnkuZWFjaCggalF1ZXJ5LmNhY2hlLCBmdW5jdGlvbigpew0KCQkJCQkJaWYgKCB0aGlzLmV2ZW50cyAmJiB0aGlzLmV2ZW50c1t0eXBlXSApDQoJCQkJCQkJalF1ZXJ5LmV2ZW50LnRyaWdnZXIoIGV2ZW50LCBkYXRhLCB0aGlzLmhhbmRsZS5lbGVtICk7DQoJCQkJCX0pOw0KCQkJfQ0KDQoJCQkvLyBIYW5kbGUgdHJpZ2dlcmluZyBhIHNpbmdsZSBlbGVtZW50DQoNCgkJCS8vIGRvbid0IGRvIGV2ZW50cyBvbiB0ZXh0IGFuZCBjb21tZW50IG5vZGVzDQoJCQlpZiAoICFlbGVtIHx8IGVsZW0ubm9kZVR5cGUgPT0gMyB8fCBlbGVtLm5vZGVUeXBlID09IDggKQ0KCQkJCXJldHVybiB1bmRlZmluZWQ7DQoJCQkNCgkJCS8vIENsZWFuIHVwIGluIGNhc2UgaXQgaXMgcmV1c2VkDQoJCQlldmVudC5yZXN1bHQgPSB1bmRlZmluZWQ7DQoJCQlldmVudC50YXJnZXQgPSBlbGVtOw0KCQkJDQoJCQkvLyBDbG9uZSB0aGUgaW5jb21pbmcgZGF0YSwgaWYgYW55DQoJCQlkYXRhID0galF1ZXJ5Lm1ha2VBcnJheShkYXRhKTsNCgkJCWRhdGEudW5zaGlmdCggZXZlbnQgKTsNCgkJfQ0KDQoJCWV2ZW50LmN1cnJlbnRUYXJnZXQgPSBlbGVtOw0KDQoJCS8vIFRyaWdnZXIgdGhlIGV2ZW50LCBpdCBpcyBhc3N1bWVkIHRoYXQgImhhbmRsZSIgaXMgYSBmdW5jdGlvbg0KCQl2YXIgaGFuZGxlID0galF1ZXJ5LmRhdGEoZWxlbSwgImhhbmRsZSIpOw0KCQlpZiAoIGhhbmRsZSApDQoJCQloYW5kbGUuYXBwbHkoIGVsZW0sIGRhdGEgKTsNCg0KCQkvLyBIYW5kbGUgdHJpZ2dlcmluZyBuYXRpdmUgLm9uZm9vIGhhbmRsZXJzIChhbmQgb24gbGlua3Mgc2luY2Ugd2UgZG9uJ3QgY2FsbCAuY2xpY2soKSBmb3IgbGlua3MpDQoJCWlmICggKCFlbGVtW3R5cGVdIHx8IChqUXVlcnkubm9kZU5hbWUoZWxlbSwgJ2EnKSAmJiB0eXBlID09ICJjbGljayIpKSAmJiBlbGVtWyJvbiIrdHlwZV0gJiYgZWxlbVsib24iK3R5cGVdLmFwcGx5KCBlbGVtLCBkYXRhICkgPT09IGZhbHNlICkNCgkJCWV2ZW50LnJlc3VsdCA9IGZhbHNlOw0KDQoJCS8vIFRyaWdnZXIgdGhlIG5hdGl2ZSBldmVudHMgKGV4Y2VwdCBmb3IgY2xpY2tzIG9uIGxpbmtzKQ0KCQlpZiAoICFidWJibGluZyAmJiBlbGVtW3R5cGVdICYmICFldmVudC5pc0RlZmF1bHRQcmV2ZW50ZWQoKSAmJiAhKGpRdWVyeS5ub2RlTmFtZShlbGVtLCAnYScpICYmIHR5cGUgPT0gImNsaWNrIikgKSB7DQoJCQl0aGlzLnRyaWdnZXJlZCA9IHRydWU7DQoJCQl0cnkgew0KCQkJCWVsZW1bIHR5cGUgXSgpOw0KCQkJLy8gcHJldmVudCBJRSBmcm9tIHRocm93aW5nIGFuIGVycm9yIGZvciBzb21lIGhpZGRlbiBlbGVtZW50cw0KCQkJfSBjYXRjaCAoZSkge30NCgkJfQ0KDQoJCXRoaXMudHJpZ2dlcmVkID0gZmFsc2U7DQoNCgkJaWYgKCAhZXZlbnQuaXNQcm9wYWdhdGlvblN0b3BwZWQoKSApIHsNCgkJCXZhciBwYXJlbnQgPSBlbGVtLnBhcmVudE5vZGUgfHwgZWxlbS5vd25lckRvY3VtZW50Ow0KCQkJaWYgKCBwYXJlbnQgKQ0KCQkJCWpRdWVyeS5ldmVudC50cmlnZ2VyKGV2ZW50LCBkYXRhLCBwYXJlbnQsIHRydWUpOw0KCQl9DQoJfSwNCg0KCWhhbmRsZTogZnVuY3Rpb24oZXZlbnQpIHsNCgkJLy8vCTxzdW1tYXJ5Pg0KCQkvLy8JCVRoaXMgbWV0aG9kIGlzIGludGVybmFsLg0KCQkvLy8JPC9zdW1tYXJ5Pg0KCQkvLy8JPHByaXZhdGUgLz4NCgkJDQoJCS8vIHJldHVybmVkIHVuZGVmaW5lZCBvciBmYWxzZQ0KCQl2YXIgYWxsLCBoYW5kbGVyczsNCg0KCQlldmVudCA9IGFyZ3VtZW50c1swXSA9IGpRdWVyeS5ldmVudC5maXgoIGV2ZW50IHx8IHdpbmRvdy5ldmVudCApOw0KCQlldmVudC5jdXJyZW50VGFyZ2V0ID0gdGhpczsNCg0KCQkvLyBOYW1lc3BhY2VkIGV2ZW50IGhhbmRsZXJzDQoJCXZhciBuYW1lc3BhY2VzID0gZXZlbnQudHlwZS5zcGxpdCgiLiIpOw0KCQlldmVudC50eXBlID0gbmFtZXNwYWNlcy5zaGlmdCgpOw0KDQoJCS8vIENhY2hlIHRoaXMgbm93LCBhbGwgPSB0cnVlIG1lYW5zLCBhbnkgaGFuZGxlcg0KCQlhbGwgPSAhbmFtZXNwYWNlcy5sZW5ndGggJiYgIWV2ZW50LmV4Y2x1c2l2ZTsNCgkJDQoJCXZhciBuYW1lc3BhY2UgPSBSZWdFeHAoIihefFxcLikiICsgbmFtZXNwYWNlcy5zbGljZSgpLnNvcnQoKS5qb2luKCIuKlxcLiIpICsgIihcXC58JCkiKTsNCg0KCQloYW5kbGVycyA9ICggalF1ZXJ5LmRhdGEodGhpcywgImV2ZW50cyIpIHx8IHt9IClbZXZlbnQudHlwZV07DQoNCgkJZm9yICggdmFyIGogaW4gaGFuZGxlcnMgKSB7DQoJCQl2YXIgaGFuZGxlciA9IGhhbmRsZXJzW2pdOw0KDQoJCQkvLyBGaWx0ZXIgdGhlIGZ1bmN0aW9ucyBieSBjbGFzcw0KCQkJaWYgKCBhbGwgfHwgbmFtZXNwYWNlLnRlc3QoaGFuZGxlci50eXBlKSApIHsNCgkJCQkvLyBQYXNzIGluIGEgcmVmZXJlbmNlIHRvIHRoZSBoYW5kbGVyIGZ1bmN0aW9uIGl0c2VsZg0KCQkJCS8vIFNvIHRoYXQgd2UgY2FuIGxhdGVyIHJlbW92ZSBpdA0KCQkJCWV2ZW50LmhhbmRsZXIgPSBoYW5kbGVyOw0KCQkJCWV2ZW50LmRhdGEgPSBoYW5kbGVyLmRhdGE7DQoNCgkJCQl2YXIgcmV0ID0gaGFuZGxlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpOw0KDQoJCQkJaWYoIHJldCAhPT0gdW5kZWZpbmVkICl7DQoJCQkJCWV2ZW50LnJlc3VsdCA9IHJldDsNCgkJCQkJaWYgKCByZXQgPT09IGZhbHNlICkgew0KCQkJCQkJZXZlbnQucHJldmVudERlZmF1bHQoKTsNCgkJCQkJCWV2ZW50LnN0b3BQcm9wYWdhdGlvbigpOw0KCQkJCQl9DQoJCQkJfQ0KDQoJCQkJaWYoIGV2ZW50LmlzSW1tZWRpYXRlUHJvcGFnYXRpb25TdG9wcGVkKCkgKQ0KCQkJCQlicmVhazsNCg0KCQkJfQ0KCQl9DQoJfSwNCg0KCXByb3BzOiAiYWx0S2V5IGF0dHJDaGFuZ2UgYXR0ck5hbWUgYnViYmxlcyBidXR0b24gY2FuY2VsYWJsZSBjaGFyQ29kZSBjbGllbnRYIGNsaWVudFkgY3RybEtleSBjdXJyZW50VGFyZ2V0IGRhdGEgZGV0YWlsIGV2ZW50UGhhc2UgZnJvbUVsZW1lbnQgaGFuZGxlciBrZXlDb2RlIG1ldGFLZXkgbmV3VmFsdWUgb3JpZ2luYWxUYXJnZXQgcGFnZVggcGFnZVkgcHJldlZhbHVlIHJlbGF0ZWROb2RlIHJlbGF0ZWRUYXJnZXQgc2NyZWVuWCBzY3JlZW5ZIHNoaWZ0S2V5IHNyY0VsZW1lbnQgdGFyZ2V0IHRvRWxlbWVudCB2aWV3IHdoZWVsRGVsdGEgd2hpY2giLnNwbGl0KCIgIiksDQoNCglmaXg6IGZ1bmN0aW9uKGV2ZW50KSB7DQoJCS8vLwk8c3VtbWFyeT4NCgkJLy8vCQlUaGlzIG1ldGhvZCBpcyBpbnRlcm5hbC4NCgkJLy8vCTwvc3VtbWFyeT4NCgkJLy8vCTxwcml2YXRlIC8+DQoJCQ0KCQlpZiAoIGV2ZW50W2V4cGFuZG9dICkNCgkJCXJldHVybiBldmVudDsNCg0KCQkvLyBzdG9yZSBhIGNvcHkgb2YgdGhlIG9yaWdpbmFsIGV2ZW50IG9iamVjdA0KCQkvLyBhbmQgImNsb25lIiB0byBzZXQgcmVhZC1vbmx5IHByb3BlcnRpZXMNCgkJdmFyIG9yaWdpbmFsRXZlbnQgPSBldmVudDsNCgkJZXZlbnQgPSBqUXVlcnkuRXZlbnQoIG9yaWdpbmFsRXZlbnQgKTsNCg0KCQlmb3IgKCB2YXIgaSA9IHRoaXMucHJvcHMubGVuZ3RoLCBwcm9wOyBpOyApew0KCQkJcHJvcCA9IHRoaXMucHJvcHNbIC0taSBdOw0KCQkJZXZlbnRbIHByb3AgXSA9IG9yaWdpbmFsRXZlbnRbIHByb3AgXTsNCgkJfQ0KDQoJCS8vIEZpeCB0YXJnZXQgcHJvcGVydHksIGlmIG5lY2Vzc2FyeQ0KCQlpZiAoICFldmVudC50YXJnZXQgKQ0KCQkJZXZlbnQudGFyZ2V0ID0gZXZlbnQuc3JjRWxlbWVudCB8fCBkb2N1bWVudDsgLy8gRml4ZXMgIzE5MjUgd2hlcmUgc3JjRWxlbWVudCBtaWdodCBub3QgYmUgZGVmaW5lZCBlaXRoZXINCg0KCQkvLyBjaGVjayBpZiB0YXJnZXQgaXMgYSB0ZXh0bm9kZSAoc2FmYXJpKQ0KCQlpZiAoIGV2ZW50LnRhcmdldC5ub2RlVHlwZSA9PSAzICkNCgkJCWV2ZW50LnRhcmdldCA9IGV2ZW50LnRhcmdldC5wYXJlbnROb2RlOw0KDQoJCS8vIEFkZCByZWxhdGVkVGFyZ2V0LCBpZiBuZWNlc3NhcnkNCgkJaWYgKCAhZXZlbnQucmVsYXRlZFRhcmdldCAmJiBldmVudC5mcm9tRWxlbWVudCApDQoJCQlldmVudC5yZWxhdGVkVGFyZ2V0ID0gZXZlbnQuZnJvbUVsZW1lbnQgPT0gZXZlbnQudGFyZ2V0ID8gZXZlbnQudG9FbGVtZW50IDogZXZlbnQuZnJvbUVsZW1lbnQ7DQoNCgkJLy8gQ2FsY3VsYXRlIHBhZ2VYL1kgaWYgbWlzc2luZyBhbmQgY2xpZW50WC9ZIGF2YWlsYWJsZQ0KCQlpZiAoIGV2ZW50LnBhZ2VYID09IG51bGwgJiYgZXZlbnQuY2xpZW50WCAhPSBudWxsICkgew0KCQkJdmFyIGRvYyA9IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCwgYm9keSA9IGRvY3VtZW50LmJvZHk7DQoJCQlldmVudC5wYWdlWCA9IGV2ZW50LmNsaWVudFggKyAoZG9jICYmIGRvYy5zY3JvbGxMZWZ0IHx8IGJvZHkgJiYgYm9keS5zY3JvbGxMZWZ0IHx8IDApIC0gKGRvYy5jbGllbnRMZWZ0IHx8IDApOw0KCQkJZXZlbnQucGFnZVkgPSBldmVudC5jbGllbnRZICsgKGRvYyAmJiBkb2Muc2Nyb2xsVG9wIHx8IGJvZHkgJiYgYm9keS5zY3JvbGxUb3AgfHwgMCkgLSAoZG9jLmNsaWVudFRvcCB8fCAwKTsNCgkJfQ0KDQoJCS8vIEFkZCB3aGljaCBmb3Iga2V5IGV2ZW50cw0KCQlpZiAoICFldmVudC53aGljaCAmJiAoKGV2ZW50LmNoYXJDb2RlIHx8IGV2ZW50LmNoYXJDb2RlID09PSAwKSA/IGV2ZW50LmNoYXJDb2RlIDogZXZlbnQua2V5Q29kZSkgKQ0KCQkJZXZlbnQud2hpY2ggPSBldmVudC5jaGFyQ29kZSB8fCBldmVudC5rZXlDb2RlOw0KDQoJCS8vIEFkZCBtZXRhS2V5IHRvIG5vbi1NYWMgYnJvd3NlcnMgKHVzZSBjdHJsIGZvciBQQydzIGFuZCBNZXRhIGZvciBNYWNzKQ0KCQlpZiAoICFldmVudC5tZXRhS2V5ICYmIGV2ZW50LmN0cmxLZXkgKQ0KCQkJZXZlbnQubWV0YUtleSA9IGV2ZW50LmN0cmxLZXk7DQoNCgkJLy8gQWRkIHdoaWNoIGZvciBjbGljazogMSA9PSBsZWZ0OyAyID09IG1pZGRsZTsgMyA9PSByaWdodA0KCQkvLyBOb3RlOiBidXR0b24gaXMgbm90IG5vcm1hbGl6ZWQsIHNvIGRvbid0IHVzZSBpdA0KCQlpZiAoICFldmVudC53aGljaCAmJiBldmVudC5idXR0b24gKQ0KCQkJZXZlbnQud2hpY2ggPSAoZXZlbnQuYnV0dG9uICYgMSA/IDEgOiAoIGV2ZW50LmJ1dHRvbiAmIDIgPyAzIDogKCBldmVudC5idXR0b24gJiA0ID8gMiA6IDAgKSApKTsNCg0KCQlyZXR1cm4gZXZlbnQ7DQoJfSwNCg0KCXByb3h5OiBmdW5jdGlvbiggZm4sIHByb3h5ICl7DQoJCS8vLwk8c3VtbWFyeT4NCgkJLy8vCQlUaGlzIG1ldGhvZCBpcyBpbnRlcm5hbC4NCgkJLy8vCTwvc3VtbWFyeT4NCgkJLy8vCTxwcml2YXRlIC8+DQoJCQ0KCQlwcm94eSA9IHByb3h5IHx8IGZ1bmN0aW9uKCl7IHJldHVybiBmbi5hcHBseSh0aGlzLCBhcmd1bWVudHMpOyB9Ow0KCQkvLyBTZXQgdGhlIGd1aWQgb2YgdW5pcXVlIGhhbmRsZXIgdG8gdGhlIHNhbWUgb2Ygb3JpZ2luYWwgaGFuZGxlciwgc28gaXQgY2FuIGJlIHJlbW92ZWQNCgkJcHJveHkuZ3VpZCA9IGZuLmd1aWQgPSBmbi5ndWlkIHx8IHByb3h5Lmd1aWQgfHwgdGhpcy5ndWlkKys7DQoJCS8vIFNvIHByb3h5IGNhbiBiZSBkZWNsYXJlZCBhcyBhbiBhcmd1bWVudA0KCQlyZXR1cm4gcHJveHk7DQoJfSwNCg0KCXNwZWNpYWw6IHsNCgkJcmVhZHk6IHsNCgkJCS8vLwk8c3VtbWFyeT4NCgkJCS8vLwkJVGhpcyBtZXRob2QgaXMgaW50ZXJuYWwuDQoJCQkvLy8JPC9zdW1tYXJ5Pg0KCQkJLy8vCTxwcml2YXRlIC8+DQoJCQkNCgkJCS8vIE1ha2Ugc3VyZSB0aGUgcmVhZHkgZXZlbnQgaXMgc2V0dXANCgkJCXNldHVwOiBiaW5kUmVhZHksDQoJCQl0ZWFyZG93bjogZnVuY3Rpb24oKSB7fQ0KCQl9DQoJfSwNCgkNCglzcGVjaWFsQWxsOiB7DQoJCWxpdmU6IHsNCgkJCXNldHVwOiBmdW5jdGlvbiggc2VsZWN0b3IsIG5hbWVzcGFjZXMgKXsNCgkJCQlqUXVlcnkuZXZlbnQuYWRkKCB0aGlzLCBuYW1lc3BhY2VzWzBdLCBsaXZlSGFuZGxlciApOw0KCQkJfSwNCgkJCXRlYXJkb3duOiAgZnVuY3Rpb24oIG5hbWVzcGFjZXMgKXsNCgkJCQlpZiAoIG5hbWVzcGFjZXMubGVuZ3RoICkgew0KCQkJCQl2YXIgcmVtb3ZlID0gMCwgbmFtZSA9IFJlZ0V4cCgiKF58XFwuKSIgKyBuYW1lc3BhY2VzWzBdICsgIihcXC58JCkiKTsNCgkJCQkJDQoJCQkJCWpRdWVyeS5lYWNoKCAoalF1ZXJ5LmRhdGEodGhpcywgImV2ZW50cyIpLmxpdmUgfHwge30pLCBmdW5jdGlvbigpew0KCQkJCQkJaWYgKCBuYW1lLnRlc3QodGhpcy50eXBlKSApDQoJCQkJCQkJcmVtb3ZlKys7DQoJCQkJCX0pOw0KCQkJCQkNCgkJCQkJaWYgKCByZW1vdmUgPCAxICkNCgkJCQkJCWpRdWVyeS5ldmVudC5yZW1vdmUoIHRoaXMsIG5hbWVzcGFjZXNbMF0sIGxpdmVIYW5kbGVyICk7DQoJCQkJfQ0KCQkJfQ0KCQl9DQoJfQ0KfTsNCg0KalF1ZXJ5LkV2ZW50ID0gZnVuY3Rpb24oIHNyYyApew0KCS8vIEFsbG93IGluc3RhbnRpYXRpb24gd2l0aG91dCB0aGUgJ25ldycga2V5d29yZA0KCWlmKCAhdGhpcy5wcmV2ZW50RGVmYXVsdCApDQoJCXJldHVybiBuZXcgalF1ZXJ5LkV2ZW50KHNyYyk7DQoJDQoJLy8gRXZlbnQgb2JqZWN0DQoJaWYoIHNyYyAmJiBzcmMudHlwZSApew0KCQl0aGlzLm9yaWdpbmFsRXZlbnQgPSBzcmM7DQoJCXRoaXMudHlwZSA9IHNyYy50eXBlOw0KCS8vIEV2ZW50IHR5cGUNCgl9ZWxzZQ0KCQl0aGlzLnR5cGUgPSBzcmM7DQoNCgkvLyB0aW1lU3RhbXAgaXMgYnVnZ3kgZm9yIHNvbWUgZXZlbnRzIG9uIEZpcmVmb3goIzM4NDMpDQoJLy8gU28gd2Ugd29uJ3QgcmVseSBvbiB0aGUgbmF0aXZlIHZhbHVlDQoJdGhpcy50aW1lU3RhbXAgPSBub3coKTsNCgkNCgkvLyBNYXJrIGl0IGFzIGZpeGVkDQoJdGhpc1tleHBhbmRvXSA9IHRydWU7DQp9Ow0KDQpmdW5jdGlvbiByZXR1cm5GYWxzZSgpew0KCXJldHVybiBmYWxzZTsNCn0NCmZ1bmN0aW9uIHJldHVyblRydWUoKXsNCglyZXR1cm4gdHJ1ZTsNCn0NCg0KLy8galF1ZXJ5LkV2ZW50IGlzIGJhc2VkIG9uIERPTTMgRXZlbnRzIGFzIHNwZWNpZmllZCBieSB0aGUgRUNNQVNjcmlwdCBMYW5ndWFnZSBCaW5kaW5nDQovLyBodHRwOi8vd3d3LnczLm9yZy9UUi8yMDAzL1dELURPTS1MZXZlbC0zLUV2ZW50cy0yMDAzMDMzMS9lY21hLXNjcmlwdC1iaW5kaW5nLmh0bWwNCmpRdWVyeS5FdmVudC5wcm90b3R5cGUgPSB7DQoJcHJldmVudERlZmF1bHQ6IGZ1bmN0aW9uKCkgew0KCQl0aGlzLmlzRGVmYXVsdFByZXZlbnRlZCA9IHJldHVyblRydWU7DQoNCgkJdmFyIGUgPSB0aGlzLm9yaWdpbmFsRXZlbnQ7DQoJCWlmKCAhZSApDQoJCQlyZXR1cm47DQoJCS8vIGlmIHByZXZlbnREZWZhdWx0IGV4aXN0cyBydW4gaXQgb24gdGhlIG9yaWdpbmFsIGV2ZW50DQoJCWlmIChlLnByZXZlbnREZWZhdWx0KQ0KCQkJZS5wcmV2ZW50RGVmYXVsdCgpOw0KCQkvLyBvdGhlcndpc2Ugc2V0IHRoZSByZXR1cm5WYWx1ZSBwcm9wZXJ0eSBvZiB0aGUgb3JpZ2luYWwgZXZlbnQgdG8gZmFsc2UgKElFKQ0KCQllLnJldHVyblZhbHVlID0gZmFsc2U7DQoJfSwNCglzdG9wUHJvcGFnYXRpb246IGZ1bmN0aW9uKCkgew0KCQl0aGlzLmlzUHJvcGFnYXRpb25TdG9wcGVkID0gcmV0dXJuVHJ1ZTsNCg0KCQl2YXIgZSA9IHRoaXMub3JpZ2luYWxFdmVudDsNCgkJaWYoICFlICkNCgkJCXJldHVybjsNCgkJLy8gaWYgc3RvcFByb3BhZ2F0aW9uIGV4aXN0cyBydW4gaXQgb24gdGhlIG9yaWdpbmFsIGV2ZW50DQoJCWlmIChlLnN0b3BQcm9wYWdhdGlvbikNCgkJCWUuc3RvcFByb3BhZ2F0aW9uKCk7DQoJCS8vIG90aGVyd2lzZSBzZXQgdGhlIGNhbmNlbEJ1YmJsZSBwcm9wZXJ0eSBvZiB0aGUgb3JpZ2luYWwgZXZlbnQgdG8gdHJ1ZSAoSUUpDQoJCWUuY2FuY2VsQnViYmxlID0gdHJ1ZTsNCgl9LA0KCXN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbjpmdW5jdGlvbigpew0KCQl0aGlzLmlzSW1tZWRpYXRlUHJvcGFnYXRpb25TdG9wcGVkID0gcmV0dXJuVHJ1ZTsNCgkJdGhpcy5zdG9wUHJvcGFnYXRpb24oKTsNCgl9LA0KCWlzRGVmYXVsdFByZXZlbnRlZDogcmV0dXJuRmFsc2UsDQoJaXNQcm9wYWdhdGlvblN0b3BwZWQ6IHJldHVybkZhbHNlLA0KCWlzSW1tZWRpYXRlUHJvcGFnYXRpb25TdG9wcGVkOiByZXR1cm5GYWxzZQ0KfTsNCi8vIENoZWNrcyBpZiBhbiBldmVudCBoYXBwZW5lZCBvbiBhbiBlbGVtZW50IHdpdGhpbiBhbm90aGVyIGVsZW1lbnQNCi8vIFVzZWQgaW4galF1ZXJ5LmV2ZW50LnNwZWNpYWwubW91c2VlbnRlciBhbmQgbW91c2VsZWF2ZSBoYW5kbGVycw0KdmFyIHdpdGhpbkVsZW1lbnQgPSBmdW5jdGlvbihldmVudCkgew0KCS8vIENoZWNrIGlmIG1vdXNlKG92ZXJ8b3V0KSBhcmUgc3RpbGwgd2l0aGluIHRoZSBzYW1lIHBhcmVudCBlbGVtZW50DQoJdmFyIHBhcmVudCA9IGV2ZW50LnJlbGF0ZWRUYXJnZXQ7DQoJLy8gVHJhdmVyc2UgdXAgdGhlIHRyZWUNCgl3aGlsZSAoIHBhcmVudCAmJiBwYXJlbnQgIT0gdGhpcyApDQoJCXRyeSB7IHBhcmVudCA9IHBhcmVudC5wYXJlbnROb2RlOyB9DQoJCWNhdGNoKGUpIHsgcGFyZW50ID0gdGhpczsgfQ0KCQ0KCWlmKCBwYXJlbnQgIT0gdGhpcyApew0KCQkvLyBzZXQgdGhlIGNvcnJlY3QgZXZlbnQgdHlwZQ0KCQlldmVudC50eXBlID0gZXZlbnQuZGF0YTsNCgkJLy8gaGFuZGxlIGV2ZW50IGlmIHdlIGFjdHVhbGx5IGp1c3QgbW91c2VkIG9uIHRvIGEgbm9uIHN1Yi1lbGVtZW50DQoJCWpRdWVyeS5ldmVudC5oYW5kbGUuYXBwbHkoIHRoaXMsIGFyZ3VtZW50cyApOw0KCX0NCn07DQoJDQpqUXVlcnkuZWFjaCh7IA0KCW1vdXNlb3ZlcjogJ21vdXNlZW50ZXInLCANCgltb3VzZW91dDogJ21vdXNlbGVhdmUnDQp9LCBmdW5jdGlvbiggb3JpZywgZml4ICl7DQoJalF1ZXJ5LmV2ZW50LnNwZWNpYWxbIGZpeCBdID0gew0KCQlzZXR1cDogZnVuY3Rpb24oKXsNCgkJCS8vLwk8c3VtbWFyeT4NCgkJCS8vLwkJVGhpcyBtZXRob2QgaXMgaW50ZXJuYWwuDQoJCQkvLy8JPC9zdW1tYXJ5Pg0KCQkJLy8vCTxwcml2YXRlIC8+DQoJCQkNCgkJCWpRdWVyeS5ldmVudC5hZGQoIHRoaXMsIG9yaWcsIHdpdGhpbkVsZW1lbnQsIGZpeCApOw0KCQl9LA0KCQl0ZWFyZG93bjogZnVuY3Rpb24oKXsNCgkJCS8vLwk8c3VtbWFyeT4NCgkJCS8vLwkJVGhpcyBtZXRob2QgaXMgaW50ZXJuYWwuDQoJCQkvLy8JPC9zdW1tYXJ5Pg0KCQkJLy8vCTxwcml2YXRlIC8+DQoJCQkNCgkJCWpRdWVyeS5ldmVudC5yZW1vdmUoIHRoaXMsIG9yaWcsIHdpdGhpbkVsZW1lbnQgKTsNCgkJfQ0KCX07CQkJICAgDQp9KTsNCg0KalF1ZXJ5LmZuLmV4dGVuZCh7DQoJYmluZDogZnVuY3Rpb24oIHR5cGUsIGRhdGEsIGZuICkgew0KCQkvLy8JPHN1bW1hcnk+DQoJCS8vLwkJQmluZHMgYSBoYW5kbGVyIHRvIG9uZSBvciBtb3JlIGV2ZW50cyBmb3IgZWFjaCBtYXRjaGVkIGVsZW1lbnQuICBDYW4gYWxzbyBiaW5kIGN1c3RvbSBldmVudHMuDQoJCS8vLwk8L3N1bW1hcnk+DQoJCS8vLwk8cGFyYW0gbmFtZT0idHlwZSIgdHlwZT0iU3RyaW5nIj5PbmUgb3IgbW9yZSBldmVudCB0eXBlcyBzZXBhcmF0ZWQgYnkgYSBzcGFjZS4gIEJ1aWx0LWluIGV2ZW50IHR5cGUgdmFsdWVzIGFyZTogYmx1ciwgZm9jdXMsIGxvYWQsIHJlc2l6ZSwgc2Nyb2xsLCB1bmxvYWQsIGNsaWNrLCBkYmxjbGljaywgbW91c2Vkb3duLCBtb3VzZXVwLCBtb3VzZW1vdmUsIG1vdXNlb3ZlciwgbW91c2VvdXQsIG1vdXNlZW50ZXIsIG1vdXNlbGVhdmUsIGNoYW5nZSwgc2VsZWN0LCBzdWJtaXQsIGtleWRvd24sIGtleXByZXNzLCBrZXl1cCwgZXJyb3IgLjwvcGFyYW0+DQoJCS8vLwk8cGFyYW0gbmFtZT0iZGF0YSIgb3B0aW9uYWw9InRydWUiIHR5cGU9Ik9iamVjdCI+QWRkaXRpb25hbCBkYXRhIHBhc3NlZCB0byB0aGUgZXZlbnQgaGFuZGxlciBhcyBldmVudC5kYXRhPC9wYXJhbT4NCgkJLy8vCTxwYXJhbSBuYW1lPSJmbiIgdHlwZT0iRnVuY3Rpb24iPkEgZnVuY3Rpb24gdG8gYmluZCB0byB0aGUgZXZlbnQgb24gZWFjaCBvZiB0aGUgc2V0IG9mIG1hdGNoZWQgZWxlbWVudHMuICBmdW5jdGlvbiBjYWxsYmFjayhldmVudE9iamVjdCkgc3VjaCB0aGF0IHRoaXMgY29ycmVzcG9uZHMgdG8gdGhlIGRvbSBlbGVtZW50LjwvcGFyYW0+DQoJCQ0KCQlyZXR1cm4gdHlwZSA9PSAidW5sb2FkIiA/IHRoaXMub25lKHR5cGUsIGRhdGEsIGZuKSA6IHRoaXMuZWFjaChmdW5jdGlvbigpew0KCQkJalF1ZXJ5LmV2ZW50LmFkZCggdGhpcywgdHlwZSwgZm4gfHwgZGF0YSwgZm4gJiYgZGF0YSApOw0KCQl9KTsNCgl9LA0KDQoJb25lOiBmdW5jdGlvbiggdHlwZSwgZGF0YSwgZm4gKSB7DQoJCS8vLwk8c3VtbWFyeT4NCgkJLy8vCQlCaW5kcyBhIGhhbmRsZXIgdG8gb25lIG9yIG1vcmUgZXZlbnRzIHRvIGJlIGV4ZWN1dGVkIGV4YWN0bHkgb25jZSBmb3IgZWFjaCBtYXRjaGVkIGVsZW1lbnQuDQoJCS8vLwk8L3N1bW1hcnk+DQoJCS8vLwk8cGFyYW0gbmFtZT0idHlwZSIgdHlwZT0iU3RyaW5nIj5PbmUgb3IgbW9yZSBldmVudCB0eXBlcyBzZXBhcmF0ZWQgYnkgYSBzcGFjZS4gIEJ1aWx0LWluIGV2ZW50IHR5cGUgdmFsdWVzIGFyZTogYmx1ciwgZm9jdXMsIGxvYWQsIHJlc2l6ZSwgc2Nyb2xsLCB1bmxvYWQsIGNsaWNrLCBkYmxjbGljaywgbW91c2Vkb3duLCBtb3VzZXVwLCBtb3VzZW1vdmUsIG1vdXNlb3ZlciwgbW91c2VvdXQsIG1vdXNlZW50ZXIsIG1vdXNlbGVhdmUsIGNoYW5nZSwgc2VsZWN0LCBzdWJtaXQsIGtleWRvd24sIGtleXByZXNzLCBrZXl1cCwgZXJyb3IgLjwvcGFyYW0+DQoJCS8vLwk8cGFyYW0gbmFtZT0iZGF0YSIgb3B0aW9uYWw9InRydWUiIHR5cGU9Ik9iamVjdCI+QWRkaXRpb25hbCBkYXRhIHBhc3NlZCB0byB0aGUgZXZlbnQgaGFuZGxlciBhcyBldmVudC5kYXRhPC9wYXJhbT4NCgkJLy8vCTxwYXJhbSBuYW1lPSJmbiIgdHlwZT0iRnVuY3Rpb24iPkEgZnVuY3Rpb24gdG8gYmluZCB0byB0aGUgZXZlbnQgb24gZWFjaCBvZiB0aGUgc2V0IG9mIG1hdGNoZWQgZWxlbWVudHMuICBmdW5jdGlvbiBjYWxsYmFjayhldmVudE9iamVjdCkgc3VjaCB0aGF0IHRoaXMgY29ycmVzcG9uZHMgdG8gdGhlIGRvbSBlbGVtZW50LjwvcGFyYW0+DQoJCQ0KCQl2YXIgb25lID0galF1ZXJ5LmV2ZW50LnByb3h5KCBmbiB8fCBkYXRhLCBmdW5jdGlvbihldmVudCkgew0KCQkJalF1ZXJ5KHRoaXMpLnVuYmluZChldmVudCwgb25lKTsNCgkJCXJldHVybiAoZm4gfHwgZGF0YSkuYXBwbHkoIHRoaXMsIGFyZ3VtZW50cyApOw0KCQl9KTsNCgkJcmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbigpew0KCQkJalF1ZXJ5LmV2ZW50LmFkZCggdGhpcywgdHlwZSwgb25lLCBmbiAmJiBkYXRhKTsNCgkJfSk7DQoJfSwNCg0KCXVuYmluZDogZnVuY3Rpb24oIHR5cGUsIGZuICkgew0KCQkvLy8JPHN1bW1hcnk+DQoJCS8vLwkJVW5iaW5kcyBhIGhhbmRsZXIgZnJvbSBvbmUgb3IgbW9yZSBldmVudHMgZm9yIGVhY2ggbWF0Y2hlZCBlbGVtZW50Lg0KCQkvLy8JPC9zdW1tYXJ5Pg0KCQkvLy8JPHBhcmFtIG5hbWU9InR5cGUiIHR5cGU9IlN0cmluZyI+T25lIG9yIG1vcmUgZXZlbnQgdHlwZXMgc2VwYXJhdGVkIGJ5IGEgc3BhY2UuICBCdWlsdC1pbiBldmVudCB0eXBlIHZhbHVlcyBhcmU6IGJsdXIsIGZvY3VzLCBsb2FkLCByZXNpemUsIHNjcm9sbCwgdW5sb2FkLCBjbGljaywgZGJsY2xpY2ssIG1vdXNlZG93biwgbW91c2V1cCwgbW91c2Vtb3ZlLCBtb3VzZW92ZXIsIG1vdXNlb3V0LCBtb3VzZWVudGVyLCBtb3VzZWxlYXZlLCBjaGFuZ2UsIHNlbGVjdCwgc3VibWl0LCBrZXlkb3duLCBrZXlwcmVzcywga2V5dXAsIGVycm9yIC48L3BhcmFtPg0KCQkvLy8JPHBhcmFtIG5hbWU9ImZuIiB0eXBlPSJGdW5jdGlvbiI+QSBmdW5jdGlvbiB0byBiaW5kIHRvIHRoZSBldmVudCBvbiBlYWNoIG9mIHRoZSBzZXQgb2YgbWF0Y2hlZCBlbGVtZW50cy4gIGZ1bmN0aW9uIGNhbGxiYWNrKGV2ZW50T2JqZWN0KSBzdWNoIHRoYXQgdGhpcyBjb3JyZXNwb25kcyB0byB0aGUgZG9tIGVsZW1lbnQuPC9wYXJhbT4NCgkJDQoJCXJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24oKXsNCgkJCWpRdWVyeS5ldmVudC5yZW1vdmUoIHRoaXMsIHR5cGUsIGZuICk7DQoJCX0pOw0KCX0sDQoNCgl0cmlnZ2VyOiBmdW5jdGlvbiggdHlwZSwgZGF0YSApIHsNCgkJLy8vCTxzdW1tYXJ5Pg0KCQkvLy8JCVRyaWdnZXJzIGEgdHlwZSBvZiBldmVudCBvbiBldmVyeSBtYXRjaGVkIGVsZW1lbnQuDQoJCS8vLwk8L3N1bW1hcnk+DQoJCS8vLwk8cGFyYW0gbmFtZT0idHlwZSIgdHlwZT0iU3RyaW5nIj5PbmUgb3IgbW9yZSBldmVudCB0eXBlcyBzZXBhcmF0ZWQgYnkgYSBzcGFjZS4gIEJ1aWx0LWluIGV2ZW50IHR5cGUgdmFsdWVzIGFyZTogYmx1ciwgZm9jdXMsIGxvYWQsIHJlc2l6ZSwgc2Nyb2xsLCB1bmxvYWQsIGNsaWNrLCBkYmxjbGljaywgbW91c2Vkb3duLCBtb3VzZXVwLCBtb3VzZW1vdmUsIG1vdXNlb3ZlciwgbW91c2VvdXQsIG1vdXNlZW50ZXIsIG1vdXNlbGVhdmUsIGNoYW5nZSwgc2VsZWN0LCBzdWJtaXQsIGtleWRvd24sIGtleXByZXNzLCBrZXl1cCwgZXJyb3IgLjwvcGFyYW0+DQoJCS8vLwk8cGFyYW0gbmFtZT0iZGF0YSIgb3B0aW9uYWw9InRydWUiIHR5cGU9IkFycmF5Ij5BZGRpdGlvbmFsIGRhdGEgcGFzc2VkIHRvIHRoZSBldmVudCBoYW5kbGVyIGFzIGFkZGl0aW9uYWwgYXJndW1lbnRzLjwvcGFyYW0+DQoJCS8vLwk8cGFyYW0gbmFtZT0iZm4iIHR5cGU9IkZ1bmN0aW9uIj5UaGlzIHBhcmFtZXRlciBpcyB1bmRvY3VtZW50ZWQuPC9wYXJhbT4NCgkJDQoJCXJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24oKXsNCgkJCWpRdWVyeS5ldmVudC50cmlnZ2VyKCB0eXBlLCBkYXRhLCB0aGlzICk7DQoJCX0pOw0KCX0sDQoNCgl0cmlnZ2VySGFuZGxlcjogZnVuY3Rpb24oIHR5cGUsIGRhdGEgKSB7DQoJCS8vLwk8c3VtbWFyeT4NCgkJLy8vCQlUcmlnZ2VycyBhbGwgYm91bmQgZXZlbnQgaGFuZGxlcnMgb24gYW4gZWxlbWVudCBmb3IgYSBzcGVjaWZpYyBldmVudCB0eXBlIHdpdGhvdXQgZXhlY3V0aW5nIHRoZSBicm93c2VyJ3MgZGVmYXVsdCBhY3Rpb25zLg0KCQkvLy8JPC9zdW1tYXJ5Pg0KCQkvLy8JPHBhcmFtIG5hbWU9InR5cGUiIHR5cGU9IlN0cmluZyI+T25lIG9yIG1vcmUgZXZlbnQgdHlwZXMgc2VwYXJhdGVkIGJ5IGEgc3BhY2UuICBCdWlsdC1pbiBldmVudCB0eXBlIHZhbHVlcyBhcmU6IGJsdXIsIGZvY3VzLCBsb2FkLCByZXNpemUsIHNjcm9sbCwgdW5sb2FkLCBjbGljaywgZGJsY2xpY2ssIG1vdXNlZG93biwgbW91c2V1cCwgbW91c2Vtb3ZlLCBtb3VzZW92ZXIsIG1vdXNlb3V0LCBtb3VzZWVudGVyLCBtb3VzZWxlYXZlLCBjaGFuZ2UsIHNlbGVjdCwgc3VibWl0LCBrZXlkb3duLCBrZXlwcmVzcywga2V5dXAsIGVycm9yIC48L3BhcmFtPg0KCQkvLy8JPHBhcmFtIG5hbWU9ImRhdGEiIG9wdGlvbmFsPSJ0cnVlIiB0eXBlPSJBcnJheSI+QWRkaXRpb25hbCBkYXRhIHBhc3NlZCB0byB0aGUgZXZlbnQgaGFuZGxlciBhcyBhZGRpdGlvbmFsIGFyZ3VtZW50cy48L3BhcmFtPg0KCQkvLy8JPHBhcmFtIG5hbWU9ImZuIiB0eXBlPSJGdW5jdGlvbiI+VGhpcyBwYXJhbWV0ZXIgaXMgdW5kb2N1bWVudGVkLjwvcGFyYW0+DQoJDQoJCWlmKCB0aGlzWzBdICl7DQoJCQl2YXIgZXZlbnQgPSBqUXVlcnkuRXZlbnQodHlwZSk7DQoJCQlldmVudC5wcmV2ZW50RGVmYXVsdCgpOw0KCQkJZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7DQoJCQlqUXVlcnkuZXZlbnQudHJpZ2dlciggZXZlbnQsIGRhdGEsIHRoaXNbMF0gKTsNCgkJCXJldHVybiBldmVudC5yZXN1bHQ7DQoJCX0JCQ0KCX0sDQoNCgl0b2dnbGU6IGZ1bmN0aW9uKCBmbiApIHsNCgkJLy8vCTxzdW1tYXJ5Pg0KCQkvLy8JCVRvZ2dsZXMgYW1vbmcgdHdvIG9yIG1vcmUgZnVuY3Rpb24gY2FsbHMgZXZlcnkgb3RoZXIgY2xpY2suDQoJCS8vLwk8L3N1bW1hcnk+DQoJCS8vLwk8cGFyYW0gbmFtZT0iZm4iIHR5cGU9IkZ1bmN0aW9uIj5UaGUgZnVuY3Rpb25zIGFtb25nIHdoaWNoIHRvIHRvZ2dsZSBleGVjdXRpb248L3BhcmFtPg0KCQkNCgkJLy8gU2F2ZSByZWZlcmVuY2UgdG8gYXJndW1lbnRzIGZvciBhY2Nlc3MgaW4gY2xvc3VyZQ0KCQl2YXIgYXJncyA9IGFyZ3VtZW50cywgaSA9IDE7DQoNCgkJLy8gbGluayBhbGwgdGhlIGZ1bmN0aW9ucywgc28gYW55IG9mIHRoZW0gY2FuIHVuYmluZCB0aGlzIGNsaWNrIGhhbmRsZXINCgkJd2hpbGUoIGkgPCBhcmdzLmxlbmd0aCApDQoJCQlqUXVlcnkuZXZlbnQucHJveHkoIGZuLCBhcmdzW2krK10gKTsNCg0KCQlyZXR1cm4gdGhpcy5jbGljayggalF1ZXJ5LmV2ZW50LnByb3h5KCBmbiwgZnVuY3Rpb24oZXZlbnQpIHsNCgkJCS8vIEZpZ3VyZSBvdXQgd2hpY2ggZnVuY3Rpb24gdG8gZXhlY3V0ZQ0KCQkJdGhpcy5sYXN0VG9nZ2xlID0gKCB0aGlzLmxhc3RUb2dnbGUgfHwgMCApICUgaTsNCg0KCQkJLy8gTWFrZSBzdXJlIHRoYXQgY2xpY2tzIHN0b3ANCgkJCWV2ZW50LnByZXZlbnREZWZhdWx0KCk7DQoNCgkJCS8vIGFuZCBleGVjdXRlIHRoZSBmdW5jdGlvbg0KCQkJcmV0dXJuIGFyZ3NbIHRoaXMubGFzdFRvZ2dsZSsrIF0uYXBwbHkoIHRoaXMsIGFyZ3VtZW50cyApIHx8IGZhbHNlOw0KCQl9KSk7DQoJfSwNCg0KCWhvdmVyOiBmdW5jdGlvbihmbk92ZXIsIGZuT3V0KSB7DQoJCS8vLwk8c3VtbWFyeT4NCgkJLy8vCQlTaW11bGF0ZXMgaG92ZXJpbmcgKG1vdmluZyB0aGUgbW91c2Ugb24gb3Igb2ZmIG9mIGFuIG9iamVjdCkuDQoJCS8vLwk8L3N1bW1hcnk+DQoJCS8vLwk8cGFyYW0gbmFtZT0iZm5PdmVyIiB0eXBlPSJGdW5jdGlvbiI+VGhlIGZ1bmN0aW9uIHRvIGZpcmUgd2hlbiB0aGUgbW91c2UgaXMgbW92ZWQgb3ZlciBhIG1hdGNoZWQgZWxlbWVudC48L3BhcmFtPg0KCQkvLy8JPHBhcmFtIG5hbWU9ImZuT3V0IiB0eXBlPSJGdW5jdGlvbiI+VGhlIGZ1bmN0aW9uIHRvIGZpcmUgd2hlbiB0aGUgbW91c2UgaXMgbW92ZWQgb2ZmIG9mIGEgbWF0Y2hlZCBlbGVtZW50LjwvcGFyYW0+DQoJCQ0KCQlyZXR1cm4gdGhpcy5tb3VzZWVudGVyKGZuT3ZlcikubW91c2VsZWF2ZShmbk91dCk7DQoJfSwNCg0KCXJlYWR5OiBmdW5jdGlvbihmbikgew0KCQkvLy8JPHN1bW1hcnk+DQoJCS8vLwkJQmluZHMgYSBmdW5jdGlvbiB0byBiZSBleGVjdXRlZCB3aGVuZXZlciB0aGUgRE9NIGlzIHJlYWR5IHRvIGJlIHRyYXZlcnNlZCBhbmQgbWFuaXB1bGF0ZWQuDQoJCS8vLwk8L3N1bW1hcnk+DQoJCS8vLwk8cGFyYW0gbmFtZT0iZm4iIHR5cGU9IkZ1bmN0aW9uIj5UaGUgZnVuY3Rpb24gdG8gYmUgZXhlY3V0ZWQgd2hlbiB0aGUgRE9NIGlzIHJlYWR5LjwvcGFyYW0+DQoNCgkJLy8gQXR0YWNoIHRoZSBsaXN0ZW5lcnMNCgkJYmluZFJlYWR5KCk7DQoNCgkJLy8gSWYgdGhlIERPTSBpcyBhbHJlYWR5IHJlYWR5DQoJCWlmICggalF1ZXJ5LmlzUmVhZHkgKQ0KCQkJLy8gRXhlY3V0ZSB0aGUgZnVuY3Rpb24gaW1tZWRpYXRlbHkNCgkJCWZuLmNhbGwoIGRvY3VtZW50LCBqUXVlcnkgKTsNCg0KCQkvLyBPdGhlcndpc2UsIHJlbWVtYmVyIHRoZSBmdW5jdGlvbiBmb3IgbGF0ZXINCgkJZWxzZQ0KCQkJLy8gQWRkIHRoZSBmdW5jdGlvbiB0byB0aGUgd2FpdCBsaXN0DQoJCQlqUXVlcnkucmVhZHlMaXN0LnB1c2goIGZuICk7DQoNCgkJcmV0dXJuIHRoaXM7DQoJfSwNCgkNCglsaXZlOiBmdW5jdGlvbiggdHlwZSwgZm4gKXsNCgkJLy8vCTxzdW1tYXJ5Pg0KCQkvLy8JCUJpbmRzIGEgaGFuZGxlciB0byBhbiBldmVudCAobGlrZSBjbGljaykgZm9yIGFsbCBjdXJyZW50IC0gYW5kIGZ1dHVyZSAtIG1hdGNoZWQgZWxlbWVudC4gQ2FuIGFsc28gYmluZCBjdXN0b20gZXZlbnRzLg0KCQkvLy8JPC9zdW1tYXJ5Pg0KCQkvLy8JPHBhcmFtIG5hbWU9InR5cGUiIHR5cGU9IlN0cmluZyI+QW4gZXZlbnQgdHlwZTwvcGFyYW0+DQoJCS8vLwk8cGFyYW0gbmFtZT0iZm4iIHR5cGU9IkZ1bmN0aW9uIj5BIGZ1bmN0aW9uIHRvIGJpbmQgdG8gdGhlIGV2ZW50IG9uIGVhY2ggb2YgdGhlIHNldCBvZiBtYXRjaGVkIGVsZW1lbnRzPC9wYXJhbT4NCg0KCQl2YXIgcHJveHkgPSBqUXVlcnkuZXZlbnQucHJveHkoIGZuICk7DQoJCXByb3h5Lmd1aWQgKz0gdGhpcy5zZWxlY3RvciArIHR5cGU7DQoNCgkJalF1ZXJ5KGRvY3VtZW50KS5iaW5kKCBsaXZlQ29udmVydCh0eXBlLCB0aGlzLnNlbGVjdG9yKSwgdGhpcy5zZWxlY3RvciwgcHJveHkgKTsNCg0KCQlyZXR1cm4gdGhpczsNCgl9LA0KCQ0KCWRpZTogZnVuY3Rpb24oIHR5cGUsIGZuICl7DQoJCS8vLwk8c3VtbWFyeT4NCgkJLy8vCQlUaGlzIGRvZXMgdGhlIG9wcG9zaXRlIG9mIGxpdmUsIGl0IHJlbW92ZXMgYSBib3VuZCBsaXZlIGV2ZW50Lg0KCQkvLy8JCVlvdSBjYW4gYWxzbyB1bmJpbmQgY3VzdG9tIGV2ZW50cyByZWdpc3RlcmVkIHdpdGggbGl2ZS4NCgkJLy8vCQlJZiB0aGUgdHlwZSBpcyBwcm92aWRlZCwgYWxsIGJvdW5kIGxpdmUgZXZlbnRzIG9mIHRoYXQgdHlwZSBhcmUgcmVtb3ZlZC4NCgkJLy8vCQlJZiB0aGUgZnVuY3Rpb24gdGhhdCB3YXMgcGFzc2VkIHRvIGxpdmUgaXMgcHJvdmlkZWQgYXMgdGhlIHNlY29uZCBhcmd1bWVudCwgb25seSB0aGF0IHNwZWNpZmljIGV2ZW50IGhhbmRsZXIgaXMgcmVtb3ZlZC4NCgkJLy8vCTwvc3VtbWFyeT4NCgkJLy8vCTxwYXJhbSBuYW1lPSJ0eXBlIiB0eXBlPSJTdHJpbmciPkEgbGl2ZSBldmVudCB0eXBlIHRvIHVuYmluZC48L3BhcmFtPg0KCQkvLy8JPHBhcmFtIG5hbWU9ImZuIiB0eXBlPSJGdW5jdGlvbiI+QSBmdW5jdGlvbiB0byB1bmJpbmQgZnJvbSB0aGUgZXZlbnQgb24gZWFjaCBvZiB0aGUgc2V0IG9mIG1hdGNoZWQgZWxlbWVudHMuPC9wYXJhbT4NCg0KCQlqUXVlcnkoZG9jdW1lbnQpLnVuYmluZCggbGl2ZUNvbnZlcnQodHlwZSwgdGhpcy5zZWxlY3RvciksIGZuID8geyBndWlkOiBmbi5ndWlkICsgdGhpcy5zZWxlY3RvciArIHR5cGUgfSA6IG51bGwgKTsNCgkJcmV0dXJuIHRoaXM7DQoJfQ0KfSk7DQoNCmZ1bmN0aW9uIGxpdmVIYW5kbGVyKCBldmVudCApew0KCXZhciBjaGVjayA9IFJlZ0V4cCgiKF58XFwuKSIgKyBldmVudC50eXBlICsgIihcXC58JCkiKSwNCgkJc3RvcCA9IHRydWUsDQoJCWVsZW1zID0gW107DQoNCglqUXVlcnkuZWFjaChqUXVlcnkuZGF0YSh0aGlzLCAiZXZlbnRzIikubGl2ZSB8fCBbXSwgZnVuY3Rpb24oaSwgZm4pew0KCQlpZiAoIGNoZWNrLnRlc3QoZm4udHlwZSkgKSB7DQoJCQl2YXIgZWxlbSA9IGpRdWVyeShldmVudC50YXJnZXQpLmNsb3Nlc3QoZm4uZGF0YSlbMF07DQoJCQlpZiAoIGVsZW0gKQ0KCQkJCWVsZW1zLnB1c2goeyBlbGVtOiBlbGVtLCBmbjogZm4gfSk7DQoJCX0NCgl9KTsNCg0KCWVsZW1zLnNvcnQoZnVuY3Rpb24oYSxiKSB7DQoJCXJldHVybiBqUXVlcnkuZGF0YShhLmVsZW0sICJjbG9zZXN0IikgLSBqUXVlcnkuZGF0YShiLmVsZW0sICJjbG9zZXN0Iik7DQoJfSk7DQoJDQoJalF1ZXJ5LmVhY2goZWxlbXMsIGZ1bmN0aW9uKCl7DQoJCWlmICggdGhpcy5mbi5jYWxsKHRoaXMuZWxlbSwgZXZlbnQsIHRoaXMuZm4uZGF0YSkgPT09IGZhbHNlICkNCgkJCXJldHVybiAoc3RvcCA9IGZhbHNlKTsNCgl9KTsNCg0KCXJldHVybiBzdG9wOw0KfQ0KDQpmdW5jdGlvbiBsaXZlQ29udmVydCh0eXBlLCBzZWxlY3Rvcil7DQoJcmV0dXJuIFsibGl2ZSIsIHR5cGUsIHNlbGVjdG9yLnJlcGxhY2UoL1wuL2csICJgIikucmVwbGFjZSgvIC9nLCAifCIpXS5qb2luKCIuIik7DQp9DQoNCmpRdWVyeS5leHRlbmQoew0KCWlzUmVhZHk6IGZhbHNlLA0KCXJlYWR5TGlzdDogW10sDQoJLy8gSGFuZGxlIHdoZW4gdGhlIERPTSBpcyByZWFkeQ0KCXJlYWR5OiBmdW5jdGlvbigpIHsNCgkJLy8vCTxzdW1tYXJ5Pg0KCQkvLy8JCVRoaXMgbWV0aG9kIGlzIGludGVybmFsLg0KCQkvLy8JPC9zdW1tYXJ5Pg0KCQkvLy8JPHByaXZhdGUgLz4NCgkJDQoJCS8vIE1ha2Ugc3VyZSB0aGF0IHRoZSBET00gaXMgbm90IGFscmVhZHkgbG9hZGVkDQoJCWlmICggIWpRdWVyeS5pc1JlYWR5ICkgew0KCQkJLy8gUmVtZW1iZXIgdGhhdCB0aGUgRE9NIGlzIHJlYWR5DQoJCQlqUXVlcnkuaXNSZWFkeSA9IHRydWU7DQoNCgkJCS8vIElmIHRoZXJlIGFyZSBmdW5jdGlvbnMgYm91bmQsIHRvIGV4ZWN1dGUNCgkJCWlmICggalF1ZXJ5LnJlYWR5TGlzdCApIHsNCgkJCQkvLyBFeGVjdXRlIGFsbCBvZiB0aGVtDQoJCQkJalF1ZXJ5LmVhY2goIGpRdWVyeS5yZWFkeUxpc3QsIGZ1bmN0aW9uKCl7DQoJCQkJCXRoaXMuY2FsbCggZG9jdW1lbnQsIGpRdWVyeSApOw0KCQkJCX0pOw0KDQoJCQkJLy8gUmVzZXQgdGhlIGxpc3Qgb2YgZnVuY3Rpb25zDQoJCQkJalF1ZXJ5LnJlYWR5TGlzdCA9IG51bGw7DQoJCQl9DQoNCgkJCS8vIFRyaWdnZXIgYW55IGJvdW5kIHJlYWR5IGV2ZW50cw0KCQkJalF1ZXJ5KGRvY3VtZW50KS50cmlnZ2VySGFuZGxlcigicmVhZHkiKTsNCgkJfQ0KCX0NCn0pOw0KDQp2YXIgcmVhZHlCb3VuZCA9IGZhbHNlOw0KDQpmdW5jdGlvbiBiaW5kUmVhZHkoKXsNCglpZiAoIHJlYWR5Qm91bmQgKSByZXR1cm47DQoJcmVhZHlCb3VuZCA9IHRydWU7DQoNCgkvLyBNb3ppbGxhLCBPcGVyYSBhbmQgd2Via2l0IG5pZ2h0bGllcyBjdXJyZW50bHkgc3VwcG9ydCB0aGlzIGV2ZW50DQoJaWYgKCBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyICkgew0KCQkvLyBVc2UgdGhlIGhhbmR5IGV2ZW50IGNhbGxiYWNrDQoJCWRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoICJET01Db250ZW50TG9hZGVkIiwgZnVuY3Rpb24oKXsNCgkJCWRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoICJET01Db250ZW50TG9hZGVkIiwgYXJndW1lbnRzLmNhbGxlZSwgZmFsc2UgKTsNCgkJCWpRdWVyeS5yZWFkeSgpOw0KCQl9LCBmYWxzZSApOw0KDQoJLy8gSWYgSUUgZXZlbnQgbW9kZWwgaXMgdXNlZA0KCX0gZWxzZSBpZiAoIGRvY3VtZW50LmF0dGFjaEV2ZW50ICkgew0KCQkvLyBlbnN1cmUgZmlyaW5nIGJlZm9yZSBvbmxvYWQsDQoJCS8vIG1heWJlIGxhdGUgYnV0IHNhZmUgYWxzbyBmb3IgaWZyYW1lcw0KCQlkb2N1bWVudC5hdHRhY2hFdmVudCgib25yZWFkeXN0YXRlY2hhbmdlIiwgZnVuY3Rpb24oKXsNCgkJCWlmICggZG9jdW1lbnQucmVhZHlTdGF0ZSA9PT0gImNvbXBsZXRlIiApIHsNCgkJCQlkb2N1bWVudC5kZXRhY2hFdmVudCggIm9ucmVhZHlzdGF0ZWNoYW5nZSIsIGFyZ3VtZW50cy5jYWxsZWUgKTsNCgkJCQlqUXVlcnkucmVhZHkoKTsNCgkJCX0NCgkJfSk7DQoNCgkJLy8gSWYgSUUgYW5kIG5vdCBhbiBpZnJhbWUNCgkJLy8gY29udGludWFsbHkgY2hlY2sgdG8gc2VlIGlmIHRoZSBkb2N1bWVudCBpcyByZWFkeQ0KCQlpZiAoIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5kb1Njcm9sbCAmJiB3aW5kb3cgPT0gd2luZG93LnRvcCApIChmdW5jdGlvbigpew0KCQkJaWYgKCBqUXVlcnkuaXNSZWFkeSApIHJldHVybjsNCg0KCQkJdHJ5IHsNCgkJCQkvLyBJZiBJRSBpcyB1c2VkLCB1c2UgdGhlIHRyaWNrIGJ5IERpZWdvIFBlcmluaQ0KCQkJCS8vIGh0dHA6Ly9qYXZhc2NyaXB0Lm53Ym94LmNvbS9JRUNvbnRlbnRMb2FkZWQvDQoJCQkJZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmRvU2Nyb2xsKCJsZWZ0Iik7DQoJCQl9IGNhdGNoKCBlcnJvciApIHsNCgkJCQlzZXRUaW1lb3V0KCBhcmd1bWVudHMuY2FsbGVlLCAwICk7DQoJCQkJcmV0dXJuOw0KCQkJfQ0KDQoJCQkvLyBhbmQgZXhlY3V0ZSBhbnkgd2FpdGluZyBmdW5jdGlvbnMNCgkJCWpRdWVyeS5yZWFkeSgpOw0KCQl9KSgpOw0KCX0NCg0KCS8vIEEgZmFsbGJhY2sgdG8gd2luZG93Lm9ubG9hZCwgdGhhdCB3aWxsIGFsd2F5cyB3b3JrDQoJalF1ZXJ5LmV2ZW50LmFkZCggd2luZG93LCAibG9hZCIsIGpRdWVyeS5yZWFkeSApOw0KfQ0KDQovLyBbdnNkb2NdIFRoZSBmb2xsb3dpbmcgc2VjdGlvbiBoYXMgYmVlbiBkZW5vcm1hbGl6ZWQgZnJvbSBvcmlnaW5hbCBzb3VyY2VzIGZvciBJbnRlbGxpU2Vuc2UuDQoNCmpRdWVyeS5lYWNoKCAoImJsdXIsZm9jdXMsbG9hZCxyZXNpemUsc2Nyb2xsLHVubG9hZCxjbGljayxkYmxjbGljaywiICsNCgkibW91c2Vkb3duLG1vdXNldXAsbW91c2Vtb3ZlLG1vdXNlb3Zlcixtb3VzZW91dCxtb3VzZWVudGVyLG1vdXNlbGVhdmUsIiArDQoJImNoYW5nZSxzZWxlY3Qsc3VibWl0LGtleWRvd24sa2V5cHJlc3Msa2V5dXAsZXJyb3IiKS5zcGxpdCgiLCIpLCBmdW5jdGlvbihpLCBuYW1lKXsNCg0KCS8vIEhhbmRsZSBldmVudCBiaW5kaW5nDQoJalF1ZXJ5LmZuW25hbWVdID0gZnVuY3Rpb24oZm4pew0KCQlyZXR1cm4gZm4gPyB0aGlzLmJpbmQobmFtZSwgZm4pIDogdGhpcy50cmlnZ2VyKG5hbWUpOw0KCX07DQp9KTsNCg0KalF1ZXJ5LmZuWyJibHVyIl0gPSBmdW5jdGlvbihmbikgew0KCS8vLwk8c3VtbWFyeT4NCgkvLy8JCTE6IGJsdXIoKSAtIFRyaWdnZXJzIHRoZSBibHVyIGV2ZW50IG9mIGVhY2ggbWF0Y2hlZCBlbGVtZW50Lg0KCS8vLwkJMjogYmx1cihmbikgLSBCaW5kcyBhIGZ1bmN0aW9uIHRvIHRoZSBibHVyIGV2ZW50IG9mIGVhY2ggbWF0Y2hlZCBlbGVtZW50Lg0KCS8vLwk8L3N1bW1hcnk+DQoJLy8vCTxwYXJhbSBuYW1lPSJmbiIgdHlwZT0iRnVuY3Rpb24iPlRoZSBmdW5jdGlvbiB0byBleGVjdXRlLjwvcGFyYW0+DQoJLy8vCTxyZXR1cm5zIHR5cGU9ImpRdWVyeSIgLz4NCglyZXR1cm4gZm4gPyB0aGlzLmJpbmQoImJsdXIiLCBmbikgOiB0aGlzLnRyaWdnZXIobmFtZSk7DQp9Ow0KDQpqUXVlcnkuZm5bImZvY3VzIl0gPSBmdW5jdGlvbihmbikgew0KCS8vLwk8c3VtbWFyeT4NCgkvLy8JCTE6IGZvY3VzKCkgLSBUcmlnZ2VycyB0aGUgZm9jdXMgZXZlbnQgb2YgZWFjaCBtYXRjaGVkIGVsZW1lbnQuDQoJLy8vCQkyOiBmb2N1cyhmbikgLSBCaW5kcyBhIGZ1bmN0aW9uIHRvIHRoZSBmb2N1cyBldmVudCBvZiBlYWNoIG1hdGNoZWQgZWxlbWVudC4NCgkvLy8JPC9zdW1tYXJ5Pg0KCS8vLwk8cGFyYW0gbmFtZT0iZm4iIHR5cGU9IkZ1bmN0aW9uIj5UaGUgZnVuY3Rpb24gdG8gZXhlY3V0ZS48L3BhcmFtPg0KCS8vLwk8cmV0dXJucyB0eXBlPSJqUXVlcnkiIC8+DQoJcmV0dXJuIGZuID8gdGhpcy5iaW5kKCJmb2N1cyIsIGZuKSA6IHRoaXMudHJpZ2dlcihuYW1lKTsNCn07DQoNCmpRdWVyeS5mblsibG9hZCJdID0gZnVuY3Rpb24oZm4pIHsNCgkvLy8JPHN1bW1hcnk+DQoJLy8vCQkxOiBsb2FkKCkgLSBUcmlnZ2VycyB0aGUgbG9hZCBldmVudCBvZiBlYWNoIG1hdGNoZWQgZWxlbWVudC4NCgkvLy8JCTI6IGxvYWQoZm4pIC0gQmluZHMgYSBmdW5jdGlvbiB0byB0aGUgbG9hZCBldmVudCBvZiBlYWNoIG1hdGNoZWQgZWxlbWVudC4NCgkvLy8JPC9zdW1tYXJ5Pg0KCS8vLwk8cGFyYW0gbmFtZT0iZm4iIHR5cGU9IkZ1bmN0aW9uIj5UaGUgZnVuY3Rpb24gdG8gZXhlY3V0ZS48L3BhcmFtPg0KCS8vLwk8cmV0dXJucyB0eXBlPSJqUXVlcnkiIC8+DQoJcmV0dXJuIGZuID8gdGhpcy5iaW5kKCJsb2FkIiwgZm4pIDogdGhpcy50cmlnZ2VyKG5hbWUpOw0KfTsNCg0KalF1ZXJ5LmZuWyJyZXNpemUiXSA9IGZ1bmN0aW9uKGZuKSB7DQoJLy8vCTxzdW1tYXJ5Pg0KCS8vLwkJMTogcmVzaXplKCkgLSBUcmlnZ2VycyB0aGUgcmVzaXplIGV2ZW50IG9mIGVhY2ggbWF0Y2hlZCBlbGVtZW50Lg0KCS8vLwkJMjogcmVzaXplKGZuKSAtIEJpbmRzIGEgZnVuY3Rpb24gdG8gdGhlIHJlc2l6ZSBldmVudCBvZiBlYWNoIG1hdGNoZWQgZWxlbWVudC4NCgkvLy8JPC9zdW1tYXJ5Pg0KCS8vLwk8cGFyYW0gbmFtZT0iZm4iIHR5cGU9IkZ1bmN0aW9uIj5UaGUgZnVuY3Rpb24gdG8gZXhlY3V0ZS48L3BhcmFtPg0KCS8vLwk8cmV0dXJucyB0eXBlPSJqUXVlcnkiIC8+DQoJcmV0dXJuIGZuID8gdGhpcy5iaW5kKCJyZXNpemUiLCBmbikgOiB0aGlzLnRyaWdnZXIobmFtZSk7DQp9Ow0KDQpqUXVlcnkuZm5bInNjcm9sbCJdID0gZnVuY3Rpb24oZm4pIHsNCgkvLy8JPHN1bW1hcnk+DQoJLy8vCQkxOiBzY3JvbGwoKSAtIFRyaWdnZXJzIHRoZSBzY3JvbGwgZXZlbnQgb2YgZWFjaCBtYXRjaGVkIGVsZW1lbnQuDQoJLy8vCQkyOiBzY3JvbGwoZm4pIC0gQmluZHMgYSBmdW5jdGlvbiB0byB0aGUgc2Nyb2xsIGV2ZW50IG9mIGVhY2ggbWF0Y2hlZCBlbGVtZW50Lg0KCS8vLwk8L3N1bW1hcnk+DQoJLy8vCTxwYXJhbSBuYW1lPSJmbiIgdHlwZT0iRnVuY3Rpb24iPlRoZSBmdW5jdGlvbiB0byBleGVjdXRlLjwvcGFyYW0+DQoJLy8vCTxyZXR1cm5zIHR5cGU9ImpRdWVyeSIgLz4NCglyZXR1cm4gZm4gPyB0aGlzLmJpbmQoInNjcm9sbCIsIGZuKSA6IHRoaXMudHJpZ2dlcihuYW1lKTsNCn07DQoNCmpRdWVyeS5mblsidW5sb2FkIl0gPSBmdW5jdGlvbihmbikgew0KCS8vLwk8c3VtbWFyeT4NCgkvLy8JCTE6IHVubG9hZCgpIC0gVHJpZ2dlcnMgdGhlIHVubG9hZCBldmVudCBvZiBlYWNoIG1hdGNoZWQgZWxlbWVudC4NCgkvLy8JCTI6IHVubG9hZChmbikgLSBCaW5kcyBhIGZ1bmN0aW9uIHRvIHRoZSB1bmxvYWQgZXZlbnQgb2YgZWFjaCBtYXRjaGVkIGVsZW1lbnQuDQoJLy8vCTwvc3VtbWFyeT4NCgkvLy8JPHBhcmFtIG5hbWU9ImZuIiB0eXBlPSJGdW5jdGlvbiI+VGhlIGZ1bmN0aW9uIHRvIGV4ZWN1dGUuPC9wYXJhbT4NCgkvLy8JPHJldHVybnMgdHlwZT0ialF1ZXJ5IiAvPg0KCXJldHVybiBmbiA/IHRoaXMuYmluZCgidW5sb2FkIiwgZm4pIDogdGhpcy50cmlnZ2VyKG5hbWUpOw0KfTsNCg0KalF1ZXJ5LmZuWyJjbGljayJdID0gZnVuY3Rpb24oZm4pIHsNCgkvLy8JPHN1bW1hcnk+DQoJLy8vCQkxOiBjbGljaygpIC0gVHJpZ2dlcnMgdGhlIGNsaWNrIGV2ZW50IG9mIGVhY2ggbWF0Y2hlZCBlbGVtZW50Lg0KCS8vLwkJMjogY2xpY2soZm4pIC0gQmluZHMgYSBmdW5jdGlvbiB0byB0aGUgY2xpY2sgZXZlbnQgb2YgZWFjaCBtYXRjaGVkIGVsZW1lbnQuDQoJLy8vCTwvc3VtbWFyeT4NCgkvLy8JPHBhcmFtIG5hbWU9ImZuIiB0eXBlPSJGdW5jdGlvbiI+VGhlIGZ1bmN0aW9uIHRvIGV4ZWN1dGUuPC9wYXJhbT4NCgkvLy8JPHJldHVybnMgdHlwZT0ialF1ZXJ5IiAvPg0KCXJldHVybiBmbiA/IHRoaXMuYmluZCgiY2xpY2siLCBmbikgOiB0aGlzLnRyaWdnZXIobmFtZSk7DQp9Ow0KDQpqUXVlcnkuZm5bImRibGNsaWNrIl0gPSBmdW5jdGlvbihmbikgew0KCS8vLwk8c3VtbWFyeT4NCgkvLy8JCTE6IGRibGNsaWNrKCkgLSBUcmlnZ2VycyB0aGUgZGJsY2xpY2sgZXZlbnQgb2YgZWFjaCBtYXRjaGVkIGVsZW1lbnQuDQoJLy8vCQkyOiBkYmxjbGljayhmbikgLSBCaW5kcyBhIGZ1bmN0aW9uIHRvIHRoZSBkYmxjbGljayBldmVudCBvZiBlYWNoIG1hdGNoZWQgZWxlbWVudC4NCgkvLy8JPC9zdW1tYXJ5Pg0KCS8vLwk8cGFyYW0gbmFtZT0iZm4iIHR5cGU9IkZ1bmN0aW9uIj5UaGUgZnVuY3Rpb24gdG8gZXhlY3V0ZS48L3BhcmFtPg0KCS8vLwk8cmV0dXJucyB0eXBlPSJqUXVlcnkiIC8+DQoJcmV0dXJuIGZuID8gdGhpcy5iaW5kKCJkYmxjbGljayIsIGZuKSA6IHRoaXMudHJpZ2dlcihuYW1lKTsNCn07DQoNCmpRdWVyeS5mblsibW91c2Vkb3duIl0gPSBmdW5jdGlvbihmbikgew0KCS8vLwk8c3VtbWFyeT4NCgkvLy8JCUJpbmRzIGEgZnVuY3Rpb24gdG8gdGhlIG1vdXNlZG93biBldmVudCBvZiBlYWNoIG1hdGNoZWQgZWxlbWVudC4gDQoJLy8vCTwvc3VtbWFyeT4NCgkvLy8JPHBhcmFtIG5hbWU9ImZuIiB0eXBlPSJGdW5jdGlvbiI+VGhlIGZ1bmN0aW9uIHRvIGV4ZWN1dGUuPC9wYXJhbT4NCgkvLy8JPHJldHVybnMgdHlwZT0ialF1ZXJ5IiAvPg0KCXJldHVybiBmbiA/IHRoaXMuYmluZCgibW91c2Vkb3duIiwgZm4pIDogdGhpcy50cmlnZ2VyKG5hbWUpOw0KfTsNCg0KalF1ZXJ5LmZuWyJtb3VzZXVwIl0gPSBmdW5jdGlvbihmbikgew0KCS8vLwk8c3VtbWFyeT4NCgkvLy8JCUJpbmQgYSBmdW5jdGlvbiB0byB0aGUgbW91c2V1cCBldmVudCBvZiBlYWNoIG1hdGNoZWQgZWxlbWVudC4NCgkvLy8JPC9zdW1tYXJ5Pg0KCS8vLwk8cGFyYW0gbmFtZT0iZm4iIHR5cGU9IkZ1bmN0aW9uIj5UaGUgZnVuY3Rpb24gdG8gZXhlY3V0ZS48L3BhcmFtPg0KCS8vLwk8cmV0dXJucyB0eXBlPSJqUXVlcnkiIC8+DQoJcmV0dXJuIGZuID8gdGhpcy5iaW5kKCJtb3VzZXVwIiwgZm4pIDogdGhpcy50cmlnZ2VyKG5hbWUpOw0KfTsNCg0KalF1ZXJ5LmZuWyJtb3VzZW1vdmUiXSA9IGZ1bmN0aW9uKGZuKSB7DQoJLy8vCTxzdW1tYXJ5Pg0KCS8vLwkJQmluZCBhIGZ1bmN0aW9uIHRvIHRoZSBtb3VzZW1vdmUgZXZlbnQgb2YgZWFjaCBtYXRjaGVkIGVsZW1lbnQuDQoJLy8vCTwvc3VtbWFyeT4NCgkvLy8JPHBhcmFtIG5hbWU9ImZuIiB0eXBlPSJGdW5jdGlvbiI+VGhlIGZ1bmN0aW9uIHRvIGV4ZWN1dGUuPC9wYXJhbT4NCgkvLy8JPHJldHVybnMgdHlwZT0ialF1ZXJ5IiAvPg0KCXJldHVybiBmbiA/IHRoaXMuYmluZCgibW91c2Vtb3ZlIiwgZm4pIDogdGhpcy50cmlnZ2VyKG5hbWUpOw0KfTsNCg0KalF1ZXJ5LmZuWyJtb3VzZW92ZXIiXSA9IGZ1bmN0aW9uKGZuKSB7DQoJLy8vCTxzdW1tYXJ5Pg0KCS8vLwkJQmluZCBhIGZ1bmN0aW9uIHRvIHRoZSBtb3VzZW92ZXIgZXZlbnQgb2YgZWFjaCBtYXRjaGVkIGVsZW1lbnQuIA0KCS8vLwk8L3N1bW1hcnk+DQoJLy8vCTxwYXJhbSBuYW1lPSJmbiIgdHlwZT0iRnVuY3Rpb24iPlRoZSBmdW5jdGlvbiB0byBleGVjdXRlLjwvcGFyYW0+DQoJLy8vCTxyZXR1cm5zIHR5cGU9ImpRdWVyeSIgLz4NCglyZXR1cm4gZm4gPyB0aGlzLmJpbmQoIm1vdXNlb3ZlciIsIGZuKSA6IHRoaXMudHJpZ2dlcihuYW1lKTsNCn07DQoNCmpRdWVyeS5mblsibW91c2VvdXQiXSA9IGZ1bmN0aW9uKGZuKSB7DQoJLy8vCTxzdW1tYXJ5Pg0KCS8vLwkJQmluZCBhIGZ1bmN0aW9uIHRvIHRoZSBtb3VzZW91dCBldmVudCBvZiBlYWNoIG1hdGNoZWQgZWxlbWVudC4gDQoJLy8vCTwvc3VtbWFyeT4NCgkvLy8JPHBhcmFtIG5hbWU9ImZuIiB0eXBlPSJGdW5jdGlvbiI+VGhlIGZ1bmN0aW9uIHRvIGV4ZWN1dGUuPC9wYXJhbT4NCgkvLy8JPHJldHVybnMgdHlwZT0ialF1ZXJ5IiAvPg0KCXJldHVybiBmbiA/IHRoaXMuYmluZCgibW91c2VvdXQiLCBmbikgOiB0aGlzLnRyaWdnZXIobmFtZSk7DQp9Ow0KDQpqUXVlcnkuZm5bIm1vdXNlZW50ZXIiXSA9IGZ1bmN0aW9uKGZuKSB7DQoJLy8vCTxzdW1tYXJ5Pg0KCS8vLwkJQmluZCBhIGZ1bmN0aW9uIHRvIHRoZSBtb3VzZWVudGVyIGV2ZW50IG9mIGVhY2ggbWF0Y2hlZCBlbGVtZW50LiANCgkvLy8JPC9zdW1tYXJ5Pg0KCS8vLwk8cGFyYW0gbmFtZT0iZm4iIHR5cGU9IkZ1bmN0aW9uIj5UaGUgZnVuY3Rpb24gdG8gZXhlY3V0ZS48L3BhcmFtPg0KCS8vLwk8cmV0dXJucyB0eXBlPSJqUXVlcnkiIC8+DQoJcmV0dXJuIGZuID8gdGhpcy5iaW5kKCJtb3VzZWVudGVyIiwgZm4pIDogdGhpcy50cmlnZ2VyKG5hbWUpOw0KfTsNCg0KalF1ZXJ5LmZuWyJtb3VzZWxlYXZlIl0gPSBmdW5jdGlvbihmbikgew0KCS8vLwk8c3VtbWFyeT4NCgkvLy8JCUJpbmQgYSBmdW5jdGlvbiB0byB0aGUgbW91c2VsZWF2ZSBldmVudCBvZiBlYWNoIG1hdGNoZWQgZWxlbWVudC4gDQoJLy8vCTwvc3VtbWFyeT4NCgkvLy8JPHBhcmFtIG5hbWU9ImZuIiB0eXBlPSJGdW5jdGlvbiI+VGhlIGZ1bmN0aW9uIHRvIGV4ZWN1dGUuPC9wYXJhbT4NCgkvLy8JPHJldHVybnMgdHlwZT0ialF1ZXJ5IiAvPg0KCXJldHVybiBmbiA/IHRoaXMuYmluZCgibW91c2VsZWF2ZSIsIGZuKSA6IHRoaXMudHJpZ2dlcihuYW1lKTsNCn07DQoNCmpRdWVyeS5mblsiY2hhbmdlIl0gPSBmdW5jdGlvbihmbikgew0KCS8vLwk8c3VtbWFyeT4NCgkvLy8JCTE6IGNoYW5nZSgpIC0gVHJpZ2dlcnMgdGhlIGNoYW5nZSBldmVudCBvZiBlYWNoIG1hdGNoZWQgZWxlbWVudC4NCgkvLy8JCTI6IGNoYW5nZShmbikgLSBCaW5kcyBhIGZ1bmN0aW9uIHRvIHRoZSBjaGFuZ2UgZXZlbnQgb2YgZWFjaCBtYXRjaGVkIGVsZW1lbnQuDQoJLy8vCTwvc3VtbWFyeT4NCgkvLy8JPHBhcmFtIG5hbWU9ImZuIiB0eXBlPSJGdW5jdGlvbiI+VGhlIGZ1bmN0aW9uIHRvIGV4ZWN1dGUuPC9wYXJhbT4NCgkvLy8JPHJldHVybnMgdHlwZT0ialF1ZXJ5IiAvPg0KCXJldHVybiBmbiA/IHRoaXMuYmluZCgiY2hhbmdlIiwgZm4pIDogdGhpcy50cmlnZ2VyKG5hbWUpOw0KfTsNCg0KalF1ZXJ5LmZuWyJzZWxlY3QiXSA9IGZ1bmN0aW9uKGZuKSB7DQoJLy8vCTxzdW1tYXJ5Pg0KCS8vLwkJMTogc2VsZWN0KCkgLSBUcmlnZ2VycyB0aGUgc2VsZWN0IGV2ZW50IG9mIGVhY2ggbWF0Y2hlZCBlbGVtZW50Lg0KCS8vLwkJMjogc2VsZWN0KGZuKSAtIEJpbmRzIGEgZnVuY3Rpb24gdG8gdGhlIHNlbGVjdCBldmVudCBvZiBlYWNoIG1hdGNoZWQgZWxlbWVudC4NCgkvLy8JPC9zdW1tYXJ5Pg0KCS8vLwk8cGFyYW0gbmFtZT0iZm4iIHR5cGU9IkZ1bmN0aW9uIj5UaGUgZnVuY3Rpb24gdG8gZXhlY3V0ZS48L3BhcmFtPg0KCS8vLwk8cmV0dXJucyB0eXBlPSJqUXVlcnkiIC8+DQoJcmV0dXJuIGZuID8gdGhpcy5iaW5kKCJzZWxlY3QiLCBmbikgOiB0aGlzLnRyaWdnZXIobmFtZSk7DQp9Ow0KDQpqUXVlcnkuZm5bInN1Ym1pdCJdID0gZnVuY3Rpb24oZm4pIHsNCgkvLy8JPHN1bW1hcnk+DQoJLy8vCQkxOiBzdWJtaXQoKSAtIFRyaWdnZXJzIHRoZSBzdWJtaXQgZXZlbnQgb2YgZWFjaCBtYXRjaGVkIGVsZW1lbnQuDQoJLy8vCQkyOiBzdWJtaXQoZm4pIC0gQmluZHMgYSBmdW5jdGlvbiB0byB0aGUgc3VibWl0IGV2ZW50IG9mIGVhY2ggbWF0Y2hlZCBlbGVtZW50Lg0KCS8vLwk8L3N1bW1hcnk+DQoJLy8vCTxwYXJhbSBuYW1lPSJmbiIgdHlwZT0iRnVuY3Rpb24iPlRoZSBmdW5jdGlvbiB0byBleGVjdXRlLjwvcGFyYW0+DQoJLy8vCTxyZXR1cm5zIHR5cGU9ImpRdWVyeSIgLz4NCglyZXR1cm4gZm4gPyB0aGlzLmJpbmQoInN1Ym1pdCIsIGZuKSA6IHRoaXMudHJpZ2dlcihuYW1lKTsNCn07DQoNCmpRdWVyeS5mblsia2V5ZG93biJdID0gZnVuY3Rpb24oZm4pIHsNCgkvLy8JPHN1bW1hcnk+DQoJLy8vCQkxOiBrZXlkb3duKCkgLSBUcmlnZ2VycyB0aGUga2V5ZG93biBldmVudCBvZiBlYWNoIG1hdGNoZWQgZWxlbWVudC4NCgkvLy8JCTI6IGtleWRvd24oZm4pIC0gQmluZHMgYSBmdW5jdGlvbiB0byB0aGUga2V5ZG93biBldmVudCBvZiBlYWNoIG1hdGNoZWQgZWxlbWVudC4NCgkvLy8JPC9zdW1tYXJ5Pg0KCS8vLwk8cGFyYW0gbmFtZT0iZm4iIHR5cGU9IkZ1bmN0aW9uIj5UaGUgZnVuY3Rpb24gdG8gZXhlY3V0ZS48L3BhcmFtPg0KCS8vLwk8cmV0dXJucyB0eXBlPSJqUXVlcnkiIC8+DQoJcmV0dXJuIGZuID8gdGhpcy5iaW5kKCJrZXlkb3duIiwgZm4pIDogdGhpcy50cmlnZ2VyKG5hbWUpOw0KfTsNCg0KalF1ZXJ5LmZuWyJrZXlwcmVzcyJdID0gZnVuY3Rpb24oZm4pIHsNCgkvLy8JPHN1bW1hcnk+DQoJLy8vCQkxOiBrZXlwcmVzcygpIC0gVHJpZ2dlcnMgdGhlIGtleXByZXNzIGV2ZW50IG9mIGVhY2ggbWF0Y2hlZCBlbGVtZW50Lg0KCS8vLwkJMjoga2V5cHJlc3MoZm4pIC0gQmluZHMgYSBmdW5jdGlvbiB0byB0aGUga2V5cHJlc3MgZXZlbnQgb2YgZWFjaCBtYXRjaGVkIGVsZW1lbnQuDQoJLy8vCTwvc3VtbWFyeT4NCgkvLy8JPHBhcmFtIG5hbWU9ImZuIiB0eXBlPSJGdW5jdGlvbiI+VGhlIGZ1bmN0aW9uIHRvIGV4ZWN1dGUuPC9wYXJhbT4NCgkvLy8JPHJldHVybnMgdHlwZT0ialF1ZXJ5IiAvPg0KCXJldHVybiBmbiA/IHRoaXMuYmluZCgia2V5cHJlc3MiLCBmbikgOiB0aGlzLnRyaWdnZXIobmFtZSk7DQp9Ow0KDQpqUXVlcnkuZm5bImtleXVwIl0gPSBmdW5jdGlvbihmbikgew0KCS8vLwk8c3VtbWFyeT4NCgkvLy8JCTE6IGtleXVwKCkgLSBUcmlnZ2VycyB0aGUga2V5dXAgZXZlbnQgb2YgZWFjaCBtYXRjaGVkIGVsZW1lbnQuDQoJLy8vCQkyOiBrZXl1cChmbikgLSBCaW5kcyBhIGZ1bmN0aW9uIHRvIHRoZSBrZXl1cCBldmVudCBvZiBlYWNoIG1hdGNoZWQgZWxlbWVudC4NCgkvLy8JPC9zdW1tYXJ5Pg0KCS8vLwk8cGFyYW0gbmFtZT0iZm4iIHR5cGU9IkZ1bmN0aW9uIj5UaGUgZnVuY3Rpb24gdG8gZXhlY3V0ZS48L3BhcmFtPg0KCS8vLwk8cmV0dXJucyB0eXBlPSJqUXVlcnkiIC8+DQoJcmV0dXJuIGZuID8gdGhpcy5iaW5kKCJrZXl1cCIsIGZuKSA6IHRoaXMudHJpZ2dlcihuYW1lKTsNCn07DQoNCmpRdWVyeS5mblsiZXJyb3IiXSA9IGZ1bmN0aW9uKGZuKSB7DQoJLy8vCTxzdW1tYXJ5Pg0KCS8vLwkJMTogZXJyb3IoKSAtIFRyaWdnZXJzIHRoZSBlcnJvciBldmVudCBvZiBlYWNoIG1hdGNoZWQgZWxlbWVudC4NCgkvLy8JCTI6IGVycm9yKGZuKSAtIEJpbmRzIGEgZnVuY3Rpb24gdG8gdGhlIGVycm9yIGV2ZW50IG9mIGVhY2ggbWF0Y2hlZCBlbGVtZW50Lg0KCS8vLwk8L3N1bW1hcnk+DQoJLy8vCTxwYXJhbSBuYW1lPSJmbiIgdHlwZT0iRnVuY3Rpb24iPlRoZSBmdW5jdGlvbiB0byBleGVjdXRlLjwvcGFyYW0+DQoJLy8vCTxyZXR1cm5zIHR5cGU9ImpRdWVyeSIgLz4NCglyZXR1cm4gZm4gPyB0aGlzLmJpbmQoImVycm9yIiwgZm4pIDogdGhpcy50cmlnZ2VyKG5hbWUpOw0KfTsNCg0KLy8gUHJldmVudCBtZW1vcnkgbGVha3MgaW4gSUUNCi8vIEFuZCBwcmV2ZW50IGVycm9ycyBvbiByZWZyZXNoIHdpdGggZXZlbnRzIGxpa2UgbW91c2VvdmVyIGluIG90aGVyIGJyb3dzZXJzDQovLyBXaW5kb3cgaXNuJ3QgaW5jbHVkZWQgc28gYXMgbm90IHRvIHVuYmluZCBleGlzdGluZyB1bmxvYWQgZXZlbnRzDQpqUXVlcnkoIHdpbmRvdyApLmJpbmQoICd1bmxvYWQnLCBmdW5jdGlvbigpeyANCglmb3IgKCB2YXIgaWQgaW4galF1ZXJ5LmNhY2hlICkNCgkJLy8gU2tpcCB0aGUgd2luZG93DQoJCWlmICggaWQgIT0gMSAmJiBqUXVlcnkuY2FjaGVbIGlkIF0uaGFuZGxlICkNCgkJCWpRdWVyeS5ldmVudC5yZW1vdmUoIGpRdWVyeS5jYWNoZVsgaWQgXS5oYW5kbGUuZWxlbSApOw0KfSk7DQoNCi8vIFt2c2RvY10gVGhlIGZvbGxvd2luZyBmdW5jdGlvbiBoYXMgYmVlbiBtb2RpZmllZCBmb3IgSW50ZWxsaVNlbnNlLg0KLy8gW3ZzZG9jXSBTdHViYmluZyBzdXBwb3J0IHByb3BlcnRpZXMgdG8gImZhbHNlIiBzaW5jZSB3ZSBzaW11bGF0ZSBJRS4NCihmdW5jdGlvbigpew0KDQoJalF1ZXJ5LnN1cHBvcnQgPSB7fTsNCg0KCWpRdWVyeS5zdXBwb3J0ID0gew0KCQkvLyBJRSBzdHJpcHMgbGVhZGluZyB3aGl0ZXNwYWNlIHdoZW4gLmlubmVySFRNTCBpcyB1c2VkDQoJCWxlYWRpbmdXaGl0ZXNwYWNlOiBmYWxzZSwNCgkJDQoJCS8vIE1ha2Ugc3VyZSB0aGF0IHRib2R5IGVsZW1lbnRzIGFyZW4ndCBhdXRvbWF0aWNhbGx5IGluc2VydGVkDQoJCS8vIElFIHdpbGwgaW5zZXJ0IHRoZW0gaW50byBlbXB0eSB0YWJsZXMNCgkJdGJvZHk6IGZhbHNlLA0KCQkNCgkJLy8gTWFrZSBzdXJlIHRoYXQgeW91IGNhbiBnZXQgYWxsIGVsZW1lbnRzIGluIGFuIDxvYmplY3Q+IGVsZW1lbnQNCgkJLy8gSUUgNyBhbHdheXMgcmV0dXJucyBubyByZXN1bHRzDQoJCW9iamVjdEFsbDogZmFsc2UsDQoJCQ0KCQkvLyBNYWtlIHN1cmUgdGhhdCBsaW5rIGVsZW1lbnRzIGdldCBzZXJpYWxpemVkIGNvcnJlY3RseSBieSBpbm5lckhUTUwNCgkJLy8gVGhpcyByZXF1aXJlcyBhIHdyYXBwZXIgZWxlbWVudCBpbiBJRQ0KCQlodG1sU2VyaWFsaXplOiBmYWxzZSwNCgkJDQoJCS8vIEdldCB0aGUgc3R5bGUgaW5mb3JtYXRpb24gZnJvbSBnZXRBdHRyaWJ1dGUNCgkJLy8gKElFIHVzZXMgLmNzc1RleHQgaW5zdGVkKQ0KCQlzdHlsZTogZmFsc2UsDQoJCQ0KCQkvLyBNYWtlIHN1cmUgdGhhdCBVUkxzIGFyZW4ndCBtYW5pcHVsYXRlZA0KCQkvLyAoSUUgbm9ybWFsaXplcyBpdCBieSBkZWZhdWx0KQ0KCQlocmVmTm9ybWFsaXplZDogZmFsc2UsDQoJCQ0KCQkvLyBNYWtlIHN1cmUgdGhhdCBlbGVtZW50IG9wYWNpdHkgZXhpc3RzDQoJCS8vIChJRSB1c2VzIGZpbHRlciBpbnN0ZWFkKQ0KCQlvcGFjaXR5OiBmYWxzZSwNCgkJDQoJCS8vIFZlcmlmeSBzdHlsZSBmbG9hdCBleGlzdGVuY2UNCgkJLy8gKElFIHVzZXMgc3R5bGVGbG9hdCBpbnN0ZWFkIG9mIGNzc0Zsb2F0KQ0KCQljc3NGbG9hdDogZmFsc2UsDQoNCgkJLy8gV2lsbCBiZSBkZWZpbmVkIGxhdGVyDQoJCXNjcmlwdEV2YWw6IGZhbHNlLA0KCQlub0Nsb25lRXZlbnQ6IGZhbHNlLA0KCQlib3hNb2RlbDogZmFsc2UNCgl9Ow0KDQp9KSgpOw0KDQovLyBbdnNkb2NdIFRoZSBmb2xsb3dpbmcgbWVtYmVyIGhhcyBiZWVuIG1vZGlmaWVkIGZvciBJbnRlbGxpU2Vuc2UuDQp2YXIgc3R5bGVGbG9hdCA9ICJzdHlsZUZsb2F0IjsNCg0KalF1ZXJ5LnByb3BzID0gew0KCSJmb3IiOiAiaHRtbEZvciIsDQoJImNsYXNzIjogImNsYXNzTmFtZSIsDQoJImZsb2F0Ijogc3R5bGVGbG9hdCwNCgljc3NGbG9hdDogc3R5bGVGbG9hdCwNCglzdHlsZUZsb2F0OiBzdHlsZUZsb2F0LA0KCXJlYWRvbmx5OiAicmVhZE9ubHkiLA0KCW1heGxlbmd0aDogIm1heExlbmd0aCIsDQoJY2VsbHNwYWNpbmc6ICJjZWxsU3BhY2luZyIsDQoJcm93c3BhbjogInJvd1NwYW4iLA0KCXRhYmluZGV4OiAidGFiSW5kZXgiDQp9Ow0KalF1ZXJ5LmZuLmV4dGVuZCh7DQoJLy8gS2VlcCBhIGNvcHkgb2YgdGhlIG9sZCBsb2FkDQoJX2xvYWQ6IGpRdWVyeS5mbi5sb2FkLA0KDQoJbG9hZDogZnVuY3Rpb24oIHVybCwgcGFyYW1zLCBjYWxsYmFjayApIHsNCgkJLy8vCTxzdW1tYXJ5Pg0KCQkvLy8JCUxvYWRzIEhUTUwgZnJvbSBhIHJlbW90ZSBmaWxlIGFuZCBpbmplY3RzIGl0IGludG8gdGhlIERPTS4gIEJ5IGRlZmF1bHQgcGVyZm9ybXMgYSBHRVQgcmVxdWVzdCwgYnV0IGlmIHBhcmFtZXRlcnMgYXJlIGluY2x1ZGVkDQoJCS8vLwkJdGhlbiBhIFBPU1Qgd2lsbCBiZSBwZXJmb3JtZWQuDQoJCS8vLwk8L3N1bW1hcnk+DQoJCS8vLwk8cGFyYW0gbmFtZT0idXJsIiB0eXBlPSJTdHJpbmciPlRoZSBVUkwgb2YgdGhlIEhUTUwgcGFnZSB0byBsb2FkLjwvcGFyYW0+DQoJCS8vLwk8cGFyYW0gbmFtZT0iZGF0YSIgb3B0aW9uYWw9InRydWUiIHR5cGU9Ik1hcCI+S2V5L3ZhbHVlIHBhaXJzIHRoYXQgd2lsbCBiZSBzZW50IHRvIHRoZSBzZXJ2ZXIuPC9wYXJhbT4NCgkJLy8vCTxwYXJhbSBuYW1lPSJjYWxsYmFjayIgb3B0aW9uYWw9InRydWUiIHR5cGU9IkZ1bmN0aW9uIj5UaGUgZnVuY3Rpb24gY2FsbGVkIHdoZW4gdGhlIEFKQVggcmVxdWVzdCBpcyBjb21wbGV0ZS4gIEl0IHNob3VsZCBtYXAgZnVuY3Rpb24ocmVzcG9uc2VUZXh0LCB0ZXh0U3RhdHVzLCBYTUxIdHRwUmVxdWVzdCkgc3VjaCB0aGF0IHRoaXMgbWFwcyB0aGUgaW5qZWN0ZWQgRE9NIGVsZW1lbnQuPC9wYXJhbT4NCgkJLy8vCTxyZXR1cm5zIHR5cGU9ImpRdWVyeSIgLz4NCgkJDQoJCWlmICggdHlwZW9mIHVybCAhPT0gInN0cmluZyIgKQ0KCQkJcmV0dXJuIHRoaXMuX2xvYWQoIHVybCApOw0KDQoJCXZhciBvZmYgPSB1cmwuaW5kZXhPZigiICIpOw0KCQlpZiAoIG9mZiA+PSAwICkgew0KCQkJdmFyIHNlbGVjdG9yID0gdXJsLnNsaWNlKG9mZiwgdXJsLmxlbmd0aCk7DQoJCQl1cmwgPSB1cmwuc2xpY2UoMCwgb2ZmKTsNCgkJfQ0KDQoJCS8vIERlZmF1bHQgdG8gYSBHRVQgcmVxdWVzdA0KCQl2YXIgdHlwZSA9ICJHRVQiOw0KDQoJCS8vIElmIHRoZSBzZWNvbmQgcGFyYW1ldGVyIHdhcyBwcm92aWRlZA0KCQlpZiAoIHBhcmFtcyApDQoJCQkvLyBJZiBpdCdzIGEgZnVuY3Rpb24NCgkJCWlmICggalF1ZXJ5LmlzRnVuY3Rpb24oIHBhcmFtcyApICkgew0KCQkJCS8vIFdlIGFzc3VtZSB0aGF0IGl0J3MgdGhlIGNhbGxiYWNrDQoJCQkJY2FsbGJhY2sgPSBwYXJhbXM7DQoJCQkJcGFyYW1zID0gbnVsbDsNCg0KCQkJLy8gT3RoZXJ3aXNlLCBidWlsZCBhIHBhcmFtIHN0cmluZw0KCQkJfSBlbHNlIGlmKCB0eXBlb2YgcGFyYW1zID09PSAib2JqZWN0IiApIHsNCgkJCQlwYXJhbXMgPSBqUXVlcnkucGFyYW0oIHBhcmFtcyApOw0KCQkJCXR5cGUgPSAiUE9TVCI7DQoJCQl9DQoNCgkJdmFyIHNlbGYgPSB0aGlzOw0KDQoJCS8vIFJlcXVlc3QgdGhlIHJlbW90ZSBkb2N1bWVudA0KCQlqUXVlcnkuYWpheCh7DQoJCQl1cmw6IHVybCwNCgkJCXR5cGU6IHR5cGUsDQoJCQlkYXRhVHlwZTogImh0bWwiLA0KCQkJZGF0YTogcGFyYW1zLA0KCQkJY29tcGxldGU6IGZ1bmN0aW9uKHJlcywgc3RhdHVzKXsNCgkJCQkvLyBJZiBzdWNjZXNzZnVsLCBpbmplY3QgdGhlIEhUTUwgaW50byBhbGwgdGhlIG1hdGNoZWQgZWxlbWVudHMNCgkJCQlpZiAoIHN0YXR1cyA9PSAic3VjY2VzcyIgfHwgc3RhdHVzID09ICJub3Rtb2RpZmllZCIgKQ0KCQkJCQkvLyBTZWUgaWYgYSBzZWxlY3RvciB3YXMgc3BlY2lmaWVkDQoJCQkJCXNlbGYuaHRtbCggc2VsZWN0b3IgPw0KCQkJCQkJLy8gQ3JlYXRlIGEgZHVtbXkgZGl2IHRvIGhvbGQgdGhlIHJlc3VsdHMNCgkJCQkJCWpRdWVyeSgiPGRpdi8+IikNCgkJCQkJCQkvLyBpbmplY3QgdGhlIGNvbnRlbnRzIG9mIHRoZSBkb2N1bWVudCBpbiwgcmVtb3ZpbmcgdGhlIHNjcmlwdHMNCgkJCQkJCQkvLyB0byBhdm9pZCBhbnkgJ1Blcm1pc3Npb24gRGVuaWVkJyBlcnJvcnMgaW4gSUUNCgkJCQkJCQkuYXBwZW5kKHJlcy5yZXNwb25zZVRleHQucmVwbGFjZSgvPHNjcmlwdCgufFxzKSo/XC9zY3JpcHQ+L2csICIiKSkNCg0KCQkJCQkJCS8vIExvY2F0ZSB0aGUgc3BlY2lmaWVkIGVsZW1lbnRzDQoJCQkJCQkJLmZpbmQoc2VsZWN0b3IpIDoNCg0KCQkJCQkJLy8gSWYgbm90LCBqdXN0IGluamVjdCB0aGUgZnVsbCByZXN1bHQNCgkJCQkJCXJlcy5yZXNwb25zZVRleHQgKTsNCg0KCQkJCWlmKCBjYWxsYmFjayApDQoJCQkJCXNlbGYuZWFjaCggY2FsbGJhY2ssIFtyZXMucmVzcG9uc2VUZXh0LCBzdGF0dXMsIHJlc10gKTsNCgkJCX0NCgkJfSk7DQoJCXJldHVybiB0aGlzOw0KCX0sDQoNCglzZXJpYWxpemU6IGZ1bmN0aW9uKCkgew0KCQkvLy8JPHN1bW1hcnk+DQoJCS8vLwkJU2VyaWFsaXplcyBhIHNldCBvZiBpbnB1dCBlbGVtZW50cyBpbnRvIGEgc3RyaW5nIG9mIGRhdGEuDQoJCS8vLwk8L3N1bW1hcnk+DQoJCS8vLwk8cmV0dXJucyB0eXBlPSJTdHJpbmciPlRoZSBzZXJpYWxpemVkIHJlc3VsdDwvcmV0dXJucz4NCgkNCgkJcmV0dXJuIGpRdWVyeS5wYXJhbSh0aGlzLnNlcmlhbGl6ZUFycmF5KCkpOw0KCX0sDQoJc2VyaWFsaXplQXJyYXk6IGZ1bmN0aW9uKCkgew0KCQkvLy8JPHN1bW1hcnk+DQoJCS8vLwkJU2VyaWFsaXplcyBhbGwgZm9ybXMgYW5kIGZvcm0gZWxlbWVudHMgYnV0IHJldHVybnMgYSBKU09OIGRhdGEgc3RydWN0dXJlLg0KCQkvLy8JPC9zdW1tYXJ5Pg0KCQkvLy8JPHJldHVybnMgdHlwZT0iU3RyaW5nIj5BIEpTT04gZGF0YSBzdHJ1Y3R1cmUgcmVwcmVzZW50aW5nIHRoZSBzZXJpYWxpemVkIGl0ZW1zLjwvcmV0dXJucz4NCgkNCgkJcmV0dXJuIHRoaXMubWFwKGZ1bmN0aW9uKCl7DQoJCQlyZXR1cm4gdGhpcy5lbGVtZW50cyA/IGpRdWVyeS5tYWtlQXJyYXkodGhpcy5lbGVtZW50cykgOiB0aGlzOw0KCQl9KQ0KCQkuZmlsdGVyKGZ1bmN0aW9uKCl7DQoJCQlyZXR1cm4gdGhpcy5uYW1lICYmICF0aGlzLmRpc2FibGVkICYmDQoJCQkJKHRoaXMuY2hlY2tlZCB8fCAvc2VsZWN0fHRleHRhcmVhL2kudGVzdCh0aGlzLm5vZGVOYW1lKSB8fA0KCQkJCQkvdGV4dHxoaWRkZW58cGFzc3dvcmR8c2VhcmNoL2kudGVzdCh0aGlzLnR5cGUpKTsNCgkJfSkNCgkJLm1hcChmdW5jdGlvbihpLCBlbGVtKXsNCgkJCXZhciB2YWwgPSBqUXVlcnkodGhpcykudmFsKCk7DQoJCQlyZXR1cm4gdmFsID09IG51bGwgPyBudWxsIDoNCgkJCQlqUXVlcnkuaXNBcnJheSh2YWwpID8NCgkJCQkJalF1ZXJ5Lm1hcCggdmFsLCBmdW5jdGlvbih2YWwsIGkpew0KCQkJCQkJcmV0dXJuIHtuYW1lOiBlbGVtLm5hbWUsIHZhbHVlOiB2YWx9Ow0KCQkJCQl9KSA6DQoJCQkJCXtuYW1lOiBlbGVtLm5hbWUsIHZhbHVlOiB2YWx9Ow0KCQl9KS5nZXQoKTsNCgl9DQp9KTsNCg0KLy8gW3ZzZG9jXSBUaGUgZm9sbG93aW5nIHNlY3Rpb24gaGFzIGJlZW4gZGVub3JtYWxpemVkIGZyb20gb3JpZ2luYWwgc291cmNlcyBmb3IgSW50ZWxsaVNlbnNlLg0KLy8gQXR0YWNoIGEgYnVuY2ggb2YgZnVuY3Rpb25zIGZvciBoYW5kbGluZyBjb21tb24gQUpBWCBldmVudHMNCi8vIGpRdWVyeS5lYWNoKCAiYWpheFN0YXJ0LGFqYXhTdG9wLGFqYXhDb21wbGV0ZSxhamF4RXJyb3IsYWpheFN1Y2Nlc3MsYWpheFNlbmQiLnNwbGl0KCIsIiksIGZ1bmN0aW9uKGksbyl7DQovLyAJalF1ZXJ5LmZuW29dID0gZnVuY3Rpb24oZil7DQovLyAJCXJldHVybiB0aGlzLmJpbmQobywgZik7DQovLyAJfTsNCi8vIH0pOw0KDQpqUXVlcnkuZm5bImFqYXhTdGFydCJdID0gZnVuY3Rpb24oY2FsbGJhY2spIHsNCgkvLy8JPHN1bW1hcnk+DQoJLy8vCQlBdHRhY2ggYSBmdW5jdGlvbiB0byBiZSBleGVjdXRlZCB3aGVuZXZlciBhbiBBSkFYIHJlcXVlc3QgYmVnaW5zIGFuZCB0aGVyZSBpcyBub25lIGFscmVhZHkgYWN0aXZlLiBUaGlzIGlzIGFuIEFqYXggRXZlbnQuDQoJLy8vCTwvc3VtbWFyeT4NCgkvLy8JPHBhcmFtIG5hbWU9ImNhbGxiYWNrIiB0eXBlPSJGdW5jdGlvbiI+VGhlIGZ1bmN0aW9uIHRvIGV4ZWN1dGUuPC9wYXJhbT4NCgkvLy8JPHJldHVybnMgdHlwZT0ialF1ZXJ5IiAvPg0KCXJldHVybiB0aGlzLmJpbmQoImFqYXhTdGFydCIsIGYpOw0KfTsNCg0KalF1ZXJ5LmZuWyJhamF4U3RvcCJdID0gZnVuY3Rpb24oY2FsbGJhY2spIHsNCgkvLy8JPHN1bW1hcnk+DQoJLy8vCQlBdHRhY2ggYSBmdW5jdGlvbiB0byBiZSBleGVjdXRlZCB3aGVuZXZlciBhbGwgQUpBWCByZXF1ZXN0cyBoYXZlIGVuZGVkLiBUaGlzIGlzIGFuIEFqYXggRXZlbnQuDQoJLy8vCTwvc3VtbWFyeT4NCgkvLy8JPHBhcmFtIG5hbWU9ImNhbGxiYWNrIiB0eXBlPSJGdW5jdGlvbiI+VGhlIGZ1bmN0aW9uIHRvIGV4ZWN1dGUuPC9wYXJhbT4NCgkvLy8JPHJldHVybnMgdHlwZT0ialF1ZXJ5IiAvPg0KCXJldHVybiB0aGlzLmJpbmQoImFqYXhTdG9wIiwgZik7DQp9Ow0KDQpqUXVlcnkuZm5bImFqYXhDb21wbGV0ZSJdID0gZnVuY3Rpb24oY2FsbGJhY2spIHsNCgkvLy8JPHN1bW1hcnk+DQoJLy8vCQlBdHRhY2ggYSBmdW5jdGlvbiB0byBiZSBleGVjdXRlZCB3aGVuZXZlciBhbiBBSkFYIHJlcXVlc3QgY29tcGxldGVzLiBUaGlzIGlzIGFuIEFqYXggRXZlbnQuDQoJLy8vCTwvc3VtbWFyeT4NCgkvLy8JPHBhcmFtIG5hbWU9ImNhbGxiYWNrIiB0eXBlPSJGdW5jdGlvbiI+VGhlIGZ1bmN0aW9uIHRvIGV4ZWN1dGUuPC9wYXJhbT4NCgkvLy8JPHJldHVybnMgdHlwZT0ialF1ZXJ5IiAvPg0KCXJldHVybiB0aGlzLmJpbmQoImFqYXhDb21wbGV0ZSIsIGYpOw0KfTsNCg0KalF1ZXJ5LmZuWyJhamF4RXJyb3IiXSA9IGZ1bmN0aW9uKGNhbGxiYWNrKSB7DQoJLy8vCTxzdW1tYXJ5Pg0KCS8vLwkJQXR0YWNoIGEgZnVuY3Rpb24gdG8gYmUgZXhlY3V0ZWQgd2hlbmV2ZXIgYW4gQUpBWCByZXF1ZXN0IGZhaWxzLiBUaGlzIGlzIGFuIEFqYXggRXZlbnQuDQoJLy8vCTwvc3VtbWFyeT4NCgkvLy8JPHBhcmFtIG5hbWU9ImNhbGxiYWNrIiB0eXBlPSJGdW5jdGlvbiI+VGhlIGZ1bmN0aW9uIHRvIGV4ZWN1dGUuPC9wYXJhbT4NCgkvLy8JPHJldHVybnMgdHlwZT0ialF1ZXJ5IiAvPg0KCXJldHVybiB0aGlzLmJpbmQoImFqYXhFcnJvciIsIGYpOw0KfTsNCg0KalF1ZXJ5LmZuWyJhamF4U3VjY2VzcyJdID0gZnVuY3Rpb24oY2FsbGJhY2spIHsNCgkvLy8JPHN1bW1hcnk+DQoJLy8vCQlBdHRhY2ggYSBmdW5jdGlvbiB0byBiZSBleGVjdXRlZCB3aGVuZXZlciBhbiBBSkFYIHJlcXVlc3QgY29tcGxldGVzIHN1Y2Nlc3NmdWxseS4gVGhpcyBpcyBhbiBBamF4IEV2ZW50Lg0KCS8vLwk8L3N1bW1hcnk+DQoJLy8vCTxwYXJhbSBuYW1lPSJjYWxsYmFjayIgdHlwZT0iRnVuY3Rpb24iPlRoZSBmdW5jdGlvbiB0byBleGVjdXRlLjwvcGFyYW0+DQoJLy8vCTxyZXR1cm5zIHR5cGU9ImpRdWVyeSIgLz4NCglyZXR1cm4gdGhpcy5iaW5kKCJhamF4U3VjY2VzcyIsIGYpOw0KfTsNCg0KalF1ZXJ5LmZuWyJhamF4U2VuZCJdID0gZnVuY3Rpb24oY2FsbGJhY2spIHsNCgkvLy8JPHN1bW1hcnk+DQoJLy8vCQlBdHRhY2ggYSBmdW5jdGlvbiB0byBiZSBleGVjdXRlZCBiZWZvcmUgYW4gQUpBWCByZXF1ZXN0IGlzIHNlbnQuIFRoaXMgaXMgYW4gQWpheCBFdmVudC4NCgkvLy8JPC9zdW1tYXJ5Pg0KCS8vLwk8cGFyYW0gbmFtZT0iY2FsbGJhY2siIHR5cGU9IkZ1bmN0aW9uIj5UaGUgZnVuY3Rpb24gdG8gZXhlY3V0ZS48L3BhcmFtPg0KCS8vLwk8cmV0dXJucyB0eXBlPSJqUXVlcnkiIC8+DQoJcmV0dXJuIHRoaXMuYmluZCgiYWpheFNlbmQiLCBmKTsNCn07DQoNCg0KdmFyIGpzYyA9IG5vdygpOw0KDQpqUXVlcnkuZXh0ZW5kKHsNCiAgDQoJZ2V0OiBmdW5jdGlvbiggdXJsLCBkYXRhLCBjYWxsYmFjaywgdHlwZSApIHsNCgkJLy8vCTxzdW1tYXJ5Pg0KCQkvLy8JCUxvYWRzIGEgcmVtb3RlIHBhZ2UgdXNpbmcgYW4gSFRUUCBHRVQgcmVxdWVzdC4NCgkJLy8vCTwvc3VtbWFyeT4NCgkJLy8vCTxwYXJhbSBuYW1lPSJ1cmwiIHR5cGU9IlN0cmluZyI+VGhlIFVSTCBvZiB0aGUgSFRNTCBwYWdlIHRvIGxvYWQuPC9wYXJhbT4NCgkJLy8vCTxwYXJhbSBuYW1lPSJkYXRhIiBvcHRpb25hbD0idHJ1ZSIgdHlwZT0iTWFwIj5LZXkvdmFsdWUgcGFpcnMgdGhhdCB3aWxsIGJlIHNlbnQgdG8gdGhlIHNlcnZlci48L3BhcmFtPg0KCQkvLy8JPHBhcmFtIG5hbWU9ImNhbGxiYWNrIiBvcHRpb25hbD0idHJ1ZSIgdHlwZT0iRnVuY3Rpb24iPlRoZSBmdW5jdGlvbiBjYWxsZWQgd2hlbiB0aGUgQUpBWCByZXF1ZXN0IGlzIGNvbXBsZXRlLiAgSXQgc2hvdWxkIG1hcCBmdW5jdGlvbihyZXNwb25zZVRleHQsIHRleHRTdGF0dXMpIHN1Y2ggdGhhdCB0aGlzIG1hcHMgdGhlIG9wdGlvbnMgZm9yIHRoaXMgQUpBWCByZXF1ZXN0LjwvcGFyYW0+DQoJCS8vLwk8cGFyYW0gbmFtZT0idHlwZSIgb3B0aW9uYWw9InRydWUiIHR5cGU9IlN0cmluZyI+VHlwZSBvZiBkYXRhIHRvIGJlIHJldHVybmVkIHRvIGNhbGxiYWNrIGZ1bmN0aW9uLiAgVmFsaWQgdmFsaXVlcyBhcmUgeG1sLCBodG1sLCBzY3JpcHQsIGpzb24sIHRleHQsIF9kZWZhdWx0LjwvcGFyYW0+DQoJCS8vLwk8cmV0dXJucyB0eXBlPSJYTUxIdHRwUmVxdWVzdCIgLz4NCgkJDQoJCS8vIHNoaWZ0IGFyZ3VtZW50cyBpZiBkYXRhIGFyZ3VtZW50IHdhcyBvbW1pdGVkDQoJCWlmICggalF1ZXJ5LmlzRnVuY3Rpb24oIGRhdGEgKSApIHsNCgkJCWNhbGxiYWNrID0gZGF0YTsNCgkJCWRhdGEgPSBudWxsOw0KCQl9DQoNCgkJcmV0dXJuIGpRdWVyeS5hamF4KHsNCgkJCXR5cGU6ICJHRVQiLA0KCQkJdXJsOiB1cmwsDQoJCQlkYXRhOiBkYXRhLA0KCQkJc3VjY2VzczogY2FsbGJhY2ssDQoJCQlkYXRhVHlwZTogdHlwZQ0KCQl9KTsNCgl9LA0KDQoJZ2V0U2NyaXB0OiBmdW5jdGlvbiggdXJsLCBjYWxsYmFjayApIHsNCgkJLy8vCTxzdW1tYXJ5Pg0KCQkvLy8JCUxvYWRzIGFuZCBleGVjdXRlcyBhIGxvY2FsIEphdmFTY3JpcHQgZmlsZSB1c2luZyBhbiBIVFRQIEdFVCByZXF1ZXN0Lg0KCQkvLy8JPC9zdW1tYXJ5Pg0KCQkvLy8JPHBhcmFtIG5hbWU9InVybCIgdHlwZT0iU3RyaW5nIj5UaGUgVVJMIG9mIHRoZSBzY3JpcHQgdG8gbG9hZC48L3BhcmFtPg0KCQkvLy8JPHBhcmFtIG5hbWU9ImNhbGxiYWNrIiBvcHRpb25hbD0idHJ1ZSIgdHlwZT0iRnVuY3Rpb24iPlRoZSBmdW5jdGlvbiBjYWxsZWQgd2hlbiB0aGUgQUpBWCByZXF1ZXN0IGlzIGNvbXBsZXRlLiAgSXQgc2hvdWxkIG1hcCBmdW5jdGlvbihkYXRhLCB0ZXh0U3RhdHVzKSBzdWNoIHRoYXQgdGhpcyBtYXBzIHRoZSBvcHRpb25zIGZvciB0aGUgQUpBWCByZXF1ZXN0LjwvcGFyYW0+DQoJCS8vLwk8cmV0dXJucyB0eXBlPSJYTUxIdHRwUmVxdWVzdCIgLz4NCgkNCgkJcmV0dXJuIGpRdWVyeS5nZXQodXJsLCBudWxsLCBjYWxsYmFjaywgInNjcmlwdCIpOw0KCX0sDQoNCglnZXRKU09OOiBmdW5jdGlvbiggdXJsLCBkYXRhLCBjYWxsYmFjayApIHsNCgkJLy8vCTxzdW1tYXJ5Pg0KCQkvLy8JCUxvYWRzIEpTT04gZGF0YSB1c2luZyBhbiBIVFRQIEdFVCByZXF1ZXN0Lg0KCQkvLy8JPC9zdW1tYXJ5Pg0KCQkvLy8JPHBhcmFtIG5hbWU9InVybCIgdHlwZT0iU3RyaW5nIj5UaGUgVVJMIG9mIHRoZSBKU09OIGRhdGEgdG8gbG9hZC48L3BhcmFtPg0KCQkvLy8JPHBhcmFtIG5hbWU9ImRhdGEiIG9wdGlvbmFsPSJ0cnVlIiB0eXBlPSJNYXAiPktleS92YWx1ZSBwYWlycyB0aGF0IHdpbGwgYmUgc2VudCB0byB0aGUgc2VydmVyLjwvcGFyYW0+DQoJCS8vLwk8cGFyYW0gbmFtZT0iY2FsbGJhY2siIG9wdGlvbmFsPSJ0cnVlIiB0eXBlPSJGdW5jdGlvbiI+VGhlIGZ1bmN0aW9uIGNhbGxlZCB3aGVuIHRoZSBBSkFYIHJlcXVlc3QgaXMgY29tcGxldGUgaWYgdGhlIGRhdGEgaXMgbG9hZGVkIHN1Y2Nlc3NmdWxseS4gIEl0IHNob3VsZCBtYXAgZnVuY3Rpb24oZGF0YSwgdGV4dFN0YXR1cykgc3VjaCB0aGF0IHRoaXMgbWFwcyB0aGUgb3B0aW9ucyBmb3IgdGhpcyBBSkFYIHJlcXVlc3QuPC9wYXJhbT4NCgkJLy8vCTxyZXR1cm5zIHR5cGU9IlhNTEh0dHBSZXF1ZXN0IiAvPg0KCQ0KCQlyZXR1cm4galF1ZXJ5LmdldCh1cmwsIGRhdGEsIGNhbGxiYWNrLCAianNvbiIpOw0KCX0sDQoNCglwb3N0OiBmdW5jdGlvbiggdXJsLCBkYXRhLCBjYWxsYmFjaywgdHlwZSApIHsNCgkJLy8vCTxzdW1tYXJ5Pg0KCQkvLy8JCUxvYWRzIGEgcmVtb3RlIHBhZ2UgdXNpbmcgYW4gSFRUUCBQT1NUIHJlcXVlc3QuDQoJCS8vLwk8L3N1bW1hcnk+DQoJCS8vLwk8cGFyYW0gbmFtZT0idXJsIiB0eXBlPSJTdHJpbmciPlRoZSBVUkwgb2YgdGhlIEhUTUwgcGFnZSB0byBsb2FkLjwvcGFyYW0+DQoJCS8vLwk8cGFyYW0gbmFtZT0iZGF0YSIgb3B0aW9uYWw9InRydWUiIHR5cGU9Ik1hcCI+S2V5L3ZhbHVlIHBhaXJzIHRoYXQgd2lsbCBiZSBzZW50IHRvIHRoZSBzZXJ2ZXIuPC9wYXJhbT4NCgkJLy8vCTxwYXJhbSBuYW1lPSJjYWxsYmFjayIgb3B0aW9uYWw9InRydWUiIHR5cGU9IkZ1bmN0aW9uIj5UaGUgZnVuY3Rpb24gY2FsbGVkIHdoZW4gdGhlIEFKQVggcmVxdWVzdCBpcyBjb21wbGV0ZS4gIEl0IHNob3VsZCBtYXAgZnVuY3Rpb24ocmVzcG9uc2VUZXh0LCB0ZXh0U3RhdHVzKSBzdWNoIHRoYXQgdGhpcyBtYXBzIHRoZSBvcHRpb25zIGZvciB0aGlzIEFKQVggcmVxdWVzdC48L3BhcmFtPg0KCQkvLy8JPHBhcmFtIG5hbWU9InR5cGUiIG9wdGlvbmFsPSJ0cnVlIiB0eXBlPSJTdHJpbmciPlR5cGUgb2YgZGF0YSB0byBiZSByZXR1cm5lZCB0byBjYWxsYmFjayBmdW5jdGlvbi4gIFZhbGlkIHZhbGl1ZXMgYXJlIHhtbCwgaHRtbCwgc2NyaXB0LCBqc29uLCB0ZXh0LCBfZGVmYXVsdC48L3BhcmFtPg0KCQkvLy8JPHJldHVybnMgdHlwZT0iWE1MSHR0cFJlcXVlc3QiIC8+DQoJCQ0KCQlpZiAoIGpRdWVyeS5pc0Z1bmN0aW9uKCBkYXRhICkgKSB7DQoJCQljYWxsYmFjayA9IGRhdGE7DQoJCQlkYXRhID0ge307DQoJCX0NCg0KCQlyZXR1cm4galF1ZXJ5LmFqYXgoew0KCQkJdHlwZTogIlBPU1QiLA0KCQkJdXJsOiB1cmwsDQoJCQlkYXRhOiBkYXRhLA0KCQkJc3VjY2VzczogY2FsbGJhY2ssDQoJCQlkYXRhVHlwZTogdHlwZQ0KCQl9KTsNCgl9LA0KDQoJYWpheFNldHVwOiBmdW5jdGlvbiggc2V0dGluZ3MgKSB7DQoJCS8vLwk8c3VtbWFyeT4NCgkJLy8vCQlTZXRzIHVwIGdsb2JhbCBzZXR0aW5ncyBmb3IgQUpBWCByZXF1ZXN0cy4NCgkJLy8vCTwvc3VtbWFyeT4NCgkJLy8vCTxwYXJhbSBuYW1lPSJzZXR0aW5ncyIgdHlwZT0iT3B0aW9ucyI+QSBzZXQgb2Yga2V5L3ZhbHVlIHBhaXJzIHRoYXQgY29uZmlndXJlIHRoZSBkZWZhdWx0IEFqYXggcmVxdWVzdC48L3BhcmFtPg0KCQ0KCQlqUXVlcnkuZXh0ZW5kKCBqUXVlcnkuYWpheFNldHRpbmdzLCBzZXR0aW5ncyApOw0KCX0sDQoNCglhamF4U2V0dGluZ3M6IHsNCgkJdXJsOiBsb2NhdGlvbi5ocmVmLA0KCQlnbG9iYWw6IHRydWUsDQoJCXR5cGU6ICJHRVQiLA0KCQljb250ZW50VHlwZTogImFwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZCIsDQoJCXByb2Nlc3NEYXRhOiB0cnVlLA0KCQlhc3luYzogdHJ1ZSwNCgkJLyoNCgkJdGltZW91dDogMCwNCgkJZGF0YTogbnVsbCwNCgkJdXNlcm5hbWU6IG51bGwsDQoJCXBhc3N3b3JkOiBudWxsLA0KCQkqLw0KCQkvLyBDcmVhdGUgdGhlIHJlcXVlc3Qgb2JqZWN0OyBNaWNyb3NvZnQgZmFpbGVkIHRvIHByb3Blcmx5DQoJCS8vIGltcGxlbWVudCB0aGUgWE1MSHR0cFJlcXVlc3QgaW4gSUU3LCBzbyB3ZSB1c2UgdGhlIEFjdGl2ZVhPYmplY3Qgd2hlbiBpdCBpcyBhdmFpbGFibGUNCgkJLy8gVGhpcyBmdW5jdGlvbiBjYW4gYmUgb3ZlcnJpZGVuIGJ5IGNhbGxpbmcgalF1ZXJ5LmFqYXhTZXR1cA0KCQl4aHI6ZnVuY3Rpb24oKXsNCgkJCXJldHVybiB3aW5kb3cuQWN0aXZlWE9iamVjdCA/IG5ldyBBY3RpdmVYT2JqZWN0KCJNaWNyb3NvZnQuWE1MSFRUUCIpIDogbmV3IFhNTEh0dHBSZXF1ZXN0KCk7DQoJCX0sDQoJCWFjY2VwdHM6IHsNCgkJCXhtbDogImFwcGxpY2F0aW9uL3htbCwgdGV4dC94bWwiLA0KCQkJaHRtbDogInRleHQvaHRtbCIsDQoJCQlzY3JpcHQ6ICJ0ZXh0L2phdmFzY3JpcHQsIGFwcGxpY2F0aW9uL2phdmFzY3JpcHQiLA0KCQkJanNvbjogImFwcGxpY2F0aW9uL2pzb24sIHRleHQvamF2YXNjcmlwdCIsDQoJCQl0ZXh0OiAidGV4dC9wbGFpbiIsDQoJCQlfZGVmYXVsdDogIiovKiINCgkJfQ0KCX0sDQoNCgkvLyBMYXN0LU1vZGlmaWVkIGhlYWRlciBjYWNoZSBmb3IgbmV4dCByZXF1ZXN0DQoJbGFzdE1vZGlmaWVkOiB7fSwNCg0KCWFqYXg6IGZ1bmN0aW9uKCBzICkgew0KCQkvLy8JPHN1bW1hcnk+DQoJCS8vLwkJTG9hZCBhIHJlbW90ZSBwYWdlIHVzaW5nIGFuIEhUVFAgcmVxdWVzdC4NCgkJLy8vCTwvc3VtbWFyeT4NCgkJLy8vCTxwcml2YXRlIC8+DQoJCQ0KCQkvLyBFeHRlbmQgdGhlIHNldHRpbmdzLCBidXQgcmUtZXh0ZW5kICdzJyBzbyB0aGF0IGl0IGNhbiBiZQ0KCQkvLyBjaGVja2VkIGFnYWluIGxhdGVyIChpbiB0aGUgdGVzdCBzdWl0ZSwgc3BlY2lmaWNhbGx5KQ0KCQlzID0galF1ZXJ5LmV4dGVuZCh0cnVlLCBzLCBqUXVlcnkuZXh0ZW5kKHRydWUsIHt9LCBqUXVlcnkuYWpheFNldHRpbmdzLCBzKSk7DQoNCgkJdmFyIGpzb25wLCBqc3JlID0gLz1cPygmfCQpL2csIHN0YXR1cywgZGF0YSwNCgkJCXR5cGUgPSBzLnR5cGUudG9VcHBlckNhc2UoKTsNCg0KCQkvLyBjb252ZXJ0IGRhdGEgaWYgbm90IGFscmVhZHkgYSBzdHJpbmcNCgkJaWYgKCBzLmRhdGEgJiYgcy5wcm9jZXNzRGF0YSAmJiB0eXBlb2Ygcy5kYXRhICE9PSAic3RyaW5nIiApDQoJCQlzLmRhdGEgPSBqUXVlcnkucGFyYW0ocy5kYXRhKTsNCg0KCQkvLyBIYW5kbGUgSlNPTlAgUGFyYW1ldGVyIENhbGxiYWNrcw0KCQlpZiAoIHMuZGF0YVR5cGUgPT0gImpzb25wIiApIHsNCgkJCWlmICggdHlwZSA9PSAiR0VUIiApIHsNCgkJCQlpZiAoICFzLnVybC5tYXRjaChqc3JlKSApDQoJCQkJCXMudXJsICs9IChzLnVybC5tYXRjaCgvXD8vKSA/ICImIiA6ICI/IikgKyAocy5qc29ucCB8fCAiY2FsbGJhY2siKSArICI9PyI7DQoJCQl9IGVsc2UgaWYgKCAhcy5kYXRhIHx8ICFzLmRhdGEubWF0Y2goanNyZSkgKQ0KCQkJCXMuZGF0YSA9IChzLmRhdGEgPyBzLmRhdGEgKyAiJiIgOiAiIikgKyAocy5qc29ucCB8fCAiY2FsbGJhY2siKSArICI9PyI7DQoJCQlzLmRhdGFUeXBlID0gImpzb24iOw0KCQl9DQoNCgkJLy8gQnVpbGQgdGVtcG9yYXJ5IEpTT05QIGZ1bmN0aW9uDQoJCWlmICggcy5kYXRhVHlwZSA9PSAianNvbiIgJiYgKHMuZGF0YSAmJiBzLmRhdGEubWF0Y2goanNyZSkgfHwgcy51cmwubWF0Y2goanNyZSkpICkgew0KCQkJanNvbnAgPSAianNvbnAiICsganNjKys7DQoNCgkJCS8vIFJlcGxhY2UgdGhlID0/IHNlcXVlbmNlIGJvdGggaW4gdGhlIHF1ZXJ5IHN0cmluZyBhbmQgdGhlIGRhdGENCgkJCWlmICggcy5kYXRhICkNCgkJCQlzLmRhdGEgPSAocy5kYXRhICsgIiIpLnJlcGxhY2UoanNyZSwgIj0iICsganNvbnAgKyAiJDEiKTsNCgkJCXMudXJsID0gcy51cmwucmVwbGFjZShqc3JlLCAiPSIgKyBqc29ucCArICIkMSIpOw0KDQoJCQkvLyBXZSBuZWVkIHRvIG1ha2Ugc3VyZQ0KCQkJLy8gdGhhdCBhIEpTT05QIHN0eWxlIHJlc3BvbnNlIGlzIGV4ZWN1dGVkIHByb3Blcmx5DQoJCQlzLmRhdGFUeXBlID0gInNjcmlwdCI7DQoNCgkJCS8vIEhhbmRsZSBKU09OUC1zdHlsZSBsb2FkaW5nDQoJCQl3aW5kb3dbIGpzb25wIF0gPSBmdW5jdGlvbih0bXApew0KCQkJCWRhdGEgPSB0bXA7DQoJCQkJc3VjY2VzcygpOw0KCQkJCWNvbXBsZXRlKCk7DQoJCQkJLy8gR2FyYmFnZSBjb2xsZWN0DQoJCQkJd2luZG93WyBqc29ucCBdID0gdW5kZWZpbmVkOw0KCQkJCXRyeXsgZGVsZXRlIHdpbmRvd1sganNvbnAgXTsgfSBjYXRjaChlKXt9DQoJCQkJaWYgKCBoZWFkICkNCgkJCQkJaGVhZC5yZW1vdmVDaGlsZCggc2NyaXB0ICk7DQoJCQl9Ow0KCQl9DQoNCgkJaWYgKCBzLmRhdGFUeXBlID09ICJzY3JpcHQiICYmIHMuY2FjaGUgPT0gbnVsbCApDQoJCQlzLmNhY2hlID0gZmFsc2U7DQoNCgkJaWYgKCBzLmNhY2hlID09PSBmYWxzZSAmJiB0eXBlID09ICJHRVQiICkgew0KCQkJdmFyIHRzID0gbm93KCk7DQoJCQkvLyB0cnkgcmVwbGFjaW5nIF89IGlmIGl0IGlzIHRoZXJlDQoJCQl2YXIgcmV0ID0gcy51cmwucmVwbGFjZSgvKFw/fCYpXz0uKj8oJnwkKS8sICIkMV89IiArIHRzICsgIiQyIik7DQoJCQkvLyBpZiBub3RoaW5nIHdhcyByZXBsYWNlZCwgYWRkIHRpbWVzdGFtcCB0byB0aGUgZW5kDQoJCQlzLnVybCA9IHJldCArICgocmV0ID09IHMudXJsKSA/IChzLnVybC5tYXRjaCgvXD8vKSA/ICImIiA6ICI/IikgKyAiXz0iICsgdHMgOiAiIik7DQoJCX0NCg0KCQkvLyBJZiBkYXRhIGlzIGF2YWlsYWJsZSwgYXBwZW5kIGRhdGEgdG8gdXJsIGZvciBnZXQgcmVxdWVzdHMNCgkJaWYgKCBzLmRhdGEgJiYgdHlwZSA9PSAiR0VUIiApIHsNCgkJCXMudXJsICs9IChzLnVybC5tYXRjaCgvXD8vKSA/ICImIiA6ICI/IikgKyBzLmRhdGE7DQoNCgkJCS8vIElFIGxpa2VzIHRvIHNlbmQgYm90aCBnZXQgYW5kIHBvc3QgZGF0YSwgcHJldmVudCB0aGlzDQoJCQlzLmRhdGEgPSBudWxsOw0KCQl9DQoNCgkJLy8gV2F0Y2ggZm9yIGEgbmV3IHNldCBvZiByZXF1ZXN0cw0KCQlpZiAoIHMuZ2xvYmFsICYmICEgalF1ZXJ5LmFjdGl2ZSsrICkNCgkJCWpRdWVyeS5ldmVudC50cmlnZ2VyKCAiYWpheFN0YXJ0IiApOw0KDQoJCS8vIE1hdGNoZXMgYW4gYWJzb2x1dGUgVVJMLCBhbmQgc2F2ZXMgdGhlIGRvbWFpbg0KCQl2YXIgcGFydHMgPSAvXihcdys6KT9cL1wvKFteXC8/I10rKS8uZXhlYyggcy51cmwgKTsNCg0KCQkvLyBJZiB3ZSdyZSByZXF1ZXN0aW5nIGEgcmVtb3RlIGRvY3VtZW50DQoJCS8vIGFuZCB0cnlpbmcgdG8gbG9hZCBKU09OIG9yIFNjcmlwdCB3aXRoIGEgR0VUDQoJCWlmICggcy5kYXRhVHlwZSA9PSAic2NyaXB0IiAmJiB0eXBlID09ICJHRVQiICYmIHBhcnRzDQoJCQkmJiAoIHBhcnRzWzFdICYmIHBhcnRzWzFdICE9IGxvY2F0aW9uLnByb3RvY29sIHx8IHBhcnRzWzJdICE9IGxvY2F0aW9uLmhvc3QgKSl7DQoNCgkJCXZhciBoZWFkID0gZG9jdW1lbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoImhlYWQiKVswXTsNCgkJCXZhciBzY3JpcHQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJzY3JpcHQiKTsNCgkJCXNjcmlwdC5zcmMgPSBzLnVybDsNCgkJCWlmIChzLnNjcmlwdENoYXJzZXQpDQoJCQkJc2NyaXB0LmNoYXJzZXQgPSBzLnNjcmlwdENoYXJzZXQ7DQoNCgkJCS8vIEhhbmRsZSBTY3JpcHQgbG9hZGluZw0KCQkJaWYgKCAhanNvbnAgKSB7DQoJCQkJdmFyIGRvbmUgPSBmYWxzZTsNCg0KCQkJCS8vIEF0dGFjaCBoYW5kbGVycyBmb3IgYWxsIGJyb3dzZXJzDQoJCQkJc2NyaXB0Lm9ubG9hZCA9IHNjcmlwdC5vbnJlYWR5c3RhdGVjaGFuZ2UgPSBmdW5jdGlvbigpew0KCQkJCQlpZiAoICFkb25lICYmICghdGhpcy5yZWFkeVN0YXRlIHx8DQoJCQkJCQkJdGhpcy5yZWFkeVN0YXRlID09ICJsb2FkZWQiIHx8IHRoaXMucmVhZHlTdGF0ZSA9PSAiY29tcGxldGUiKSApIHsNCgkJCQkJCWRvbmUgPSB0cnVlOw0KCQkJCQkJc3VjY2VzcygpOw0KCQkJCQkJY29tcGxldGUoKTsNCg0KCQkJCQkJLy8gSGFuZGxlIG1lbW9yeSBsZWFrIGluIElFDQoJCQkJCQlzY3JpcHQub25sb2FkID0gc2NyaXB0Lm9ucmVhZHlzdGF0ZWNoYW5nZSA9IG51bGw7DQoJCQkJCQloZWFkLnJlbW92ZUNoaWxkKCBzY3JpcHQgKTsNCgkJCQkJfQ0KCQkJCX07DQoJCQl9DQoNCgkJCWhlYWQuYXBwZW5kQ2hpbGQoc2NyaXB0KTsNCg0KCQkJLy8gV2UgaGFuZGxlIGV2ZXJ5dGhpbmcgdXNpbmcgdGhlIHNjcmlwdCBlbGVtZW50IGluamVjdGlvbg0KCQkJcmV0dXJuIHVuZGVmaW5lZDsNCgkJfQ0KDQoJCXZhciByZXF1ZXN0RG9uZSA9IGZhbHNlOw0KDQoJCS8vIENyZWF0ZSB0aGUgcmVxdWVzdCBvYmplY3QNCgkJdmFyIHhociA9IHMueGhyKCk7DQoNCgkJLy8gT3BlbiB0aGUgc29ja2V0DQoJCS8vIFBhc3NpbmcgbnVsbCB1c2VybmFtZSwgZ2VuZXJhdGVzIGEgbG9naW4gcG9wdXAgb24gT3BlcmEgKCMyODY1KQ0KCQlpZiggcy51c2VybmFtZSApDQoJCQl4aHIub3Blbih0eXBlLCBzLnVybCwgcy5hc3luYywgcy51c2VybmFtZSwgcy5wYXNzd29yZCk7DQoJCWVsc2UNCgkJCXhoci5vcGVuKHR5cGUsIHMudXJsLCBzLmFzeW5jKTsNCg0KCQkvLyBOZWVkIGFuIGV4dHJhIHRyeS9jYXRjaCBmb3IgY3Jvc3MgZG9tYWluIHJlcXVlc3RzIGluIEZpcmVmb3ggMw0KCQl0cnkgew0KCQkJLy8gU2V0IHRoZSBjb3JyZWN0IGhlYWRlciwgaWYgZGF0YSBpcyBiZWluZyBzZW50DQoJCQlpZiAoIHMuZGF0YSApDQoJCQkJeGhyLnNldFJlcXVlc3RIZWFkZXIoIkNvbnRlbnQtVHlwZSIsIHMuY29udGVudFR5cGUpOw0KDQoJCQkvLyBTZXQgdGhlIElmLU1vZGlmaWVkLVNpbmNlIGhlYWRlciwgaWYgaWZNb2RpZmllZCBtb2RlLg0KCQkJaWYgKCBzLmlmTW9kaWZpZWQgKQ0KCQkJCXhoci5zZXRSZXF1ZXN0SGVhZGVyKCJJZi1Nb2RpZmllZC1TaW5jZSIsDQoJCQkJCWpRdWVyeS5sYXN0TW9kaWZpZWRbcy51cmxdIHx8ICJUaHUsIDAxIEphbiAxOTcwIDAwOjAwOjAwIEdNVCIgKTsNCg0KCQkJLy8gU2V0IGhlYWRlciBzbyB0aGUgY2FsbGVkIHNjcmlwdCBrbm93cyB0aGF0IGl0J3MgYW4gWE1MSHR0cFJlcXVlc3QNCgkJCXhoci5zZXRSZXF1ZXN0SGVhZGVyKCJYLVJlcXVlc3RlZC1XaXRoIiwgIlhNTEh0dHBSZXF1ZXN0Iik7DQoNCgkJCS8vIFNldCB0aGUgQWNjZXB0cyBoZWFkZXIgZm9yIHRoZSBzZXJ2ZXIsIGRlcGVuZGluZyBvbiB0aGUgZGF0YVR5cGUNCgkJCXhoci5zZXRSZXF1ZXN0SGVhZGVyKCJBY2NlcHQiLCBzLmRhdGFUeXBlICYmIHMuYWNjZXB0c1sgcy5kYXRhVHlwZSBdID8NCgkJCQlzLmFjY2VwdHNbIHMuZGF0YVR5cGUgXSArICIsICovKiIgOg0KCQkJCXMuYWNjZXB0cy5fZGVmYXVsdCApOw0KCQl9IGNhdGNoKGUpe30NCg0KCQkvLyBBbGxvdyBjdXN0b20gaGVhZGVycy9taW1ldHlwZXMgYW5kIGVhcmx5IGFib3J0DQoJCWlmICggcy5iZWZvcmVTZW5kICYmIHMuYmVmb3JlU2VuZCh4aHIsIHMpID09PSBmYWxzZSApIHsNCgkJCS8vIEhhbmRsZSB0aGUgZ2xvYmFsIEFKQVggY291bnRlcg0KCQkJaWYgKCBzLmdsb2JhbCAmJiAhIC0talF1ZXJ5LmFjdGl2ZSApDQoJCQkJalF1ZXJ5LmV2ZW50LnRyaWdnZXIoICJhamF4U3RvcCIgKTsNCgkJCS8vIGNsb3NlIG9wZW5kZWQgc29ja2V0DQoJCQl4aHIuYWJvcnQoKTsNCgkJCXJldHVybiBmYWxzZTsNCgkJfQ0KDQoJCWlmICggcy5nbG9iYWwgKQ0KCQkJalF1ZXJ5LmV2ZW50LnRyaWdnZXIoImFqYXhTZW5kIiwgW3hociwgc10pOw0KDQoJCS8vIFdhaXQgZm9yIGEgcmVzcG9uc2UgdG8gY29tZSBiYWNrDQoJCXZhciBvbnJlYWR5c3RhdGVjaGFuZ2UgPSBmdW5jdGlvbihpc1RpbWVvdXQpew0KCQkJLy8gVGhlIHJlcXVlc3Qgd2FzIGFib3J0ZWQsIGNsZWFyIHRoZSBpbnRlcnZhbCBhbmQgZGVjcmVtZW50IGpRdWVyeS5hY3RpdmUNCgkJCWlmICh4aHIucmVhZHlTdGF0ZSA9PSAwKSB7DQoJCQkJaWYgKGl2YWwpIHsNCgkJCQkJLy8gY2xlYXIgcG9sbCBpbnRlcnZhbA0KCQkJCQljbGVhckludGVydmFsKGl2YWwpOw0KCQkJCQlpdmFsID0gbnVsbDsNCgkJCQkJLy8gSGFuZGxlIHRoZSBnbG9iYWwgQUpBWCBjb3VudGVyDQoJCQkJCWlmICggcy5nbG9iYWwgJiYgISAtLWpRdWVyeS5hY3RpdmUgKQ0KCQkJCQkJalF1ZXJ5LmV2ZW50LnRyaWdnZXIoICJhamF4U3RvcCIgKTsNCgkJCQl9DQoJCQkvLyBUaGUgdHJhbnNmZXIgaXMgY29tcGxldGUgYW5kIHRoZSBkYXRhIGlzIGF2YWlsYWJsZSwgb3IgdGhlIHJlcXVlc3QgdGltZWQgb3V0DQoJCQl9IGVsc2UgaWYgKCAhcmVxdWVzdERvbmUgJiYgeGhyICYmICh4aHIucmVhZHlTdGF0ZSA9PSA0IHx8IGlzVGltZW91dCA9PSAidGltZW91dCIpICkgew0KCQkJCXJlcXVlc3REb25lID0gdHJ1ZTsNCg0KCQkJCS8vIGNsZWFyIHBvbGwgaW50ZXJ2YWwNCgkJCQlpZiAoaXZhbCkgew0KCQkJCQljbGVhckludGVydmFsKGl2YWwpOw0KCQkJCQlpdmFsID0gbnVsbDsNCgkJCQl9DQoNCgkJCQlzdGF0dXMgPSBpc1RpbWVvdXQgPT0gInRpbWVvdXQiID8gInRpbWVvdXQiIDoNCgkJCQkJIWpRdWVyeS5odHRwU3VjY2VzcyggeGhyICkgPyAiZXJyb3IiIDoNCgkJCQkJcy5pZk1vZGlmaWVkICYmIGpRdWVyeS5odHRwTm90TW9kaWZpZWQoIHhociwgcy51cmwgKSA/ICJub3Rtb2RpZmllZCIgOg0KCQkJCQkic3VjY2VzcyI7DQoNCgkJCQlpZiAoIHN0YXR1cyA9PSAic3VjY2VzcyIgKSB7DQoJCQkJCS8vIFdhdGNoIGZvciwgYW5kIGNhdGNoLCBYTUwgZG9jdW1lbnQgcGFyc2UgZXJyb3JzDQoJCQkJCXRyeSB7DQoJCQkJCQkvLyBwcm9jZXNzIHRoZSBkYXRhIChydW5zIHRoZSB4bWwgdGhyb3VnaCBodHRwRGF0YSByZWdhcmRsZXNzIG9mIGNhbGxiYWNrKQ0KCQkJCQkJZGF0YSA9IGpRdWVyeS5odHRwRGF0YSggeGhyLCBzLmRhdGFUeXBlLCBzICk7DQoJCQkJCX0gY2F0Y2goZSkgew0KCQkJCQkJc3RhdHVzID0gInBhcnNlcmVycm9yIjsNCgkJCQkJfQ0KCQkJCX0NCg0KCQkJCS8vIE1ha2Ugc3VyZSB0aGF0IHRoZSByZXF1ZXN0IHdhcyBzdWNjZXNzZnVsIG9yIG5vdG1vZGlmaWVkDQoJCQkJaWYgKCBzdGF0dXMgPT0gInN1Y2Nlc3MiICkgew0KCQkJCQkvLyBDYWNoZSBMYXN0LU1vZGlmaWVkIGhlYWRlciwgaWYgaWZNb2RpZmllZCBtb2RlLg0KCQkJCQl2YXIgbW9kUmVzOw0KCQkJCQl0cnkgew0KCQkJCQkJbW9kUmVzID0geGhyLmdldFJlc3BvbnNlSGVhZGVyKCJMYXN0LU1vZGlmaWVkIik7DQoJCQkJCX0gY2F0Y2goZSkge30gLy8gc3dhbGxvdyBleGNlcHRpb24gdGhyb3duIGJ5IEZGIGlmIGhlYWRlciBpcyBub3QgYXZhaWxhYmxlDQoNCgkJCQkJaWYgKCBzLmlmTW9kaWZpZWQgJiYgbW9kUmVzICkNCgkJCQkJCWpRdWVyeS5sYXN0TW9kaWZpZWRbcy51cmxdID0gbW9kUmVzOw0KDQoJCQkJCS8vIEpTT05QIGhhbmRsZXMgaXRzIG93biBzdWNjZXNzIGNhbGxiYWNrDQoJCQkJCWlmICggIWpzb25wICkNCgkJCQkJCXN1Y2Nlc3MoKTsNCgkJCQl9IGVsc2UNCgkJCQkJalF1ZXJ5LmhhbmRsZUVycm9yKHMsIHhociwgc3RhdHVzKTsNCg0KCQkJCS8vIEZpcmUgdGhlIGNvbXBsZXRlIGhhbmRsZXJzDQoJCQkJY29tcGxldGUoKTsNCg0KCQkJCWlmICggaXNUaW1lb3V0ICkNCgkJCQkJeGhyLmFib3J0KCk7DQoNCgkJCQkvLyBTdG9wIG1lbW9yeSBsZWFrcw0KCQkJCWlmICggcy5hc3luYyApDQoJCQkJCXhociA9IG51bGw7DQoJCQl9DQoJCX07DQoNCgkJaWYgKCBzLmFzeW5jICkgew0KCQkJLy8gZG9uJ3QgYXR0YWNoIHRoZSBoYW5kbGVyIHRvIHRoZSByZXF1ZXN0LCBqdXN0IHBvbGwgaXQgaW5zdGVhZA0KCQkJdmFyIGl2YWwgPSBzZXRJbnRlcnZhbChvbnJlYWR5c3RhdGVjaGFuZ2UsIDEzKTsNCg0KCQkJLy8gVGltZW91dCBjaGVja2VyDQoJCQlpZiAoIHMudGltZW91dCA+IDAgKQ0KCQkJCXNldFRpbWVvdXQoZnVuY3Rpb24oKXsNCgkJCQkJLy8gQ2hlY2sgdG8gc2VlIGlmIHRoZSByZXF1ZXN0IGlzIHN0aWxsIGhhcHBlbmluZw0KCQkJCQlpZiAoIHhociAmJiAhcmVxdWVzdERvbmUgKQ0KCQkJCQkJb25yZWFkeXN0YXRlY2hhbmdlKCAidGltZW91dCIgKTsNCgkJCQl9LCBzLnRpbWVvdXQpOw0KCQl9DQoNCgkJLy8gU2VuZCB0aGUgZGF0YQ0KCQl0cnkgew0KCQkJeGhyLnNlbmQocy5kYXRhKTsNCgkJfSBjYXRjaChlKSB7DQoJCQlqUXVlcnkuaGFuZGxlRXJyb3IocywgeGhyLCBudWxsLCBlKTsNCgkJfQ0KDQoJCS8vIGZpcmVmb3ggMS41IGRvZXNuJ3QgZmlyZSBzdGF0ZWNoYW5nZSBmb3Igc3luYyByZXF1ZXN0cw0KCQlpZiAoICFzLmFzeW5jICkNCgkJCW9ucmVhZHlzdGF0ZWNoYW5nZSgpOw0KDQoJCWZ1bmN0aW9uIHN1Y2Nlc3MoKXsNCgkJCS8vIElmIGEgbG9jYWwgY2FsbGJhY2sgd2FzIHNwZWNpZmllZCwgZmlyZSBpdCBhbmQgcGFzcyBpdCB0aGUgZGF0YQ0KCQkJaWYgKCBzLnN1Y2Nlc3MgKQ0KCQkJCXMuc3VjY2VzcyggZGF0YSwgc3RhdHVzICk7DQoNCgkJCS8vIEZpcmUgdGhlIGdsb2JhbCBjYWxsYmFjaw0KCQkJaWYgKCBzLmdsb2JhbCApDQoJCQkJalF1ZXJ5LmV2ZW50LnRyaWdnZXIoICJhamF4U3VjY2VzcyIsIFt4aHIsIHNdICk7DQoJCX0NCg0KCQlmdW5jdGlvbiBjb21wbGV0ZSgpew0KCQkJLy8gUHJvY2VzcyByZXN1bHQNCgkJCWlmICggcy5jb21wbGV0ZSApDQoJCQkJcy5jb21wbGV0ZSh4aHIsIHN0YXR1cyk7DQoNCgkJCS8vIFRoZSByZXF1ZXN0IHdhcyBjb21wbGV0ZWQNCgkJCWlmICggcy5nbG9iYWwgKQ0KCQkJCWpRdWVyeS5ldmVudC50cmlnZ2VyKCAiYWpheENvbXBsZXRlIiwgW3hociwgc10gKTsNCg0KCQkJLy8gSGFuZGxlIHRoZSBnbG9iYWwgQUpBWCBjb3VudGVyDQoJCQlpZiAoIHMuZ2xvYmFsICYmICEgLS1qUXVlcnkuYWN0aXZlICkNCgkJCQlqUXVlcnkuZXZlbnQudHJpZ2dlciggImFqYXhTdG9wIiApOw0KCQl9DQoNCgkJLy8gcmV0dXJuIFhNTEh0dHBSZXF1ZXN0IHRvIGFsbG93IGFib3J0aW5nIHRoZSByZXF1ZXN0IGV0Yy4NCgkJcmV0dXJuIHhocjsNCgl9LA0KDQoJaGFuZGxlRXJyb3I6IGZ1bmN0aW9uKCBzLCB4aHIsIHN0YXR1cywgZSApIHsNCgkJLy8vCTxzdW1tYXJ5Pg0KCQkvLy8JCVRoaXMgbWV0aG9kIGlzIGludGVybmFsLg0KCQkvLy8JPC9zdW1tYXJ5Pg0KCQkvLy8JPHByaXZhdGUgLz4NCg0KCQkvLyBJZiBhIGxvY2FsIGNhbGxiYWNrIHdhcyBzcGVjaWZpZWQsIGZpcmUgaXQNCgkJaWYgKCBzLmVycm9yICkgcy5lcnJvciggeGhyLCBzdGF0dXMsIGUgKTsNCg0KCQkvLyBGaXJlIHRoZSBnbG9iYWwgY2FsbGJhY2sNCgkJaWYgKCBzLmdsb2JhbCApDQoJCQlqUXVlcnkuZXZlbnQudHJpZ2dlciggImFqYXhFcnJvciIsIFt4aHIsIHMsIGVdICk7DQoJfSwNCg0KCS8vIENvdW50ZXIgZm9yIGhvbGRpbmcgdGhlIG51bWJlciBvZiBhY3RpdmUgcXVlcmllcw0KCWFjdGl2ZTogMCwNCg0KCS8vIERldGVybWluZXMgaWYgYW4gWE1MSHR0cFJlcXVlc3Qgd2FzIHN1Y2Nlc3NmdWwgb3Igbm90DQoJaHR0cFN1Y2Nlc3M6IGZ1bmN0aW9uKCB4aHIgKSB7DQoJCS8vLwk8c3VtbWFyeT4NCgkJLy8vCQlUaGlzIG1ldGhvZCBpcyBpbnRlcm5hbC4NCgkJLy8vCTwvc3VtbWFyeT4NCgkJLy8vCTxwcml2YXRlIC8+DQoJCQ0KCQl0cnkgew0KCQkJLy8gSUUgZXJyb3Igc29tZXRpbWVzIHJldHVybnMgMTIyMyB3aGVuIGl0IHNob3VsZCBiZSAyMDQgc28gdHJlYXQgaXQgYXMgc3VjY2Vzcywgc2VlICMxNDUwDQoJCQlyZXR1cm4gIXhoci5zdGF0dXMgJiYgbG9jYXRpb24ucHJvdG9jb2wgPT0gImZpbGU6IiB8fA0KCQkJCSggeGhyLnN0YXR1cyA+PSAyMDAgJiYgeGhyLnN0YXR1cyA8IDMwMCApIHx8IHhoci5zdGF0dXMgPT0gMzA0IHx8IHhoci5zdGF0dXMgPT0gMTIyMzsNCgkJfSBjYXRjaChlKXt9DQoJCXJldHVybiBmYWxzZTsNCgl9LA0KDQoJLy8gRGV0ZXJtaW5lcyBpZiBhbiBYTUxIdHRwUmVxdWVzdCByZXR1cm5zIE5vdE1vZGlmaWVkDQoJaHR0cE5vdE1vZGlmaWVkOiBmdW5jdGlvbiggeGhyLCB1cmwgKSB7DQoJCS8vLwk8c3VtbWFyeT4NCgkJLy8vCQlUaGlzIG1ldGhvZCBpcyBpbnRlcm5hbC4NCgkJLy8vCTwvc3VtbWFyeT4NCgkJLy8vCTxwcml2YXRlIC8+DQoJCQ0KCQl0cnkgew0KCQkJdmFyIHhoclJlcyA9IHhoci5nZXRSZXNwb25zZUhlYWRlcigiTGFzdC1Nb2RpZmllZCIpOw0KDQoJCQkvLyBGaXJlZm94IGFsd2F5cyByZXR1cm5zIDIwMC4gY2hlY2sgTGFzdC1Nb2RpZmllZCBkYXRlDQoJCQlyZXR1cm4geGhyLnN0YXR1cyA9PSAzMDQgfHwgeGhyUmVzID09IGpRdWVyeS5sYXN0TW9kaWZpZWRbdXJsXTsNCgkJfSBjYXRjaChlKXt9DQoJCXJldHVybiBmYWxzZTsNCgl9LA0KDQoJaHR0cERhdGE6IGZ1bmN0aW9uKCB4aHIsIHR5cGUsIHMgKSB7DQoJCS8vLwk8c3VtbWFyeT4NCgkJLy8vCQlUaGlzIG1ldGhvZCBpcyBpbnRlcm5hbC4NCgkJLy8vCTwvc3VtbWFyeT4NCgkJLy8vCTxwcml2YXRlIC8+DQoJCQ0KCQl2YXIgY3QgPSB4aHIuZ2V0UmVzcG9uc2VIZWFkZXIoImNvbnRlbnQtdHlwZSIpLA0KCQkJeG1sID0gdHlwZSA9PSAieG1sIiB8fCAhdHlwZSAmJiBjdCAmJiBjdC5pbmRleE9mKCJ4bWwiKSA+PSAwLA0KCQkJZGF0YSA9IHhtbCA/IHhoci5yZXNwb25zZVhNTCA6IHhoci5yZXNwb25zZVRleHQ7DQoNCgkJaWYgKCB4bWwgJiYgZGF0YS5kb2N1bWVudEVsZW1lbnQudGFnTmFtZSA9PSAicGFyc2VyZXJyb3IiICkNCgkJCXRocm93ICJwYXJzZXJlcnJvciI7DQoJCQkNCgkJLy8gQWxsb3cgYSBwcmUtZmlsdGVyaW5nIGZ1bmN0aW9uIHRvIHNhbml0aXplIHRoZSByZXNwb25zZQ0KCQkvLyBzICE9IG51bGwgaXMgY2hlY2tlZCB0byBrZWVwIGJhY2t3YXJkcyBjb21wYXRpYmlsaXR5DQoJCWlmKCBzICYmIHMuZGF0YUZpbHRlciApDQoJCQlkYXRhID0gcy5kYXRhRmlsdGVyKCBkYXRhLCB0eXBlICk7DQoNCgkJLy8gVGhlIGZpbHRlciBjYW4gYWN0dWFsbHkgcGFyc2UgdGhlIHJlc3BvbnNlDQoJCWlmKCB0eXBlb2YgZGF0YSA9PT0gInN0cmluZyIgKXsNCg0KCQkJLy8gSWYgdGhlIHR5cGUgaXMgInNjcmlwdCIsIGV2YWwgaXQgaW4gZ2xvYmFsIGNvbnRleHQNCgkJCWlmICggdHlwZSA9PSAic2NyaXB0IiApDQoJCQkJalF1ZXJ5Lmdsb2JhbEV2YWwoIGRhdGEgKTsNCg0KCQkJLy8gR2V0IHRoZSBKYXZhU2NyaXB0IG9iamVjdCwgaWYgSlNPTiBpcyB1c2VkLg0KCQkJaWYgKCB0eXBlID09ICJqc29uIiApDQoJCQkJZGF0YSA9IHdpbmRvd1siZXZhbCJdKCIoIiArIGRhdGEgKyAiKSIpOw0KCQl9DQoJCQ0KCQlyZXR1cm4gZGF0YTsNCgl9LA0KDQoJLy8gU2VyaWFsaXplIGFuIGFycmF5IG9mIGZvcm0gZWxlbWVudHMgb3IgYSBzZXQgb2YNCgkvLyBrZXkvdmFsdWVzIGludG8gYSBxdWVyeSBzdHJpbmcNCglwYXJhbTogZnVuY3Rpb24oIGEgKSB7DQoJCS8vLwk8c3VtbWFyeT4NCgkJLy8vCQlUaGlzIG1ldGhvZCBpcyBpbnRlcm5hbC4gIFVzZSBzZXJpYWxpemUoKSBpbnN0ZWFkLg0KCQkvLy8JPC9zdW1tYXJ5Pg0KCQkvLy8JPHBhcmFtIG5hbWU9ImEiIHR5cGU9Ik1hcCI+QSBtYXAgb2Yga2V5L3ZhbHVlIHBhaXJzIHRvIHNlcmlhbGl6ZSBpbnRvIGEgc3RyaW5nLjwvcGFyYW0+Jw0KCQkvLy8JPHJldHVybnMgdHlwZT0iU3RyaW5nIiAvPg0KCQkvLy8JPHByaXZhdGUgLz4NCgkNCgkJdmFyIHMgPSBbIF07DQoNCgkJZnVuY3Rpb24gYWRkKCBrZXksIHZhbHVlICl7DQoJCQlzWyBzLmxlbmd0aCBdID0gZW5jb2RlVVJJQ29tcG9uZW50KGtleSkgKyAnPScgKyBlbmNvZGVVUklDb21wb25lbnQodmFsdWUpOw0KCQl9Ow0KDQoJCS8vIElmIGFuIGFycmF5IHdhcyBwYXNzZWQgaW4sIGFzc3VtZSB0aGF0IGl0IGlzIGFuIGFycmF5DQoJCS8vIG9mIGZvcm0gZWxlbWVudHMNCgkJaWYgKCBqUXVlcnkuaXNBcnJheShhKSB8fCBhLmpxdWVyeSApDQoJCQkvLyBTZXJpYWxpemUgdGhlIGZvcm0gZWxlbWVudHMNCgkJCWpRdWVyeS5lYWNoKCBhLCBmdW5jdGlvbigpew0KCQkJCWFkZCggdGhpcy5uYW1lLCB0aGlzLnZhbHVlICk7DQoJCQl9KTsNCg0KCQkvLyBPdGhlcndpc2UsIGFzc3VtZSB0aGF0IGl0J3MgYW4gb2JqZWN0IG9mIGtleS92YWx1ZSBwYWlycw0KCQllbHNlDQoJCQkvLyBTZXJpYWxpemUgdGhlIGtleS92YWx1ZXMNCgkJCWZvciAoIHZhciBqIGluIGEgKQ0KCQkJCS8vIElmIHRoZSB2YWx1ZSBpcyBhbiBhcnJheSB0aGVuIHRoZSBrZXkgbmFtZXMgbmVlZCB0byBiZSByZXBlYXRlZA0KCQkJCWlmICggalF1ZXJ5LmlzQXJyYXkoYVtqXSkgKQ0KCQkJCQlqUXVlcnkuZWFjaCggYVtqXSwgZnVuY3Rpb24oKXsNCgkJCQkJCWFkZCggaiwgdGhpcyApOw0KCQkJCQl9KTsNCgkJCQllbHNlDQoJCQkJCWFkZCggaiwgalF1ZXJ5LmlzRnVuY3Rpb24oYVtqXSkgPyBhW2pdKCkgOiBhW2pdICk7DQoNCgkJLy8gUmV0dXJuIHRoZSByZXN1bHRpbmcgc2VyaWFsaXphdGlvbg0KCQlyZXR1cm4gcy5qb2luKCImIikucmVwbGFjZSgvJTIwL2csICIrIik7DQoJfQ0KDQp9KTsNCnZhciBlbGVtZGlzcGxheSA9IHt9LA0KCXRpbWVySWQsDQoJZnhBdHRycyA9IFsNCgkJLy8gaGVpZ2h0IGFuaW1hdGlvbnMNCgkJWyAiaGVpZ2h0IiwgIm1hcmdpblRvcCIsICJtYXJnaW5Cb3R0b20iLCAicGFkZGluZ1RvcCIsICJwYWRkaW5nQm90dG9tIiBdLA0KCQkvLyB3aWR0aCBhbmltYXRpb25zDQoJCVsgIndpZHRoIiwgIm1hcmdpbkxlZnQiLCAibWFyZ2luUmlnaHQiLCAicGFkZGluZ0xlZnQiLCAicGFkZGluZ1JpZ2h0IiBdLA0KCQkvLyBvcGFjaXR5IGFuaW1hdGlvbnMNCgkJWyAib3BhY2l0eSIgXQ0KCV07DQoNCmZ1bmN0aW9uIGdlbkZ4KCB0eXBlLCBudW0gKXsNCgl2YXIgb2JqID0ge307DQoJalF1ZXJ5LmVhY2goIGZ4QXR0cnMuY29uY2F0LmFwcGx5KFtdLCBmeEF0dHJzLnNsaWNlKDAsbnVtKSksIGZ1bmN0aW9uKCl7DQoJCW9ialsgdGhpcyBdID0gdHlwZTsNCgl9KTsNCglyZXR1cm4gb2JqOw0KfQ0KDQpqUXVlcnkuZm4uZXh0ZW5kKHsNCglzaG93OiBmdW5jdGlvbihzcGVlZCxjYWxsYmFjayl7DQoJCS8vLwk8c3VtbWFyeT4NCgkJLy8vCQlTaG93IGFsbCBtYXRjaGVkIGVsZW1lbnRzIHVzaW5nIGEgZ3JhY2VmdWwgYW5pbWF0aW9uIGFuZCBmaXJpbmcgYW4gb3B0aW9uYWwgY2FsbGJhY2sgYWZ0ZXIgY29tcGxldGlvbi4NCgkJLy8vCTwvc3VtbWFyeT4NCgkJLy8vCTxwYXJhbSBuYW1lPSJzcGVlZCIgdHlwZT0iU3RyaW5nIj5BIHN0cmluZyByZXByZXNlbnRpbmcgb25lIG9mIHRocmVlIHByZWRlZmluZWQgc3BlZWRzICgnc2xvdycsICdub3JtYWwnLCBvciAnZmFzdCcpLCBvcg0KCQkvLy8JCXRoZSBudW1iZXIgb2YgbWlsbGlzZWNvbmRzIHRvIHJ1biB0aGUgYW5pbWF0aW9uPC9wYXJhbT4NCgkJLy8vCTxwYXJhbSBuYW1lPSJjYWxsYmFjayIgb3B0aW9uYWw9InRydWUiIHR5cGU9IkZ1bmN0aW9uIj5BIGZ1bmN0aW9uIHRvIGJlIGV4ZWN1dGVkIHdoZW5ldmVyIHRoZSBhbmltYXRpb24gY29tcGxldGVzLCBvbmNlIGZvciBlYWNoIGFuaW1hdGVkIGVsZW1lbnQuICBJdCBzaG91bGQgbWFwIGZ1bmN0aW9uIGNhbGxiYWNrKCkgc3VjaCB0aGF0IHRoaXMgaXMgdGhlIERPTSBlbGVtZW50IGJlaW5nIGFuaW1hdGVkLjwvcGFyYW0+DQoJCS8vLwk8cmV0dXJucyB0eXBlPSJqUXVlcnkiIC8+DQoJCQ0KCQlpZiAoIHNwZWVkICkgew0KCQkJcmV0dXJuIHRoaXMuYW5pbWF0ZSggZ2VuRngoInNob3ciLCAzKSwgc3BlZWQsIGNhbGxiYWNrKTsNCgkJfSBlbHNlIHsNCgkJCWZvciAoIHZhciBpID0gMCwgbCA9IHRoaXMubGVuZ3RoOyBpIDwgbDsgaSsrICl7DQoJCQkJdmFyIG9sZCA9IGpRdWVyeS5kYXRhKHRoaXNbaV0sICJvbGRkaXNwbGF5Iik7DQoJCQkJDQoJCQkJdGhpc1tpXS5zdHlsZS5kaXNwbGF5ID0gb2xkIHx8ICIiOw0KCQkJCQ0KCQkJCWlmICggalF1ZXJ5LmNzcyh0aGlzW2ldLCAiZGlzcGxheSIpID09PSAibm9uZSIgKSB7DQoJCQkJCXZhciB0YWdOYW1lID0gdGhpc1tpXS50YWdOYW1lLCBkaXNwbGF5Ow0KCQkJCQkNCgkJCQkJaWYgKCBlbGVtZGlzcGxheVsgdGFnTmFtZSBdICkgew0KCQkJCQkJZGlzcGxheSA9IGVsZW1kaXNwbGF5WyB0YWdOYW1lIF07DQoJCQkJCX0gZWxzZSB7DQoJCQkJCQl2YXIgZWxlbSA9IGpRdWVyeSgiPCIgKyB0YWdOYW1lICsgIiAvPiIpLmFwcGVuZFRvKCJib2R5Iik7DQoJCQkJCQkNCgkJCQkJCWRpc3BsYXkgPSBlbGVtLmNzcygiZGlzcGxheSIpOw0KCQkJCQkJaWYgKCBkaXNwbGF5ID09PSAibm9uZSIgKQ0KCQkJCQkJCWRpc3BsYXkgPSAiYmxvY2siOw0KCQkJCQkJDQoJCQkJCQllbGVtLnJlbW92ZSgpOw0KCQkJCQkJDQoJCQkJCQllbGVtZGlzcGxheVsgdGFnTmFtZSBdID0gZGlzcGxheTsNCgkJCQkJfQ0KCQkJCQkNCgkJCQkJalF1ZXJ5LmRhdGEodGhpc1tpXSwgIm9sZGRpc3BsYXkiLCBkaXNwbGF5KTsNCgkJCQl9DQoJCQl9DQoNCgkJCS8vIFNldCB0aGUgZGlzcGxheSBvZiB0aGUgZWxlbWVudHMgaW4gYSBzZWNvbmQgbG9vcA0KCQkJLy8gdG8gYXZvaWQgdGhlIGNvbnN0YW50IHJlZmxvdw0KCQkJZm9yICggdmFyIGkgPSAwLCBsID0gdGhpcy5sZW5ndGg7IGkgPCBsOyBpKysgKXsNCgkJCQl0aGlzW2ldLnN0eWxlLmRpc3BsYXkgPSBqUXVlcnkuZGF0YSh0aGlzW2ldLCAib2xkZGlzcGxheSIpIHx8ICIiOw0KCQkJfQ0KCQkJDQoJCQlyZXR1cm4gdGhpczsNCgkJfQ0KCX0sDQoNCgloaWRlOiBmdW5jdGlvbihzcGVlZCxjYWxsYmFjayl7DQoJCS8vLwk8c3VtbWFyeT4NCgkJLy8vCQlIaWRlcyBhbGwgbWF0Y2hlZCBlbGVtZW50cyB1c2luZyBhIGdyYWNlZnVsIGFuaW1hdGlvbiBhbmQgZmlyaW5nIGFuIG9wdGlvbmFsIGNhbGxiYWNrIGFmdGVyIGNvbXBsZXRpb24uDQoJCS8vLwk8L3N1bW1hcnk+DQoJCS8vLwk8cGFyYW0gbmFtZT0ic3BlZWQiIHR5cGU9IlN0cmluZyI+QSBzdHJpbmcgcmVwcmVzZW50aW5nIG9uZSBvZiB0aHJlZSBwcmVkZWZpbmVkIHNwZWVkcyAoJ3Nsb3cnLCAnbm9ybWFsJywgb3IgJ2Zhc3QnKSwgb3INCgkJLy8vCQl0aGUgbnVtYmVyIG9mIG1pbGxpc2Vjb25kcyB0byBydW4gdGhlIGFuaW1hdGlvbjwvcGFyYW0+DQoJCS8vLwk8cGFyYW0gbmFtZT0iY2FsbGJhY2siIG9wdGlvbmFsPSJ0cnVlIiB0eXBlPSJGdW5jdGlvbiI+QSBmdW5jdGlvbiB0byBiZSBleGVjdXRlZCB3aGVuZXZlciB0aGUgYW5pbWF0aW9uIGNvbXBsZXRlcywgb25jZSBmb3IgZWFjaCBhbmltYXRlZCBlbGVtZW50LiAgSXQgc2hvdWxkIG1hcCBmdW5jdGlvbiBjYWxsYmFjaygpIHN1Y2ggdGhhdCB0aGlzIGlzIHRoZSBET00gZWxlbWVudCBiZWluZyBhbmltYXRlZC48L3BhcmFtPg0KCQkvLy8JPHJldHVybnMgdHlwZT0ialF1ZXJ5IiAvPg0KCQ0KCQlpZiAoIHNwZWVkICkgew0KCQkJcmV0dXJuIHRoaXMuYW5pbWF0ZSggZ2VuRngoImhpZGUiLCAzKSwgc3BlZWQsIGNhbGxiYWNrKTsNCgkJfSBlbHNlIHsNCgkJCWZvciAoIHZhciBpID0gMCwgbCA9IHRoaXMubGVuZ3RoOyBpIDwgbDsgaSsrICl7DQoJCQkJdmFyIG9sZCA9IGpRdWVyeS5kYXRhKHRoaXNbaV0sICJvbGRkaXNwbGF5Iik7DQoJCQkJaWYgKCAhb2xkICYmIG9sZCAhPT0gIm5vbmUiICkNCgkJCQkJalF1ZXJ5LmRhdGEodGhpc1tpXSwgIm9sZGRpc3BsYXkiLCBqUXVlcnkuY3NzKHRoaXNbaV0sICJkaXNwbGF5IikpOw0KCQkJfQ0KDQoJCQkvLyBTZXQgdGhlIGRpc3BsYXkgb2YgdGhlIGVsZW1lbnRzIGluIGEgc2Vjb25kIGxvb3ANCgkJCS8vIHRvIGF2b2lkIHRoZSBjb25zdGFudCByZWZsb3cNCgkJCWZvciAoIHZhciBpID0gMCwgbCA9IHRoaXMubGVuZ3RoOyBpIDwgbDsgaSsrICl7DQoJCQkJdGhpc1tpXS5zdHlsZS5kaXNwbGF5ID0gIm5vbmUiOw0KCQkJfQ0KDQoJCQlyZXR1cm4gdGhpczsNCgkJfQ0KCX0sDQoNCgkvLyBTYXZlIHRoZSBvbGQgdG9nZ2xlIGZ1bmN0aW9uDQoJX3RvZ2dsZTogalF1ZXJ5LmZuLnRvZ2dsZSwNCg0KCXRvZ2dsZTogZnVuY3Rpb24oIGZuLCBmbjIgKXsNCgkJLy8vCTxzdW1tYXJ5Pg0KCQkvLy8JCVRvZ2dsZXMgZGlzcGxheWluZyBlYWNoIG9mIHRoZSBzZXQgb2YgbWF0Y2hlZCBlbGVtZW50cy4NCgkJLy8vCTwvc3VtbWFyeT4NCgkJLy8vCTxyZXR1cm5zIHR5cGU9ImpRdWVyeSIgLz4NCgkJDQoJCXZhciBib29sID0gdHlwZW9mIGZuID09PSAiYm9vbGVhbiI7DQoNCgkJcmV0dXJuIGpRdWVyeS5pc0Z1bmN0aW9uKGZuKSAmJiBqUXVlcnkuaXNGdW5jdGlvbihmbjIpID8NCgkJCXRoaXMuX3RvZ2dsZS5hcHBseSggdGhpcywgYXJndW1lbnRzICkgOg0KCQkJZm4gPT0gbnVsbCB8fCBib29sID8NCgkJCQl0aGlzLmVhY2goZnVuY3Rpb24oKXsNCgkJCQkJdmFyIHN0YXRlID0gYm9vbCA/IGZuIDogalF1ZXJ5KHRoaXMpLmlzKCI6aGlkZGVuIik7DQoJCQkJCWpRdWVyeSh0aGlzKVsgc3RhdGUgPyAic2hvdyIgOiAiaGlkZSIgXSgpOw0KCQkJCX0pIDoNCgkJCQl0aGlzLmFuaW1hdGUoZ2VuRngoInRvZ2dsZSIsIDMpLCBmbiwgZm4yKTsNCgl9LA0KDQoJZmFkZVRvOiBmdW5jdGlvbihzcGVlZCx0byxjYWxsYmFjayl7DQoJCS8vLwk8c3VtbWFyeT4NCgkJLy8vCQlGYWRlcyB0aGUgb3BhY2l0eSBvZiBhbGwgbWF0Y2hlZCBlbGVtZW50cyB0byBhIHNwZWNpZmllZCBvcGFjaXR5Lg0KCQkvLy8JPC9zdW1tYXJ5Pg0KCQkvLy8JPHBhcmFtIG5hbWU9InNwZWVkIiB0eXBlPSJTdHJpbmciPkEgc3RyaW5nIHJlcHJlc2VudGluZyBvbmUgb2YgdGhyZWUgcHJlZGVmaW5lZCBzcGVlZHMgKCdzbG93JywgJ25vcm1hbCcsIG9yICdmYXN0JyksIG9yDQoJCS8vLwkJdGhlIG51bWJlciBvZiBtaWxsaXNlY29uZHMgdG8gcnVuIHRoZSBhbmltYXRpb248L3BhcmFtPg0KCQkvLy8JPHBhcmFtIG5hbWU9ImNhbGxiYWNrIiBvcHRpb25hbD0idHJ1ZSIgdHlwZT0iRnVuY3Rpb24iPkEgZnVuY3Rpb24gdG8gYmUgZXhlY3V0ZWQgd2hlbmV2ZXIgdGhlIGFuaW1hdGlvbiBjb21wbGV0ZXMsIG9uY2UgZm9yIGVhY2ggYW5pbWF0ZWQgZWxlbWVudC4gIEl0IHNob3VsZCBtYXAgZnVuY3Rpb24gY2FsbGJhY2soKSBzdWNoIHRoYXQgdGhpcyBpcyB0aGUgRE9NIGVsZW1lbnQgYmVpbmcgYW5pbWF0ZWQuPC9wYXJhbT4NCgkJLy8vCTxyZXR1cm5zIHR5cGU9ImpRdWVyeSIgLz4NCgkJcmV0dXJuIHRoaXMuYW5pbWF0ZSh7b3BhY2l0eTogdG99LCBzcGVlZCwgY2FsbGJhY2spOw0KCX0sDQoNCglhbmltYXRlOiBmdW5jdGlvbiggcHJvcCwgc3BlZWQsIGVhc2luZywgY2FsbGJhY2sgKSB7DQoJCS8vLwk8c3VtbWFyeT4NCgkJLy8vCQlBIGZ1bmN0aW9uIGZvciBtYWtpbmcgY3VzdG9tIGFuaW1hdGlvbnMuDQoJCS8vLwk8L3N1bW1hcnk+DQoJCS8vLwk8cGFyYW0gbmFtZT0icHJvcCIgdHlwZT0iT3B0aW9ucyI+QSBzZXQgb2Ygc3R5bGUgYXR0cmlidXRlcyB0aGF0IHlvdSB3aXNoIHRvIGFuaW1hdGUgYW5kIHRvIHdoYXQgZW5kLjwvcGFyYW0+DQoJCS8vLwk8cGFyYW0gbmFtZT0ic3BlZWQiIG9wdGlvbmFsPSJ0cnVlIiB0eXBlPSJTdHJpbmciPkEgc3RyaW5nIHJlcHJlc2VudGluZyBvbmUgb2YgdGhyZWUgcHJlZGVmaW5lZCBzcGVlZHMgKCdzbG93JywgJ25vcm1hbCcsIG9yICdmYXN0JyksIG9yDQoJCS8vLwkJdGhlIG51bWJlciBvZiBtaWxsaXNlY29uZHMgdG8gcnVuIHRoZSBhbmltYXRpb248L3BhcmFtPg0KCQkvLy8JPHBhcmFtIG5hbWU9ImVhc2luZyIgb3B0aW9uYWw9InRydWUiIHR5cGU9IlN0cmluZyI+VGhlIG5hbWUgb2YgdGhlIGVhc2luZyBlZmZlY3QgdGhhdCB5b3Ugd2FudCB0byB1c2UuICBUaGVyZSBhcmUgdHdvIGJ1aWx0LWluIHZhbHVlcywgJ2xpbmVhcicgYW5kICdzd2luZycuPC9wYXJhbT4NCgkJLy8vCTxwYXJhbSBuYW1lPSJjYWxsYmFjayIgb3B0aW9uYWw9InRydWUiIHR5cGU9IkZ1bmN0aW9uIj5BIGZ1bmN0aW9uIHRvIGJlIGV4ZWN1dGVkIHdoZW5ldmVyIHRoZSBhbmltYXRpb24gY29tcGxldGVzLCBvbmNlIGZvciBlYWNoIGFuaW1hdGVkIGVsZW1lbnQuICBJdCBzaG91bGQgbWFwIGZ1bmN0aW9uIGNhbGxiYWNrKCkgc3VjaCB0aGF0IHRoaXMgaXMgdGhlIERPTSBlbGVtZW50IGJlaW5nIGFuaW1hdGVkLjwvcGFyYW0+DQoJCS8vLwk8cmV0dXJucyB0eXBlPSJqUXVlcnkiIC8+DQoNCgkJdmFyIG9wdGFsbCA9IGpRdWVyeS5zcGVlZChzcGVlZCwgZWFzaW5nLCBjYWxsYmFjayk7DQoNCgkJcmV0dXJuIHRoaXNbIG9wdGFsbC5xdWV1ZSA9PT0gZmFsc2UgPyAiZWFjaCIgOiAicXVldWUiIF0oZnVuY3Rpb24oKXsNCgkJDQoJCQl2YXIgb3B0ID0galF1ZXJ5LmV4dGVuZCh7fSwgb3B0YWxsKSwgcCwNCgkJCQloaWRkZW4gPSB0aGlzLm5vZGVUeXBlID09IDEgJiYgalF1ZXJ5KHRoaXMpLmlzKCI6aGlkZGVuIiksDQoJCQkJc2VsZiA9IHRoaXM7DQoJDQoJCQlmb3IgKCBwIGluIHByb3AgKSB7DQoJCQkJaWYgKCBwcm9wW3BdID09ICJoaWRlIiAmJiBoaWRkZW4gfHwgcHJvcFtwXSA9PSAic2hvdyIgJiYgIWhpZGRlbiApDQoJCQkJCXJldHVybiBvcHQuY29tcGxldGUuY2FsbCh0aGlzKTsNCg0KCQkJCWlmICggKCBwID09ICJoZWlnaHQiIHx8IHAgPT0gIndpZHRoIiApICYmIHRoaXMuc3R5bGUgKSB7DQoJCQkJCS8vIFN0b3JlIGRpc3BsYXkgcHJvcGVydHkNCgkJCQkJb3B0LmRpc3BsYXkgPSBqUXVlcnkuY3NzKHRoaXMsICJkaXNwbGF5Iik7DQoNCgkJCQkJLy8gTWFrZSBzdXJlIHRoYXQgbm90aGluZyBzbmVha3Mgb3V0DQoJCQkJCW9wdC5vdmVyZmxvdyA9IHRoaXMuc3R5bGUub3ZlcmZsb3c7DQoJCQkJfQ0KCQkJfQ0KDQoJCQlpZiAoIG9wdC5vdmVyZmxvdyAhPSBudWxsICkNCgkJCQl0aGlzLnN0eWxlLm92ZXJmbG93ID0gImhpZGRlbiI7DQoNCgkJCW9wdC5jdXJBbmltID0galF1ZXJ5LmV4dGVuZCh7fSwgcHJvcCk7DQoNCgkJCWpRdWVyeS5lYWNoKCBwcm9wLCBmdW5jdGlvbihuYW1lLCB2YWwpew0KCQkJCXZhciBlID0gbmV3IGpRdWVyeS5meCggc2VsZiwgb3B0LCBuYW1lICk7DQoNCgkJCQlpZiAoIC90b2dnbGV8c2hvd3xoaWRlLy50ZXN0KHZhbCkgKQ0KCQkJCQllWyB2YWwgPT0gInRvZ2dsZSIgPyBoaWRkZW4gPyAic2hvdyIgOiAiaGlkZSIgOiB2YWwgXSggcHJvcCApOw0KCQkJCWVsc2Ugew0KCQkJCQl2YXIgcGFydHMgPSB2YWwudG9TdHJpbmcoKS5tYXRjaCgvXihbKy1dPSk/KFtcZCstLl0rKSguKikkLyksDQoJCQkJCQlzdGFydCA9IGUuY3VyKHRydWUpIHx8IDA7DQoNCgkJCQkJaWYgKCBwYXJ0cyApIHsNCgkJCQkJCXZhciBlbmQgPSBwYXJzZUZsb2F0KHBhcnRzWzJdKSwNCgkJCQkJCQl1bml0ID0gcGFydHNbM10gfHwgInB4IjsNCg0KCQkJCQkJLy8gV2UgbmVlZCB0byBjb21wdXRlIHN0YXJ0aW5nIHZhbHVlDQoJCQkJCQlpZiAoIHVuaXQgIT0gInB4IiApIHsNCgkJCQkJCQlzZWxmLnN0eWxlWyBuYW1lIF0gPSAoZW5kIHx8IDEpICsgdW5pdDsNCgkJCQkJCQlzdGFydCA9ICgoZW5kIHx8IDEpIC8gZS5jdXIodHJ1ZSkpICogc3RhcnQ7DQoJCQkJCQkJc2VsZi5zdHlsZVsgbmFtZSBdID0gc3RhcnQgKyB1bml0Ow0KCQkJCQkJfQ0KDQoJCQkJCQkvLyBJZiBhICs9Ly09IHRva2VuIHdhcyBwcm92aWRlZCwgd2UncmUgZG9pbmcgYSByZWxhdGl2ZSBhbmltYXRpb24NCgkJCQkJCWlmICggcGFydHNbMV0gKQ0KCQkJCQkJCWVuZCA9ICgocGFydHNbMV0gPT0gIi09IiA/IC0xIDogMSkgKiBlbmQpICsgc3RhcnQ7DQoNCgkJCQkJCWUuY3VzdG9tKCBzdGFydCwgZW5kLCB1bml0ICk7DQoJCQkJCX0gZWxzZQ0KCQkJCQkJZS5jdXN0b20oIHN0YXJ0LCB2YWwsICIiICk7DQoJCQkJfQ0KCQkJfSk7DQoNCgkJCS8vIEZvciBKUyBzdHJpY3QgY29tcGxpYW5jZQ0KCQkJcmV0dXJuIHRydWU7DQoJCX0pOw0KCX0sDQoNCglzdG9wOiBmdW5jdGlvbihjbGVhclF1ZXVlLCBnb3RvRW5kKXsNCgkJLy8vCTxzdW1tYXJ5Pg0KCQkvLy8JCVN0b3BzIGFsbCBjdXJyZW50bHkgYW5pbWF0aW9ucyBvbiB0aGUgc3BlY2lmaWVkIGVsZW1lbnRzLg0KCQkvLy8JPC9zdW1tYXJ5Pg0KCQkvLy8JPHBhcmFtIG5hbWU9ImNsZWFyUXVldWUiIG9wdGlvbmFsPSJ0cnVlIiB0eXBlPSJCb29sZWFuIj5UcnVlIHRvIGNsZWFyIGFuaW1hdGlvbnMgdGhhdCBhcmUgcXVldWVkIHRvIHJ1bi48L3BhcmFtPg0KCQkvLy8JPHBhcmFtIG5hbWU9ImdvdG9FbmQiIG9wdGlvbmFsPSJ0cnVlIiB0eXBlPSJCb29sZWFuIj5UcnVlIHRvIG1vdmUgdGhlIGVsZW1lbnQgdmFsdWUgdG8gdGhlIGVuZCBvZiBpdHMgYW5pbWF0aW9uIHRhcmdldC48L3BhcmFtPg0KCQkvLy8JPHJldHVybnMgdHlwZT0ialF1ZXJ5IiAvPg0KCQkNCgkJdmFyIHRpbWVycyA9IGpRdWVyeS50aW1lcnM7DQoNCgkJaWYgKGNsZWFyUXVldWUpDQoJCQl0aGlzLnF1ZXVlKFtdKTsNCg0KCQl0aGlzLmVhY2goZnVuY3Rpb24oKXsNCgkJCS8vIGdvIGluIHJldmVyc2Ugb3JkZXIgc28gYW55dGhpbmcgYWRkZWQgdG8gdGhlIHF1ZXVlIGR1cmluZyB0aGUgbG9vcCBpcyBpZ25vcmVkDQoJCQlmb3IgKCB2YXIgaSA9IHRpbWVycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSApDQoJCQkJaWYgKCB0aW1lcnNbaV0uZWxlbSA9PSB0aGlzICkgew0KCQkJCQlpZiAoZ290b0VuZCkNCgkJCQkJCS8vIGZvcmNlIHRoZSBuZXh0IHN0ZXAgdG8gYmUgdGhlIGxhc3QNCgkJCQkJCXRpbWVyc1tpXSh0cnVlKTsNCgkJCQkJdGltZXJzLnNwbGljZShpLCAxKTsNCgkJCQl9DQoJCX0pOw0KDQoJCS8vIHN0YXJ0IHRoZSBuZXh0IGluIHRoZSBxdWV1ZSBpZiB0aGUgbGFzdCBzdGVwIHdhc24ndCBmb3JjZWQNCgkJaWYgKCFnb3RvRW5kKQ0KCQkJdGhpcy5kZXF1ZXVlKCk7DQoNCgkJcmV0dXJuIHRoaXM7DQoJfQ0KDQp9KTsNCg0KLy8gR2VuZXJhdGUgc2hvcnRjdXRzIGZvciBjdXN0b20gYW5pbWF0aW9ucw0KLy8galF1ZXJ5LmVhY2goew0KLy8gCXNsaWRlRG93bjogZ2VuRngoInNob3ciLCAxKSwNCi8vIAlzbGlkZVVwOiBnZW5GeCgiaGlkZSIsIDEpLA0KLy8gCXNsaWRlVG9nZ2xlOiBnZW5GeCgidG9nZ2xlIiwgMSksDQovLyAJZmFkZUluOiB7IG9wYWNpdHk6ICJzaG93IiB9LA0KLy8gCWZhZGVPdXQ6IHsgb3BhY2l0eTogImhpZGUiIH0NCi8vIH0sIGZ1bmN0aW9uKCBuYW1lLCBwcm9wcyApew0KLy8gCWpRdWVyeS5mblsgbmFtZSBdID0gZnVuY3Rpb24oIHNwZWVkLCBjYWxsYmFjayApew0KLy8gCQlyZXR1cm4gdGhpcy5hbmltYXRlKCBwcm9wcywgc3BlZWQsIGNhbGxiYWNrICk7DQovLyAJfTsNCi8vIH0pOw0KDQovLyBbdnNkb2NdIFRoZSBmb2xsb3dpbmcgc2VjdGlvbiBoYXMgYmVlbiBkZW5vcm1hbGl6ZWQgZnJvbSBvcmlnaW5hbCBzb3VyY2VzIGZvciBJbnRlbGxpU2Vuc2UuDQoNCmpRdWVyeS5mbi5zbGlkZURvd24gPSBmdW5jdGlvbiggc3BlZWQsIGNhbGxiYWNrICl7DQoJLy8vCTxzdW1tYXJ5Pg0KCS8vLwkJUmV2ZWFsIGFsbCBtYXRjaGVkIGVsZW1lbnRzIGJ5IGFkanVzdGluZyB0aGVpciBoZWlnaHQuDQoJLy8vCTwvc3VtbWFyeT4NCgkvLy8JPHBhcmFtIG5hbWU9InNwZWVkIiB0eXBlPSJTdHJpbmciPkEgc3RyaW5nIHJlcHJlc2VudGluZyBvbmUgb2YgdGhyZWUgcHJlZGVmaW5lZCBzcGVlZHMgKCdzbG93JywgJ25vcm1hbCcsIG9yICdmYXN0JyksIG9yDQoJLy8vCQl0aGUgbnVtYmVyIG9mIG1pbGxpc2Vjb25kcyB0byBydW4gdGhlIGFuaW1hdGlvbjwvcGFyYW0+DQoJLy8vCTxwYXJhbSBuYW1lPSJjYWxsYmFjayIgb3B0aW9uYWw9InRydWUiIHR5cGU9IkZ1bmN0aW9uIj5BIGZ1bmN0aW9uIHRvIGJlIGV4ZWN1dGVkIHdoZW5ldmVyIHRoZSBhbmltYXRpb24gY29tcGxldGVzLCBvbmNlIGZvciBlYWNoIGFuaW1hdGVkIGVsZW1lbnQuICBJdCBzaG91bGQgbWFwIGZ1bmN0aW9uIGNhbGxiYWNrKCkgc3VjaCB0aGF0IHRoaXMgaXMgdGhlIERPTSBlbGVtZW50IGJlaW5nIGFuaW1hdGVkLjwvcGFyYW0+DQoJLy8vCTxyZXR1cm5zIHR5cGU9ImpRdWVyeSIgLz4NCglyZXR1cm4gdGhpcy5hbmltYXRlKCBnZW5GeCgic2hvdyIsIDEpLCBzcGVlZCwgY2FsbGJhY2sgKTsNCn07DQoNCmpRdWVyeS5mbi5zbGlkZVVwID0gZnVuY3Rpb24oIHNwZWVkLCBjYWxsYmFjayApew0KCS8vLwk8c3VtbWFyeT4NCgkvLy8JCUhpZGluZyBhbGwgbWF0Y2hlZCBlbGVtZW50cyBieSBhZGp1c3RpbmcgdGhlaXIgaGVpZ2h0Lg0KCS8vLwk8L3N1bW1hcnk+DQoJLy8vCTxwYXJhbSBuYW1lPSJzcGVlZCIgdHlwZT0iU3RyaW5nIj5BIHN0cmluZyByZXByZXNlbnRpbmcgb25lIG9mIHRocmVlIHByZWRlZmluZWQgc3BlZWRzICgnc2xvdycsICdub3JtYWwnLCBvciAnZmFzdCcpLCBvcg0KCS8vLwkJdGhlIG51bWJlciBvZiBtaWxsaXNlY29uZHMgdG8gcnVuIHRoZSBhbmltYXRpb248L3BhcmFtPg0KCS8vLwk8cGFyYW0gbmFtZT0iY2FsbGJhY2siIG9wdGlvbmFsPSJ0cnVlIiB0eXBlPSJGdW5jdGlvbiI+QSBmdW5jdGlvbiB0byBiZSBleGVjdXRlZCB3aGVuZXZlciB0aGUgYW5pbWF0aW9uIGNvbXBsZXRlcywgb25jZSBmb3IgZWFjaCBhbmltYXRlZCBlbGVtZW50LiAgSXQgc2hvdWxkIG1hcCBmdW5jdGlvbiBjYWxsYmFjaygpIHN1Y2ggdGhhdCB0aGlzIGlzIHRoZSBET00gZWxlbWVudCBiZWluZyBhbmltYXRlZC48L3BhcmFtPg0KCS8vLwk8cmV0dXJucyB0eXBlPSJqUXVlcnkiIC8+DQoJcmV0dXJuIHRoaXMuYW5pbWF0ZSggZ2VuRngoImhpZGUiLCAxKSwgc3BlZWQsIGNhbGxiYWNrICk7DQp9Ow0KDQpqUXVlcnkuZm4uc2xpZGVUb2dnbGUgPSBmdW5jdGlvbiggc3BlZWQsIGNhbGxiYWNrICl7DQoJLy8vCTxzdW1tYXJ5Pg0KCS8vLwkJVG9nZ2xlcyB0aGUgdmlzaWJpbGl0eSBvZiBhbGwgbWF0Y2hlZCBlbGVtZW50cyBieSBhZGp1c3RpbmcgdGhlaXIgaGVpZ2h0Lg0KCS8vLwk8L3N1bW1hcnk+DQoJLy8vCTxwYXJhbSBuYW1lPSJzcGVlZCIgdHlwZT0iU3RyaW5nIj5BIHN0cmluZyByZXByZXNlbnRpbmcgb25lIG9mIHRocmVlIHByZWRlZmluZWQgc3BlZWRzICgnc2xvdycsICdub3JtYWwnLCBvciAnZmFzdCcpLCBvcg0KCS8vLwkJdGhlIG51bWJlciBvZiBtaWxsaXNlY29uZHMgdG8gcnVuIHRoZSBhbmltYXRpb248L3BhcmFtPg0KCS8vLwk8cGFyYW0gbmFtZT0iY2FsbGJhY2siIG9wdGlvbmFsPSJ0cnVlIiB0eXBlPSJGdW5jdGlvbiI+QSBmdW5jdGlvbiB0byBiZSBleGVjdXRlZCB3aGVuZXZlciB0aGUgYW5pbWF0aW9uIGNvbXBsZXRlcywgb25jZSBmb3IgZWFjaCBhbmltYXRlZCBlbGVtZW50LiAgSXQgc2hvdWxkIG1hcCBmdW5jdGlvbiBjYWxsYmFjaygpIHN1Y2ggdGhhdCB0aGlzIGlzIHRoZSBET00gZWxlbWVudCBiZWluZyBhbmltYXRlZC48L3BhcmFtPg0KCS8vLwk8cmV0dXJucyB0eXBlPSJqUXVlcnkiIC8+DQoJcmV0dXJuIHRoaXMuYW5pbWF0ZSggZ2VuRngoInRvZ2dsZSIsIDEpLCBzcGVlZCwgY2FsbGJhY2sgKTsNCn07DQoNCmpRdWVyeS5mbi5mYWRlSW4gPSBmdW5jdGlvbiggc3BlZWQsIGNhbGxiYWNrICl7DQoJLy8vCTxzdW1tYXJ5Pg0KCS8vLwkJRmFkZXMgaW4gYWxsIG1hdGNoZWQgZWxlbWVudHMgYnkgYWRqdXN0aW5nIHRoZWlyIG9wYWNpdHkuDQoJLy8vCTwvc3VtbWFyeT4NCgkvLy8JPHBhcmFtIG5hbWU9InNwZWVkIiB0eXBlPSJTdHJpbmciPkEgc3RyaW5nIHJlcHJlc2VudGluZyBvbmUgb2YgdGhyZWUgcHJlZGVmaW5lZCBzcGVlZHMgKCdzbG93JywgJ25vcm1hbCcsIG9yICdmYXN0JyksIG9yDQoJLy8vCQl0aGUgbnVtYmVyIG9mIG1pbGxpc2Vjb25kcyB0byBydW4gdGhlIGFuaW1hdGlvbjwvcGFyYW0+DQoJLy8vCTxwYXJhbSBuYW1lPSJjYWxsYmFjayIgb3B0aW9uYWw9InRydWUiIHR5cGU9IkZ1bmN0aW9uIj5BIGZ1bmN0aW9uIHRvIGJlIGV4ZWN1dGVkIHdoZW5ldmVyIHRoZSBhbmltYXRpb24gY29tcGxldGVzLCBvbmNlIGZvciBlYWNoIGFuaW1hdGVkIGVsZW1lbnQuICBJdCBzaG91bGQgbWFwIGZ1bmN0aW9uIGNhbGxiYWNrKCkgc3VjaCB0aGF0IHRoaXMgaXMgdGhlIERPTSBlbGVtZW50IGJlaW5nIGFuaW1hdGVkLjwvcGFyYW0+DQoJLy8vCTxyZXR1cm5zIHR5cGU9ImpRdWVyeSIgLz4NCglyZXR1cm4gdGhpcy5hbmltYXRlKCB7IG9wYWNpdHk6ICJzaG93IiB9LCBzcGVlZCwgY2FsbGJhY2sgKTsNCn07DQoNCmpRdWVyeS5mbi5mYWRlT3V0ID0gZnVuY3Rpb24oIHNwZWVkLCBjYWxsYmFjayApew0KCS8vLwk8c3VtbWFyeT4NCgkvLy8JCUZhZGVzIHRoZSBvcGFjaXR5IG9mIGFsbCBtYXRjaGVkIGVsZW1lbnRzIHRvIGEgc3BlY2lmaWVkIG9wYWNpdHkuDQoJLy8vCTwvc3VtbWFyeT4NCgkvLy8JPHBhcmFtIG5hbWU9InNwZWVkIiB0eXBlPSJTdHJpbmciPkEgc3RyaW5nIHJlcHJlc2VudGluZyBvbmUgb2YgdGhyZWUgcHJlZGVmaW5lZCBzcGVlZHMgKCdzbG93JywgJ25vcm1hbCcsIG9yICdmYXN0JyksIG9yDQoJLy8vCQl0aGUgbnVtYmVyIG9mIG1pbGxpc2Vjb25kcyB0byBydW4gdGhlIGFuaW1hdGlvbjwvcGFyYW0+DQoJLy8vCTxwYXJhbSBuYW1lPSJjYWxsYmFjayIgb3B0aW9uYWw9InRydWUiIHR5cGU9IkZ1bmN0aW9uIj5BIGZ1bmN0aW9uIHRvIGJlIGV4ZWN1dGVkIHdoZW5ldmVyIHRoZSBhbmltYXRpb24gY29tcGxldGVzLCBvbmNlIGZvciBlYWNoIGFuaW1hdGVkIGVsZW1lbnQuICBJdCBzaG91bGQgbWFwIGZ1bmN0aW9uIGNhbGxiYWNrKCkgc3VjaCB0aGF0IHRoaXMgaXMgdGhlIERPTSBlbGVtZW50IGJlaW5nIGFuaW1hdGVkLjwvcGFyYW0+DQoJLy8vCTxyZXR1cm5zIHR5cGU9ImpRdWVyeSIgLz4NCglyZXR1cm4gdGhpcy5hbmltYXRlKCB7IG9wYWNpdHk6ICJoaWRlIiB9LCBzcGVlZCwgY2FsbGJhY2sgKTsNCn07DQoNCmpRdWVyeS5leHRlbmQoew0KDQoJc3BlZWQ6IGZ1bmN0aW9uKHNwZWVkLCBlYXNpbmcsIGZuKSB7DQoJCS8vLwk8c3VtbWFyeT4NCgkJLy8vCQlUaGlzIG1lbWJlciBpcyBpbnRlcm5hbC4NCgkJLy8vCTwvc3VtbWFyeT4NCgkJLy8vCTxwcml2YXRlIC8+DQoJCXZhciBvcHQgPSB0eXBlb2Ygc3BlZWQgPT09ICJvYmplY3QiID8gc3BlZWQgOiB7DQoJCQljb21wbGV0ZTogZm4gfHwgIWZuICYmIGVhc2luZyB8fA0KCQkJCWpRdWVyeS5pc0Z1bmN0aW9uKCBzcGVlZCApICYmIHNwZWVkLA0KCQkJZHVyYXRpb246IHNwZWVkLA0KCQkJZWFzaW5nOiBmbiAmJiBlYXNpbmcgfHwgZWFzaW5nICYmICFqUXVlcnkuaXNGdW5jdGlvbihlYXNpbmcpICYmIGVhc2luZw0KCQl9Ow0KDQoJCW9wdC5kdXJhdGlvbiA9IGpRdWVyeS5meC5vZmYgPyAwIDogdHlwZW9mIG9wdC5kdXJhdGlvbiA9PT0gIm51bWJlciIgPyBvcHQuZHVyYXRpb24gOg0KCQkJalF1ZXJ5LmZ4LnNwZWVkc1tvcHQuZHVyYXRpb25dIHx8IGpRdWVyeS5meC5zcGVlZHMuX2RlZmF1bHQ7DQoNCgkJLy8gUXVldWVpbmcNCgkJb3B0Lm9sZCA9IG9wdC5jb21wbGV0ZTsNCgkJb3B0LmNvbXBsZXRlID0gZnVuY3Rpb24oKXsNCgkJCWlmICggb3B0LnF1ZXVlICE9PSBmYWxzZSApDQoJCQkJalF1ZXJ5KHRoaXMpLmRlcXVldWUoKTsNCgkJCWlmICggalF1ZXJ5LmlzRnVuY3Rpb24oIG9wdC5vbGQgKSApDQoJCQkJb3B0Lm9sZC5jYWxsKCB0aGlzICk7DQoJCX07DQoNCgkJcmV0dXJuIG9wdDsNCgl9LA0KDQoJZWFzaW5nOiB7DQoJCWxpbmVhcjogZnVuY3Rpb24oIHAsIG4sIGZpcnN0TnVtLCBkaWZmICkgew0KICAgCQkvLy8JPHN1bW1hcnk+DQogICAJCS8vLwkJVGhpcyBtZW1iZXIgaXMgaW50ZXJuYWwuDQoJCQkvLy8JPC9zdW1tYXJ5Pg0KICAgCQkvLy8JPHByaXZhdGUgLz4NCgkJCXJldHVybiBmaXJzdE51bSArIGRpZmYgKiBwOw0KCQl9LA0KCQlzd2luZzogZnVuY3Rpb24oIHAsIG4sIGZpcnN0TnVtLCBkaWZmICkgew0KICAgCQkvLy8JPHN1bW1hcnk+DQogICAJCS8vLwkJVGhpcyBtZW1iZXIgaXMgaW50ZXJuYWwuDQoJCQkvLy8JPC9zdW1tYXJ5Pg0KICAgCQkvLy8JPHByaXZhdGUgLz4NCgkJCXJldHVybiAoKC1NYXRoLmNvcyhwKk1hdGguUEkpLzIpICsgMC41KSAqIGRpZmYgKyBmaXJzdE51bTsNCgkJfQ0KCX0sDQoNCgl0aW1lcnM6IFtdLA0KDQoJZng6IGZ1bmN0aW9uKCBlbGVtLCBvcHRpb25zLCBwcm9wICl7DQoJCS8vLwk8c3VtbWFyeT4NCgkJLy8vCQlUaGlzIG1lbWJlciBpcyBpbnRlcm5hbC4NCgkJLy8vCTwvc3VtbWFyeT4NCgkJLy8vCTxwcml2YXRlIC8+DQoJCXRoaXMub3B0aW9ucyA9IG9wdGlvbnM7DQoJCXRoaXMuZWxlbSA9IGVsZW07DQoJCXRoaXMucHJvcCA9IHByb3A7DQoNCgkJaWYgKCAhb3B0aW9ucy5vcmlnICkNCgkJCW9wdGlvbnMub3JpZyA9IHt9Ow0KCX0NCg0KfSk7DQoNCmpRdWVyeS5meC5wcm90b3R5cGUgPSB7DQoNCgkvLyBTaW1wbGUgZnVuY3Rpb24gZm9yIHNldHRpbmcgYSBzdHlsZSB2YWx1ZQ0KCXVwZGF0ZTogZnVuY3Rpb24oKXsNCgkJLy8vCTxzdW1tYXJ5Pg0KCQkvLy8JCVRoaXMgbWVtYmVyIGlzIGludGVybmFsLg0KCQkvLy8JPC9zdW1tYXJ5Pg0KCQkvLy8JPHByaXZhdGUgLz4NCgkJaWYgKCB0aGlzLm9wdGlvbnMuc3RlcCApDQoJCQl0aGlzLm9wdGlvbnMuc3RlcC5jYWxsKCB0aGlzLmVsZW0sIHRoaXMubm93LCB0aGlzICk7DQoNCgkJKGpRdWVyeS5meC5zdGVwW3RoaXMucHJvcF0gfHwgalF1ZXJ5LmZ4LnN0ZXAuX2RlZmF1bHQpKCB0aGlzICk7DQoNCgkJLy8gU2V0IGRpc3BsYXkgcHJvcGVydHkgdG8gYmxvY2sgZm9yIGhlaWdodC93aWR0aCBhbmltYXRpb25zDQoJCWlmICggKCB0aGlzLnByb3AgPT0gImhlaWdodCIgfHwgdGhpcy5wcm9wID09ICJ3aWR0aCIgKSAmJiB0aGlzLmVsZW0uc3R5bGUgKQ0KCQkJdGhpcy5lbGVtLnN0eWxlLmRpc3BsYXkgPSAiYmxvY2siOw0KCX0sDQoNCgkvLyBHZXQgdGhlIGN1cnJlbnQgc2l6ZQ0KCWN1cjogZnVuY3Rpb24oZm9yY2Upew0KCQkvLy8JPHN1bW1hcnk+DQoJCS8vLwkJVGhpcyBtZW1iZXIgaXMgaW50ZXJuYWwuDQoJCS8vLwk8L3N1bW1hcnk+DQoJCS8vLwk8cHJpdmF0ZSAvPg0KCQlpZiAoIHRoaXMuZWxlbVt0aGlzLnByb3BdICE9IG51bGwgJiYgKCF0aGlzLmVsZW0uc3R5bGUgfHwgdGhpcy5lbGVtLnN0eWxlW3RoaXMucHJvcF0gPT0gbnVsbCkgKQ0KCQkJcmV0dXJuIHRoaXMuZWxlbVsgdGhpcy5wcm9wIF07DQoNCgkJdmFyIHIgPSBwYXJzZUZsb2F0KGpRdWVyeS5jc3ModGhpcy5lbGVtLCB0aGlzLnByb3AsIGZvcmNlKSk7DQoJCXJldHVybiByICYmIHIgPiAtMTAwMDAgPyByIDogcGFyc2VGbG9hdChqUXVlcnkuY3VyQ1NTKHRoaXMuZWxlbSwgdGhpcy5wcm9wKSkgfHwgMDsNCgl9LA0KDQoJLy8gU3RhcnQgYW4gYW5pbWF0aW9uIGZyb20gb25lIG51bWJlciB0byBhbm90aGVyDQoJY3VzdG9tOiBmdW5jdGlvbihmcm9tLCB0bywgdW5pdCl7DQoJCXRoaXMuc3RhcnRUaW1lID0gbm93KCk7DQoJCXRoaXMuc3RhcnQgPSBmcm9tOw0KCQl0aGlzLmVuZCA9IHRvOw0KCQl0aGlzLnVuaXQgPSB1bml0IHx8IHRoaXMudW5pdCB8fCAicHgiOw0KCQl0aGlzLm5vdyA9IHRoaXMuc3RhcnQ7DQoJCXRoaXMucG9zID0gdGhpcy5zdGF0ZSA9IDA7DQoNCgkJdmFyIHNlbGYgPSB0aGlzOw0KCQlmdW5jdGlvbiB0KGdvdG9FbmQpew0KCQkJcmV0dXJuIHNlbGYuc3RlcChnb3RvRW5kKTsNCgkJfQ0KDQoJCXQuZWxlbSA9IHRoaXMuZWxlbTsNCg0KCQlpZiAoIHQoKSAmJiBqUXVlcnkudGltZXJzLnB1c2godCkgJiYgIXRpbWVySWQgKSB7DQoJCQl0aW1lcklkID0gc2V0SW50ZXJ2YWwoZnVuY3Rpb24oKXsNCgkJCQl2YXIgdGltZXJzID0galF1ZXJ5LnRpbWVyczsNCg0KCQkJCWZvciAoIHZhciBpID0gMDsgaSA8IHRpbWVycy5sZW5ndGg7IGkrKyApDQoJCQkJCWlmICggIXRpbWVyc1tpXSgpICkNCgkJCQkJCXRpbWVycy5zcGxpY2UoaS0tLCAxKTsNCg0KCQkJCWlmICggIXRpbWVycy5sZW5ndGggKSB7DQoJCQkJCWNsZWFySW50ZXJ2YWwoIHRpbWVySWQgKTsNCgkJCQkJdGltZXJJZCA9IHVuZGVmaW5lZDsNCgkJCQl9DQoJCQl9LCAxMyk7DQoJCX0NCgl9LA0KDQoJLy8gU2ltcGxlICdzaG93JyBmdW5jdGlvbg0KCXNob3c6IGZ1bmN0aW9uKCl7DQoJCS8vLwk8c3VtbWFyeT4NCgkJLy8vCQlEaXNwbGF5cyBlYWNoIG9mIHRoZSBzZXQgb2YgbWF0Y2hlZCBlbGVtZW50cyBpZiB0aGV5IGFyZSBoaWRkZW4uDQoJCS8vLwk8L3N1bW1hcnk+DQoJCS8vIFJlbWVtYmVyIHdoZXJlIHdlIHN0YXJ0ZWQsIHNvIHRoYXQgd2UgY2FuIGdvIGJhY2sgdG8gaXQgbGF0ZXINCgkJdGhpcy5vcHRpb25zLm9yaWdbdGhpcy5wcm9wXSA9IGpRdWVyeS5hdHRyKCB0aGlzLmVsZW0uc3R5bGUsIHRoaXMucHJvcCApOw0KCQl0aGlzLm9wdGlvbnMuc2hvdyA9IHRydWU7DQoNCgkJLy8gQmVnaW4gdGhlIGFuaW1hdGlvbg0KCQkvLyBNYWtlIHN1cmUgdGhhdCB3ZSBzdGFydCBhdCBhIHNtYWxsIHdpZHRoL2hlaWdodCB0byBhdm9pZCBhbnkNCgkJLy8gZmxhc2ggb2YgY29udGVudA0KCQl0aGlzLmN1c3RvbSh0aGlzLnByb3AgPT0gIndpZHRoIiB8fCB0aGlzLnByb3AgPT0gImhlaWdodCIgPyAxIDogMCwgdGhpcy5jdXIoKSk7DQoNCgkJLy8gU3RhcnQgYnkgc2hvd2luZyB0aGUgZWxlbWVudA0KCQlqUXVlcnkodGhpcy5lbGVtKS5zaG93KCk7DQoJfSwNCg0KCS8vIFNpbXBsZSAnaGlkZScgZnVuY3Rpb24NCgloaWRlOiBmdW5jdGlvbigpew0KCQkvLy8JPHN1bW1hcnk+DQoJCS8vLwkJSGlkZXMgZWFjaCBvZiB0aGUgc2V0IG9mIG1hdGNoZWQgZWxlbWVudHMgaWYgdGhleSBhcmUgc2hvd24uDQoJCS8vLwk8L3N1bW1hcnk+DQoNCgkJLy8gUmVtZW1iZXIgd2hlcmUgd2Ugc3RhcnRlZCwgc28gdGhhdCB3ZSBjYW4gZ28gYmFjayB0byBpdCBsYXRlcg0KCQl0aGlzLm9wdGlvbnMub3JpZ1t0aGlzLnByb3BdID0galF1ZXJ5LmF0dHIoIHRoaXMuZWxlbS5zdHlsZSwgdGhpcy5wcm9wICk7DQoJCXRoaXMub3B0aW9ucy5oaWRlID0gdHJ1ZTsNCg0KCQkvLyBCZWdpbiB0aGUgYW5pbWF0aW9uDQoJCXRoaXMuY3VzdG9tKHRoaXMuY3VyKCksIDApOw0KCX0sDQoNCgkvLyBFYWNoIHN0ZXAgb2YgYW4gYW5pbWF0aW9uDQoJc3RlcDogZnVuY3Rpb24oZ290b0VuZCl7DQoJCS8vLwk8c3VtbWFyeT4NCgkJLy8vCQlUaGlzIG1ldGhvZCBpcyBpbnRlcm5hbC4NCgkJLy8vCTwvc3VtbWFyeT4NCgkJLy8vCTxwcml2YXRlIC8+DQoJCXZhciB0ID0gbm93KCk7DQoNCgkJaWYgKCBnb3RvRW5kIHx8IHQgPj0gdGhpcy5vcHRpb25zLmR1cmF0aW9uICsgdGhpcy5zdGFydFRpbWUgKSB7DQoJCQl0aGlzLm5vdyA9IHRoaXMuZW5kOw0KCQkJdGhpcy5wb3MgPSB0aGlzLnN0YXRlID0gMTsNCgkJCXRoaXMudXBkYXRlKCk7DQoNCgkJCXRoaXMub3B0aW9ucy5jdXJBbmltWyB0aGlzLnByb3AgXSA9IHRydWU7DQoNCgkJCXZhciBkb25lID0gdHJ1ZTsNCgkJCWZvciAoIHZhciBpIGluIHRoaXMub3B0aW9ucy5jdXJBbmltICkNCgkJCQlpZiAoIHRoaXMub3B0aW9ucy5jdXJBbmltW2ldICE9PSB0cnVlICkNCgkJCQkJZG9uZSA9IGZhbHNlOw0KDQoJCQlpZiAoIGRvbmUgKSB7DQoJCQkJaWYgKCB0aGlzLm9wdGlvbnMuZGlzcGxheSAhPSBudWxsICkgew0KCQkJCQkvLyBSZXNldCB0aGUgb3ZlcmZsb3cNCgkJCQkJdGhpcy5lbGVtLnN0eWxlLm92ZXJmbG93ID0gdGhpcy5vcHRpb25zLm92ZXJmbG93Ow0KDQoJCQkJCS8vIFJlc2V0IHRoZSBkaXNwbGF5DQoJCQkJCXRoaXMuZWxlbS5zdHlsZS5kaXNwbGF5ID0gdGhpcy5vcHRpb25zLmRpc3BsYXk7DQoJCQkJCWlmICggalF1ZXJ5LmNzcyh0aGlzLmVsZW0sICJkaXNwbGF5IikgPT0gIm5vbmUiICkNCgkJCQkJCXRoaXMuZWxlbS5zdHlsZS5kaXNwbGF5ID0gImJsb2NrIjsNCgkJCQl9DQoNCgkJCQkvLyBIaWRlIHRoZSBlbGVtZW50IGlmIHRoZSAiaGlkZSIgb3BlcmF0aW9uIHdhcyBkb25lDQoJCQkJaWYgKCB0aGlzLm9wdGlvbnMuaGlkZSApDQoJCQkJCWpRdWVyeSh0aGlzLmVsZW0pLmhpZGUoKTsNCg0KCQkJCS8vIFJlc2V0IHRoZSBwcm9wZXJ0aWVzLCBpZiB0aGUgaXRlbSBoYXMgYmVlbiBoaWRkZW4gb3Igc2hvd24NCgkJCQlpZiAoIHRoaXMub3B0aW9ucy5oaWRlIHx8IHRoaXMub3B0aW9ucy5zaG93ICkNCgkJCQkJZm9yICggdmFyIHAgaW4gdGhpcy5vcHRpb25zLmN1ckFuaW0gKQ0KCQkJCQkJalF1ZXJ5LmF0dHIodGhpcy5lbGVtLnN0eWxlLCBwLCB0aGlzLm9wdGlvbnMub3JpZ1twXSk7DQoJCQkJCQ0KCQkJCS8vIEV4ZWN1dGUgdGhlIGNvbXBsZXRlIGZ1bmN0aW9uDQoJCQkJdGhpcy5vcHRpb25zLmNvbXBsZXRlLmNhbGwoIHRoaXMuZWxlbSApOw0KCQkJfQ0KDQoJCQlyZXR1cm4gZmFsc2U7DQoJCX0gZWxzZSB7DQoJCQl2YXIgbiA9IHQgLSB0aGlzLnN0YXJ0VGltZTsNCgkJCXRoaXMuc3RhdGUgPSBuIC8gdGhpcy5vcHRpb25zLmR1cmF0aW9uOw0KDQoJCQkvLyBQZXJmb3JtIHRoZSBlYXNpbmcgZnVuY3Rpb24sIGRlZmF1bHRzIHRvIHN3aW5nDQoJCQl0aGlzLnBvcyA9IGpRdWVyeS5lYXNpbmdbdGhpcy5vcHRpb25zLmVhc2luZyB8fCAoalF1ZXJ5LmVhc2luZy5zd2luZyA/ICJzd2luZyIgOiAibGluZWFyIildKHRoaXMuc3RhdGUsIG4sIDAsIDEsIHRoaXMub3B0aW9ucy5kdXJhdGlvbik7DQoJCQl0aGlzLm5vdyA9IHRoaXMuc3RhcnQgKyAoKHRoaXMuZW5kIC0gdGhpcy5zdGFydCkgKiB0aGlzLnBvcyk7DQoNCgkJCS8vIFBlcmZvcm0gdGhlIG5leHQgc3RlcCBvZiB0aGUgYW5pbWF0aW9uDQoJCQl0aGlzLnVwZGF0ZSgpOw0KCQl9DQoNCgkJcmV0dXJuIHRydWU7DQoJfQ0KDQp9Ow0KDQpqUXVlcnkuZXh0ZW5kKCBqUXVlcnkuZngsIHsNCglzcGVlZHM6ew0KCQlzbG93OiA2MDAsDQogCQlmYXN0OiAyMDAsDQogCQkvLyBEZWZhdWx0IHNwZWVkDQogCQlfZGVmYXVsdDogNDAwDQoJfSwNCglzdGVwOiB7DQoNCgkJb3BhY2l0eTogZnVuY3Rpb24oZngpew0KCQkJalF1ZXJ5LmF0dHIoZnguZWxlbS5zdHlsZSwgIm9wYWNpdHkiLCBmeC5ub3cpOw0KCQl9LA0KDQoJCV9kZWZhdWx0OiBmdW5jdGlvbihmeCl7DQoJCQlpZiAoIGZ4LmVsZW0uc3R5bGUgJiYgZnguZWxlbS5zdHlsZVsgZngucHJvcCBdICE9IG51bGwgKQ0KCQkJCWZ4LmVsZW0uc3R5bGVbIGZ4LnByb3AgXSA9IGZ4Lm5vdyArIGZ4LnVuaXQ7DQoJCQllbHNlDQoJCQkJZnguZWxlbVsgZngucHJvcCBdID0gZngubm93Ow0KCQl9DQoJfQ0KfSk7DQppZiAoIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudFsiZ2V0Qm91bmRpbmdDbGllbnRSZWN0Il0gKQ0KCWpRdWVyeS5mbi5vZmZzZXQgPSBmdW5jdGlvbigpIHsNCgkJLy8vCTxzdW1tYXJ5Pg0KCQkvLy8JCUdldHMgdGhlIGN1cnJlbnQgb2Zmc2V0IG9mIHRoZSBmaXJzdCBtYXRjaGVkIGVsZW1lbnQgcmVsYXRpdmUgdG8gdGhlIHZpZXdwb3J0Lg0KCQkvLy8JPC9zdW1tYXJ5Pg0KCQkvLy8JPHJldHVybnMgdHlwZT0iT2JqZWN0Ij5BbiBvYmplY3Qgd2l0aCB0d28gSW50ZWdlciBwcm9wZXJ0aWVzLCAndG9wJyBhbmQgJ2xlZnQnLjwvcmV0dXJucz4NCgkJaWYgKCAhdGhpc1swXSApIHJldHVybiB7IHRvcDogMCwgbGVmdDogMCB9Ow0KCQlpZiAoIHRoaXNbMF0gPT09IHRoaXNbMF0ub3duZXJEb2N1bWVudC5ib2R5ICkgcmV0dXJuIGpRdWVyeS5vZmZzZXQuYm9keU9mZnNldCggdGhpc1swXSApOw0KCQl2YXIgYm94ICA9IHRoaXNbMF0uZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCksIGRvYyA9IHRoaXNbMF0ub3duZXJEb2N1bWVudCwgYm9keSA9IGRvYy5ib2R5LCBkb2NFbGVtID0gZG9jLmRvY3VtZW50RWxlbWVudCwNCgkJCWNsaWVudFRvcCA9IGRvY0VsZW0uY2xpZW50VG9wIHx8IGJvZHkuY2xpZW50VG9wIHx8IDAsIGNsaWVudExlZnQgPSBkb2NFbGVtLmNsaWVudExlZnQgfHwgYm9keS5jbGllbnRMZWZ0IHx8IDAsDQoJCQl0b3AgID0gYm94LnRvcCAgKyAoc2VsZi5wYWdlWU9mZnNldCB8fCBqUXVlcnkuYm94TW9kZWwgJiYgZG9jRWxlbS5zY3JvbGxUb3AgIHx8IGJvZHkuc2Nyb2xsVG9wICkgLSBjbGllbnRUb3AsDQoJCQlsZWZ0ID0gYm94LmxlZnQgKyAoc2VsZi5wYWdlWE9mZnNldCB8fCBqUXVlcnkuYm94TW9kZWwgJiYgZG9jRWxlbS5zY3JvbGxMZWZ0IHx8IGJvZHkuc2Nyb2xsTGVmdCkgLSBjbGllbnRMZWZ0Ow0KCQlyZXR1cm4geyB0b3A6IHRvcCwgbGVmdDogbGVmdCB9Ow0KCX07DQplbHNlIA0KCWpRdWVyeS5mbi5vZmZzZXQgPSBmdW5jdGlvbigpIHsNCgkJLy8vCTxzdW1tYXJ5Pg0KCQkvLy8JCUdldHMgdGhlIGN1cnJlbnQgb2Zmc2V0IG9mIHRoZSBmaXJzdCBtYXRjaGVkIGVsZW1lbnQgcmVsYXRpdmUgdG8gdGhlIHZpZXdwb3J0Lg0KCQkvLy8JPC9zdW1tYXJ5Pg0KCQkvLy8JPHJldHVybnMgdHlwZT0iT2JqZWN0Ij5BbiBvYmplY3Qgd2l0aCB0d28gSW50ZWdlciBwcm9wZXJ0aWVzLCAndG9wJyBhbmQgJ2xlZnQnLjwvcmV0dXJucz4NCgkJaWYgKCAhdGhpc1swXSApIHJldHVybiB7IHRvcDogMCwgbGVmdDogMCB9Ow0KCQlpZiAoIHRoaXNbMF0gPT09IHRoaXNbMF0ub3duZXJEb2N1bWVudC5ib2R5ICkgcmV0dXJuIGpRdWVyeS5vZmZzZXQuYm9keU9mZnNldCggdGhpc1swXSApOw0KCQlqUXVlcnkub2Zmc2V0LmluaXRpYWxpemVkIHx8IGpRdWVyeS5vZmZzZXQuaW5pdGlhbGl6ZSgpOw0KDQoJCXZhciBlbGVtID0gdGhpc1swXSwgb2Zmc2V0UGFyZW50ID0gZWxlbS5vZmZzZXRQYXJlbnQsIHByZXZPZmZzZXRQYXJlbnQgPSBlbGVtLA0KCQkJZG9jID0gZWxlbS5vd25lckRvY3VtZW50LCBjb21wdXRlZFN0eWxlLCBkb2NFbGVtID0gZG9jLmRvY3VtZW50RWxlbWVudCwNCgkJCWJvZHkgPSBkb2MuYm9keSwgZGVmYXVsdFZpZXcgPSBkb2MuZGVmYXVsdFZpZXcsDQoJCQlwcmV2Q29tcHV0ZWRTdHlsZSA9IGRlZmF1bHRWaWV3LmdldENvbXB1dGVkU3R5bGUoZWxlbSwgbnVsbCksDQoJCQl0b3AgPSBlbGVtLm9mZnNldFRvcCwgbGVmdCA9IGVsZW0ub2Zmc2V0TGVmdDsNCg0KCQl3aGlsZSAoIChlbGVtID0gZWxlbS5wYXJlbnROb2RlKSAmJiBlbGVtICE9PSBib2R5ICYmIGVsZW0gIT09IGRvY0VsZW0gKSB7DQoJCQljb21wdXRlZFN0eWxlID0gZGVmYXVsdFZpZXcuZ2V0Q29tcHV0ZWRTdHlsZShlbGVtLCBudWxsKTsNCgkJCXRvcCAtPSBlbGVtLnNjcm9sbFRvcCwgbGVmdCAtPSBlbGVtLnNjcm9sbExlZnQ7DQoJCQlpZiAoIGVsZW0gPT09IG9mZnNldFBhcmVudCApIHsNCgkJCQl0b3AgKz0gZWxlbS5vZmZzZXRUb3AsIGxlZnQgKz0gZWxlbS5vZmZzZXRMZWZ0Ow0KCQkJCWlmICggalF1ZXJ5Lm9mZnNldC5kb2VzTm90QWRkQm9yZGVyICYmICEoalF1ZXJ5Lm9mZnNldC5kb2VzQWRkQm9yZGVyRm9yVGFibGVBbmRDZWxscyAmJiAvXnQoYWJsZXxkfGgpJC9pLnRlc3QoZWxlbS50YWdOYW1lKSkgKQ0KCQkJCQl0b3AgICs9IHBhcnNlSW50KCBjb21wdXRlZFN0eWxlLmJvcmRlclRvcFdpZHRoLCAgMTApIHx8IDAsDQoJCQkJCWxlZnQgKz0gcGFyc2VJbnQoIGNvbXB1dGVkU3R5bGUuYm9yZGVyTGVmdFdpZHRoLCAxMCkgfHwgMDsNCgkJCQlwcmV2T2Zmc2V0UGFyZW50ID0gb2Zmc2V0UGFyZW50LCBvZmZzZXRQYXJlbnQgPSBlbGVtLm9mZnNldFBhcmVudDsNCgkJCX0NCgkJCWlmICggalF1ZXJ5Lm9mZnNldC5zdWJ0cmFjdHNCb3JkZXJGb3JPdmVyZmxvd05vdFZpc2libGUgJiYgY29tcHV0ZWRTdHlsZS5vdmVyZmxvdyAhPT0gInZpc2libGUiICkNCgkJCQl0b3AgICs9IHBhcnNlSW50KCBjb21wdXRlZFN0eWxlLmJvcmRlclRvcFdpZHRoLCAgMTApIHx8IDAsDQoJCQkJbGVmdCArPSBwYXJzZUludCggY29tcHV0ZWRTdHlsZS5ib3JkZXJMZWZ0V2lkdGgsIDEwKSB8fCAwOw0KCQkJcHJldkNvbXB1dGVkU3R5bGUgPSBjb21wdXRlZFN0eWxlOw0KCQl9DQoNCgkJaWYgKCBwcmV2Q29tcHV0ZWRTdHlsZS5wb3NpdGlvbiA9PT0gInJlbGF0aXZlIiB8fCBwcmV2Q29tcHV0ZWRTdHlsZS5wb3NpdGlvbiA9PT0gInN0YXRpYyIgKQ0KCQkJdG9wICArPSBib2R5Lm9mZnNldFRvcCwNCgkJCWxlZnQgKz0gYm9keS5vZmZzZXRMZWZ0Ow0KDQoJCWlmICggcHJldkNvbXB1dGVkU3R5bGUucG9zaXRpb24gPT09ICJmaXhlZCIgKQ0KCQkJdG9wICArPSBNYXRoLm1heChkb2NFbGVtLnNjcm9sbFRvcCwgYm9keS5zY3JvbGxUb3ApLA0KCQkJbGVmdCArPSBNYXRoLm1heChkb2NFbGVtLnNjcm9sbExlZnQsIGJvZHkuc2Nyb2xsTGVmdCk7DQoNCgkJcmV0dXJuIHsgdG9wOiB0b3AsIGxlZnQ6IGxlZnQgfTsNCgl9Ow0KDQpqUXVlcnkub2Zmc2V0ID0gew0KCWluaXRpYWxpemU6IGZ1bmN0aW9uKCkgew0KCQlpZiAoIHRoaXMuaW5pdGlhbGl6ZWQgKSByZXR1cm47DQoJCXZhciBib2R5ID0gZG9jdW1lbnQuYm9keSwgY29udGFpbmVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2JyksIGlubmVyRGl2LCBjaGVja0RpdiwgdGFibGUsIHRkLCBydWxlcywgcHJvcCwgYm9keU1hcmdpblRvcCA9IGJvZHkuc3R5bGUubWFyZ2luVG9wLA0KCQkJaHRtbCA9ICc8ZGl2IHN0eWxlPSJwb3NpdGlvbjphYnNvbHV0ZTt0b3A6MDtsZWZ0OjA7bWFyZ2luOjA7Ym9yZGVyOjVweCBzb2xpZCAjMDAwO3BhZGRpbmc6MDt3aWR0aDoxcHg7aGVpZ2h0OjFweDsiPjxkaXY+PC9kaXY+PC9kaXY+PHRhYmxlIHN0eWxlPSJwb3NpdGlvbjphYnNvbHV0ZTt0b3A6MDtsZWZ0OjA7bWFyZ2luOjA7Ym9yZGVyOjVweCBzb2xpZCAjMDAwO3BhZGRpbmc6MDt3aWR0aDoxcHg7aGVpZ2h0OjFweDsiY2VsbHBhZGRpbmc9IjAiY2VsbHNwYWNpbmc9IjAiPjx0cj48dGQ+PC90ZD48L3RyPjwvdGFibGU+JzsNCg0KCQlydWxlcyA9IHsgcG9zaXRpb246ICdhYnNvbHV0ZScsIHRvcDogMCwgbGVmdDogMCwgbWFyZ2luOiAwLCBib3JkZXI6IDAsIHdpZHRoOiAnMXB4JywgaGVpZ2h0OiAnMXB4JywgdmlzaWJpbGl0eTogJ2hpZGRlbicgfTsNCgkJZm9yICggcHJvcCBpbiBydWxlcyApIGNvbnRhaW5lci5zdHlsZVtwcm9wXSA9IHJ1bGVzW3Byb3BdOw0KDQoJCWNvbnRhaW5lci5pbm5lckhUTUwgPSBodG1sOw0KCQlib2R5Lmluc2VydEJlZm9yZShjb250YWluZXIsIGJvZHkuZmlyc3RDaGlsZCk7DQoJCWlubmVyRGl2ID0gY29udGFpbmVyLmZpcnN0Q2hpbGQsIGNoZWNrRGl2ID0gaW5uZXJEaXYuZmlyc3RDaGlsZCwgdGQgPSBpbm5lckRpdi5uZXh0U2libGluZy5maXJzdENoaWxkLmZpcnN0Q2hpbGQ7DQoNCgkJdGhpcy5kb2VzTm90QWRkQm9yZGVyID0gKGNoZWNrRGl2Lm9mZnNldFRvcCAhPT0gNSk7DQoJCXRoaXMuZG9lc0FkZEJvcmRlckZvclRhYmxlQW5kQ2VsbHMgPSAodGQub2Zmc2V0VG9wID09PSA1KTsNCg0KCQlpbm5lckRpdi5zdHlsZS5vdmVyZmxvdyA9ICdoaWRkZW4nLCBpbm5lckRpdi5zdHlsZS5wb3NpdGlvbiA9ICdyZWxhdGl2ZSc7DQoJCXRoaXMuc3VidHJhY3RzQm9yZGVyRm9yT3ZlcmZsb3dOb3RWaXNpYmxlID0gKGNoZWNrRGl2Lm9mZnNldFRvcCA9PT0gLTUpOw0KDQoJCWJvZHkuc3R5bGUubWFyZ2luVG9wID0gJzFweCc7DQoJCXRoaXMuZG9lc05vdEluY2x1ZGVNYXJnaW5JbkJvZHlPZmZzZXQgPSAoYm9keS5vZmZzZXRUb3AgPT09IDApOw0KCQlib2R5LnN0eWxlLm1hcmdpblRvcCA9IGJvZHlNYXJnaW5Ub3A7DQoNCgkJYm9keS5yZW1vdmVDaGlsZChjb250YWluZXIpOw0KCQl0aGlzLmluaXRpYWxpemVkID0gdHJ1ZTsNCgl9LA0KDQoJYm9keU9mZnNldDogZnVuY3Rpb24oYm9keSkgew0KCQlqUXVlcnkub2Zmc2V0LmluaXRpYWxpemVkIHx8IGpRdWVyeS5vZmZzZXQuaW5pdGlhbGl6ZSgpOw0KCQl2YXIgdG9wID0gYm9keS5vZmZzZXRUb3AsIGxlZnQgPSBib2R5Lm9mZnNldExlZnQ7DQoJCWlmICggalF1ZXJ5Lm9mZnNldC5kb2VzTm90SW5jbHVkZU1hcmdpbkluQm9keU9mZnNldCApDQoJCQl0b3AgICs9IHBhcnNlSW50KCBqUXVlcnkuY3VyQ1NTKGJvZHksICdtYXJnaW5Ub3AnLCAgdHJ1ZSksIDEwICkgfHwgMCwNCgkJCWxlZnQgKz0gcGFyc2VJbnQoIGpRdWVyeS5jdXJDU1MoYm9keSwgJ21hcmdpbkxlZnQnLCB0cnVlKSwgMTAgKSB8fCAwOw0KCQlyZXR1cm4geyB0b3A6IHRvcCwgbGVmdDogbGVmdCB9Ow0KCX0NCn07DQoNCg0KalF1ZXJ5LmZuLmV4dGVuZCh7DQoJcG9zaXRpb246IGZ1bmN0aW9uKCkgew0KCQkvLy8JPHN1bW1hcnk+DQoJCS8vLwkJR2V0cyB0aGUgdG9wIGFuZCBsZWZ0IHBvc2l0aW9ucyBvZiBhbiBlbGVtZW50IHJlbGF0aXZlIHRvIGl0cyBvZmZzZXQgcGFyZW50Lg0KCQkvLy8JPC9zdW1tYXJ5Pg0KCQkvLy8JPHJldHVybnMgdHlwZT0iT2JqZWN0Ij5BbiBvYmplY3Qgd2l0aCB0d28gaW50ZWdlciBwcm9wZXJ0aWVzLCAndG9wJyBhbmQgJ2xlZnQnLjwvcmV0dXJucz4NCgkJdmFyIGxlZnQgPSAwLCB0b3AgPSAwLCByZXN1bHRzOw0KDQoJCWlmICggdGhpc1swXSApIHsNCgkJCS8vIEdldCAqcmVhbCogb2Zmc2V0UGFyZW50DQoJCQl2YXIgb2Zmc2V0UGFyZW50ID0gdGhpcy5vZmZzZXRQYXJlbnQoKSwNCg0KCQkJLy8gR2V0IGNvcnJlY3Qgb2Zmc2V0cw0KCQkJb2Zmc2V0ICAgICAgID0gdGhpcy5vZmZzZXQoKSwNCgkJCXBhcmVudE9mZnNldCA9IC9eYm9keXxodG1sJC9pLnRlc3Qob2Zmc2V0UGFyZW50WzBdLnRhZ05hbWUpID8geyB0b3A6IDAsIGxlZnQ6IDAgfSA6IG9mZnNldFBhcmVudC5vZmZzZXQoKTsNCg0KCQkJLy8gU3VidHJhY3QgZWxlbWVudCBtYXJnaW5zDQoJCQkvLyBub3RlOiB3aGVuIGFuIGVsZW1lbnQgaGFzIG1hcmdpbjogYXV0byB0aGUgb2Zmc2V0TGVmdCBhbmQgbWFyZ2luTGVmdCANCgkJCS8vIGFyZSB0aGUgc2FtZSBpbiBTYWZhcmkgY2F1c2luZyBvZmZzZXQubGVmdCB0byBpbmNvcnJlY3RseSBiZSAwDQoJCQlvZmZzZXQudG9wICAtPSBudW0oIHRoaXMsICdtYXJnaW5Ub3AnICApOw0KCQkJb2Zmc2V0LmxlZnQgLT0gbnVtKCB0aGlzLCAnbWFyZ2luTGVmdCcgKTsNCg0KCQkJLy8gQWRkIG9mZnNldFBhcmVudCBib3JkZXJzDQoJCQlwYXJlbnRPZmZzZXQudG9wICArPSBudW0oIG9mZnNldFBhcmVudCwgJ2JvcmRlclRvcFdpZHRoJyAgKTsNCgkJCXBhcmVudE9mZnNldC5sZWZ0ICs9IG51bSggb2Zmc2V0UGFyZW50LCAnYm9yZGVyTGVmdFdpZHRoJyApOw0KDQoJCQkvLyBTdWJ0cmFjdCB0aGUgdHdvIG9mZnNldHMNCgkJCXJlc3VsdHMgPSB7DQoJCQkJdG9wOiAgb2Zmc2V0LnRvcCAgLSBwYXJlbnRPZmZzZXQudG9wLA0KCQkJCWxlZnQ6IG9mZnNldC5sZWZ0IC0gcGFyZW50T2Zmc2V0LmxlZnQNCgkJCX07DQoJCX0NCg0KCQlyZXR1cm4gcmVzdWx0czsNCgl9LA0KDQoJb2Zmc2V0UGFyZW50OiBmdW5jdGlvbigpIHsNCgkJLy8vCTxzdW1tYXJ5Pg0KCQkvLy8JCVRoaXMgbWV0aG9kIGlzIGludGVybmFsLg0KCQkvLy8JPC9zdW1tYXJ5Pg0KCQkvLy8JPHByaXZhdGUgLz4NCgkJdmFyIG9mZnNldFBhcmVudCA9IHRoaXNbMF0ub2Zmc2V0UGFyZW50IHx8IGRvY3VtZW50LmJvZHk7DQoJCXdoaWxlICggb2Zmc2V0UGFyZW50ICYmICghL15ib2R5fGh0bWwkL2kudGVzdChvZmZzZXRQYXJlbnQudGFnTmFtZSkgJiYgalF1ZXJ5LmNzcyhvZmZzZXRQYXJlbnQsICdwb3NpdGlvbicpID09ICdzdGF0aWMnKSApDQoJCQlvZmZzZXRQYXJlbnQgPSBvZmZzZXRQYXJlbnQub2Zmc2V0UGFyZW50Ow0KCQlyZXR1cm4galF1ZXJ5KG9mZnNldFBhcmVudCk7DQoJfQ0KfSk7DQoNCg0KLy8gQ3JlYXRlIHNjcm9sbExlZnQgYW5kIHNjcm9sbFRvcCBtZXRob2RzDQpqUXVlcnkuZWFjaCggWydMZWZ0J10sIGZ1bmN0aW9uKGksIG5hbWUpIHsNCgl2YXIgbWV0aG9kID0gJ3Njcm9sbCcgKyBuYW1lOw0KCQ0KCWpRdWVyeS5mblsgbWV0aG9kIF0gPSBmdW5jdGlvbih2YWwpIHsNCgkJLy8vCTxzdW1tYXJ5Pg0KCQkvLy8JCUdldHMgYW5kIG9wdGlvbmFsbHkgc2V0cyB0aGUgc2Nyb2xsIGxlZnQgb2Zmc2V0IG9mIHRoZSBmaXJzdCBtYXRjaGVkIGVsZW1lbnQuDQoJCS8vLwk8L3N1bW1hcnk+DQoJCS8vLwk8cGFyYW0gbmFtZT0idmFsIiB0eXBlPSJOdW1iZXIiIGludGVnZXI9InRydWUiIG9wdGlvbmFsPSJ0cnVlIj5BIHBvc2l0aXZlIG51bWJlciByZXByZXNlbnRpbmcgdGhlIGRlc2lyZWQgc2Nyb2xsIGxlZnQgb2Zmc2V0LjwvcGFyYW0+DQoJCS8vLwk8cmV0dXJucyB0eXBlPSJOdW1iZXIiIGludGVnZXI9InRydWUiPlRoZSBzY3JvbGwgbGVmdCBvZmZzZXQgb2YgdGhlIGZpcnN0IG1hdGNoZWQgZWxlbWVudC48L3JldHVybnM+DQoJCWlmICghdGhpc1swXSkgcmV0dXJuIG51bGw7DQoNCgkJcmV0dXJuIHZhbCAhPT0gdW5kZWZpbmVkID8NCg0KCQkJLy8gU2V0IHRoZSBzY3JvbGwgb2Zmc2V0DQoJCQl0aGlzLmVhY2goZnVuY3Rpb24oKSB7DQoJCQkJdGhpcyA9PSB3aW5kb3cgfHwgdGhpcyA9PSBkb2N1bWVudCA/DQoJCQkJCXdpbmRvdy5zY3JvbGxUbygNCgkJCQkJCSFpID8gdmFsIDogalF1ZXJ5KHdpbmRvdykuc2Nyb2xsTGVmdCgpLA0KCQkJCQkJIGkgPyB2YWwgOiBqUXVlcnkod2luZG93KS5zY3JvbGxUb3AoKQ0KCQkJCQkpIDoNCgkJCQkJdGhpc1sgbWV0aG9kIF0gPSB2YWw7DQoJCQl9KSA6DQoNCgkJCS8vIFJldHVybiB0aGUgc2Nyb2xsIG9mZnNldA0KCQkJdGhpc1swXSA9PSB3aW5kb3cgfHwgdGhpc1swXSA9PSBkb2N1bWVudCA/DQoJCQkJc2VsZlsgaSA/ICdwYWdlWU9mZnNldCcgOiAncGFnZVhPZmZzZXQnIF0gfHwNCgkJCQkJalF1ZXJ5LmJveE1vZGVsICYmIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudFsgbWV0aG9kIF0gfHwNCgkJCQkJZG9jdW1lbnQuYm9keVsgbWV0aG9kIF0gOg0KCQkJCXRoaXNbMF1bIG1ldGhvZCBdOw0KCX07DQp9KTsNCg0KLy8gQ3JlYXRlIHNjcm9sbExlZnQgYW5kIHNjcm9sbFRvcCBtZXRob2RzDQpqUXVlcnkuZWFjaCggWydUb3AnXSwgZnVuY3Rpb24oaSwgbmFtZSkgew0KCXZhciBtZXRob2QgPSAnc2Nyb2xsJyArIG5hbWU7DQoJDQoJalF1ZXJ5LmZuWyBtZXRob2QgXSA9IGZ1bmN0aW9uKHZhbCkgew0KCQkvLy8JPHN1bW1hcnk+DQoJCS8vLwkJR2V0cyBhbmQgb3B0aW9uYWxseSBzZXRzIHRoZSBzY3JvbGwgdG9wIG9mZnNldCBvZiB0aGUgZmlyc3QgbWF0Y2hlZCBlbGVtZW50Lg0KCQkvLy8JPC9zdW1tYXJ5Pg0KCQkvLy8JPHBhcmFtIG5hbWU9InZhbCIgdHlwZT0iTnVtYmVyIiBpbnRlZ2VyPSJ0cnVlIiBvcHRpb25hbD0idHJ1ZSI+QSBwb3NpdGl2ZSBudW1iZXIgcmVwcmVzZW50aW5nIHRoZSBkZXNpcmVkIHNjcm9sbCB0b3Agb2Zmc2V0LjwvcGFyYW0+DQoJCS8vLwk8cmV0dXJucyB0eXBlPSJOdW1iZXIiIGludGVnZXI9InRydWUiPlRoZSBzY3JvbGwgdG9wIG9mZnNldCBvZiB0aGUgZmlyc3QgbWF0Y2hlZCBlbGVtZW50LjwvcmV0dXJucz4NCgkJaWYgKCF0aGlzWzBdKSByZXR1cm4gbnVsbDsNCg0KCQlyZXR1cm4gdmFsICE9PSB1bmRlZmluZWQgPw0KDQoJCQkvLyBTZXQgdGhlIHNjcm9sbCBvZmZzZXQNCgkJCXRoaXMuZWFjaChmdW5jdGlvbigpIHsNCgkJCQl0aGlzID09IHdpbmRvdyB8fCB0aGlzID09IGRvY3VtZW50ID8NCgkJCQkJd2luZG93LnNjcm9sbFRvKA0KCQkJCQkJIWkgPyB2YWwgOiBqUXVlcnkod2luZG93KS5zY3JvbGxMZWZ0KCksDQoJCQkJCQkgaSA/IHZhbCA6IGpRdWVyeSh3aW5kb3cpLnNjcm9sbFRvcCgpDQoJCQkJCSkgOg0KCQkJCQl0aGlzWyBtZXRob2QgXSA9IHZhbDsNCgkJCX0pIDoNCg0KCQkJLy8gUmV0dXJuIHRoZSBzY3JvbGwgb2Zmc2V0DQoJCQl0aGlzWzBdID09IHdpbmRvdyB8fCB0aGlzWzBdID09IGRvY3VtZW50ID8NCgkJCQlzZWxmWyBpID8gJ3BhZ2VZT2Zmc2V0JyA6ICdwYWdlWE9mZnNldCcgXSB8fA0KCQkJCQlqUXVlcnkuYm94TW9kZWwgJiYgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50WyBtZXRob2QgXSB8fA0KCQkJCQlkb2N1bWVudC5ib2R5WyBtZXRob2QgXSA6DQoJCQkJdGhpc1swXVsgbWV0aG9kIF07DQoJfTsNCn0pOw0KDQovLyBDcmVhdGUgaW5uZXJIZWlnaHQsIGlubmVyV2lkdGgsIG91dGVySGVpZ2h0IGFuZCBvdXRlcldpZHRoIG1ldGhvZHMNCmpRdWVyeS5lYWNoKFsgIkhlaWdodCIgXSwgZnVuY3Rpb24oaSwgbmFtZSl7DQoNCgl2YXIgdGwgPSBpID8gIkxlZnQiICA6ICJUb3AiLCAgLy8gdG9wIG9yIGxlZnQNCgkJYnIgPSBpID8gIlJpZ2h0IiA6ICJCb3R0b20iLCAvLyBib3R0b20gb3IgcmlnaHQNCgkJbG93ZXIgPSBuYW1lLnRvTG93ZXJDYXNlKCk7DQoNCgkvLyBpbm5lckhlaWdodCBhbmQgaW5uZXJXaWR0aA0KCWpRdWVyeS5mblsiaW5uZXIiICsgbmFtZV0gPSBmdW5jdGlvbigpew0KCQkvLy8JPHN1bW1hcnk+DQoJCS8vLwkJR2V0cyB0aGUgaW5uZXIgaGVpZ2h0IG9mIHRoZSBmaXJzdCBtYXRjaGVkIGVsZW1lbnQsIGV4Y2x1ZGluZyBib3JkZXIgYnV0IGluY2x1ZGluZyBwYWRkaW5nLg0KCQkvLy8JPC9zdW1tYXJ5Pg0KCQkvLy8JPHJldHVybnMgdHlwZT0iTnVtYmVyIiBpbnRlZ2VyPSJ0cnVlIj5UaGUgb3V0ZXIgaGVpZ2h0IG9mIHRoZSBmaXJzdCBtYXRjaGVkIGVsZW1lbnQuPC9yZXR1cm5zPg0KCQlyZXR1cm4gdGhpc1swXSA/DQoJCQlqUXVlcnkuY3NzKCB0aGlzWzBdLCBsb3dlciwgZmFsc2UsICJwYWRkaW5nIiApIDoNCgkJCW51bGw7DQoJfTsNCg0KCS8vIG91dGVySGVpZ2h0IGFuZCBvdXRlcldpZHRoDQoJalF1ZXJ5LmZuWyJvdXRlciIgKyBuYW1lXSA9IGZ1bmN0aW9uKG1hcmdpbikgew0KCQkvLy8JPHN1bW1hcnk+DQoJCS8vLwkJR2V0cyB0aGUgb3V0ZXIgaGVpZ2h0IG9mIHRoZSBmaXJzdCBtYXRjaGVkIGVsZW1lbnQsIGluY2x1ZGluZyBib3JkZXIgYW5kIHBhZGRpbmcgYnkgZGVmYXVsdC4NCgkJLy8vCTwvc3VtbWFyeT4NCgkJLy8vCTxwYXJhbSBuYW1lPSJtYXJnaW5zIiB0eXBlPSJNYXAiPkEgc2V0IG9mIGtleS92YWx1ZSBwYWlycyB0aGF0IHNwZWNpZnkgdGhlIG9wdGlvbnMgZm9yIHRoZSBtZXRob2QuPC9wYXJhbT4NCgkJLy8vCTxyZXR1cm5zIHR5cGU9Ik51bWJlciIgaW50ZWdlcj0idHJ1ZSI+VGhlIG91dGVyIGhlaWdodCBvZiB0aGUgZmlyc3QgbWF0Y2hlZCBlbGVtZW50LjwvcmV0dXJucz4NCgkJcmV0dXJuIHRoaXNbMF0gPw0KCQkJalF1ZXJ5LmNzcyggdGhpc1swXSwgbG93ZXIsIGZhbHNlLCBtYXJnaW4gPyAibWFyZ2luIiA6ICJib3JkZXIiICkgOg0KCQkJbnVsbDsNCgl9Ow0KCQ0KCXZhciB0eXBlID0gbmFtZS50b0xvd2VyQ2FzZSgpOw0KDQoJalF1ZXJ5LmZuWyB0eXBlIF0gPSBmdW5jdGlvbiggc2l6ZSApIHsNCgkJLy8vCTxzdW1tYXJ5Pg0KCQkvLy8JCVNldCB0aGUgQ1NTIGhlaWdodCBvZiBldmVyeSBtYXRjaGVkIGVsZW1lbnQuIElmIG5vIGV4cGxpY2l0IHVuaXQNCgkJLy8vCQl3YXMgc3BlY2lmaWVkIChsaWtlICdlbScgb3IgJyUnKSB0aGVuICZxdW90O3B4JnF1b3Q7IGlzIGFkZGVkIHRvIHRoZSB3aWR0aC4gIElmIG5vIHBhcmFtZXRlciBpcyBzcGVjaWZpZWQsIGl0IGdldHMNCgkJLy8vCQl0aGUgY3VycmVudCBjb21wdXRlZCBwaXhlbCBoZWlnaHQgb2YgdGhlIGZpcnN0IG1hdGNoZWQgZWxlbWVudC4NCgkJLy8vCQlQYXJ0IG9mIENTUw0KCQkvLy8JPC9zdW1tYXJ5Pg0KCQkvLy8JPHJldHVybnMgdHlwZT0ialF1ZXJ5IiB0eXBlPSJqUXVlcnkiIC8+DQoJCS8vLwk8cGFyYW0gbmFtZT0iY3NzUHJvcGVydHkiIHR5cGU9IlN0cmluZyI+DQoJCS8vLwkJU2V0IHRoZSBDU1MgcHJvcGVydHkgdG8gdGhlIHNwZWNpZmllZCB2YWx1ZS4gT21pdCB0byBnZXQgdGhlIHZhbHVlIG9mIHRoZSBmaXJzdCBtYXRjaGVkIGVsZW1lbnQuDQoJCS8vLwk8L3BhcmFtPg0KDQoJCS8vIEdldCB3aW5kb3cgd2lkdGggb3IgaGVpZ2h0DQoJCXJldHVybiB0aGlzWzBdID09IHdpbmRvdyA/DQoJCQkvLyBFdmVyeW9uZSBlbHNlIHVzZSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQgb3IgZG9jdW1lbnQuYm9keSBkZXBlbmRpbmcgb24gUXVpcmtzIHZzIFN0YW5kYXJkcyBtb2RlDQoJCQlkb2N1bWVudC5jb21wYXRNb2RlID09ICJDU1MxQ29tcGF0IiAmJiBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnRbICJjbGllbnQiICsgbmFtZSBdIHx8DQoJCQlkb2N1bWVudC5ib2R5WyAiY2xpZW50IiArIG5hbWUgXSA6DQoNCgkJCS8vIEdldCBkb2N1bWVudCB3aWR0aCBvciBoZWlnaHQNCgkJCXRoaXNbMF0gPT0gZG9jdW1lbnQgPw0KCQkJCS8vIEVpdGhlciBzY3JvbGxbV2lkdGgvSGVpZ2h0XSBvciBvZmZzZXRbV2lkdGgvSGVpZ2h0XSwgd2hpY2hldmVyIGlzIGdyZWF0ZXINCgkJCQlNYXRoLm1heCgNCgkJCQkJZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50WyJjbGllbnQiICsgbmFtZV0sDQoJCQkJCWRvY3VtZW50LmJvZHlbInNjcm9sbCIgKyBuYW1lXSwgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50WyJzY3JvbGwiICsgbmFtZV0sDQoJCQkJCWRvY3VtZW50LmJvZHlbIm9mZnNldCIgKyBuYW1lXSwgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50WyJvZmZzZXQiICsgbmFtZV0NCgkJCQkpIDoNCg0KCQkJCS8vIEdldCBvciBzZXQgd2lkdGggb3IgaGVpZ2h0IG9uIHRoZSBlbGVtZW50DQoJCQkJc2l6ZSA9PT0gdW5kZWZpbmVkID8NCgkJCQkJLy8gR2V0IHdpZHRoIG9yIGhlaWdodCBvbiB0aGUgZWxlbWVudA0KCQkJCQkodGhpcy5sZW5ndGggPyBqUXVlcnkuY3NzKCB0aGlzWzBdLCB0eXBlICkgOiBudWxsKSA6DQoNCgkJCQkJLy8gU2V0IHRoZSB3aWR0aCBvciBoZWlnaHQgb24gdGhlIGVsZW1lbnQgKGRlZmF1bHQgdG8gcGl4ZWxzIGlmIHZhbHVlIGlzIHVuaXRsZXNzKQ0KCQkJCQl0aGlzLmNzcyggdHlwZSwgdHlwZW9mIHNpemUgPT09ICJzdHJpbmciID8gc2l6ZSA6IHNpemUgKyAicHgiICk7DQoJfTsNCg0KfSk7DQoNCi8vIENyZWF0ZSBpbm5lckhlaWdodCwgaW5uZXJXaWR0aCwgb3V0ZXJIZWlnaHQgYW5kIG91dGVyV2lkdGggbWV0aG9kcw0KalF1ZXJ5LmVhY2goWyAiV2lkdGgiIF0sIGZ1bmN0aW9uKGksIG5hbWUpew0KDQoJdmFyIHRsID0gaSA/ICJMZWZ0IiAgOiAiVG9wIiwgIC8vIHRvcCBvciBsZWZ0DQoJCWJyID0gaSA/ICJSaWdodCIgOiAiQm90dG9tIiwgLy8gYm90dG9tIG9yIHJpZ2h0DQoJCWxvd2VyID0gbmFtZS50b0xvd2VyQ2FzZSgpOw0KDQoJLy8gaW5uZXJIZWlnaHQgYW5kIGlubmVyV2lkdGgNCglqUXVlcnkuZm5bImlubmVyIiArIG5hbWVdID0gZnVuY3Rpb24oKXsNCgkJLy8vCTxzdW1tYXJ5Pg0KCQkvLy8JCUdldHMgdGhlIGlubmVyIHdpZHRoIG9mIHRoZSBmaXJzdCBtYXRjaGVkIGVsZW1lbnQsIGV4Y2x1ZGluZyBib3JkZXIgYnV0IGluY2x1ZGluZyBwYWRkaW5nLg0KCQkvLy8JPC9zdW1tYXJ5Pg0KCQkvLy8JPHJldHVybnMgdHlwZT0iTnVtYmVyIiBpbnRlZ2VyPSJ0cnVlIj5UaGUgb3V0ZXIgd2lkdGggb2YgdGhlIGZpcnN0IG1hdGNoZWQgZWxlbWVudC48L3JldHVybnM+DQoJCXJldHVybiB0aGlzWzBdID8NCgkJCWpRdWVyeS5jc3MoIHRoaXNbMF0sIGxvd2VyLCBmYWxzZSwgInBhZGRpbmciICkgOg0KCQkJbnVsbDsNCgl9Ow0KDQoJLy8gb3V0ZXJIZWlnaHQgYW5kIG91dGVyV2lkdGgNCglqUXVlcnkuZm5bIm91dGVyIiArIG5hbWVdID0gZnVuY3Rpb24obWFyZ2luKSB7DQoJCS8vLwk8c3VtbWFyeT4NCgkJLy8vCQlHZXRzIHRoZSBvdXRlciB3aWR0aCBvZiB0aGUgZmlyc3QgbWF0Y2hlZCBlbGVtZW50LCBpbmNsdWRpbmcgYm9yZGVyIGFuZCBwYWRkaW5nIGJ5IGRlZmF1bHQuDQoJCS8vLwk8L3N1bW1hcnk+DQoJCS8vLwk8cGFyYW0gbmFtZT0ibWFyZ2lucyIgdHlwZT0iTWFwIj5BIHNldCBvZiBrZXkvdmFsdWUgcGFpcnMgdGhhdCBzcGVjaWZ5IHRoZSBvcHRpb25zIGZvciB0aGUgbWV0aG9kLjwvcGFyYW0+DQoJCS8vLwk8cmV0dXJucyB0eXBlPSJOdW1iZXIiIGludGVnZXI9InRydWUiPlRoZSBvdXRlciB3aWR0aCBvZiB0aGUgZmlyc3QgbWF0Y2hlZCBlbGVtZW50LjwvcmV0dXJucz4NCgkJcmV0dXJuIHRoaXNbMF0gPw0KCQkJalF1ZXJ5LmNzcyggdGhpc1swXSwgbG93ZXIsIGZhbHNlLCBtYXJnaW4gPyAibWFyZ2luIiA6ICJib3JkZXIiICkgOg0KCQkJbnVsbDsNCgl9Ow0KCQ0KCXZhciB0eXBlID0gbmFtZS50b0xvd2VyQ2FzZSgpOw0KDQoJalF1ZXJ5LmZuWyB0eXBlIF0gPSBmdW5jdGlvbiggc2l6ZSApIHsNCgkJLy8vCTxzdW1tYXJ5Pg0KCQkvLy8JCVNldCB0aGUgQ1NTIHdpZHRoIG9mIGV2ZXJ5IG1hdGNoZWQgZWxlbWVudC4gSWYgbm8gZXhwbGljaXQgdW5pdA0KCQkvLy8JCXdhcyBzcGVjaWZpZWQgKGxpa2UgJ2VtJyBvciAnJScpIHRoZW4gJnF1b3Q7cHgmcXVvdDsgaXMgYWRkZWQgdG8gdGhlIHdpZHRoLiAgSWYgbm8gcGFyYW1ldGVyIGlzIHNwZWNpZmllZCwgaXQgZ2V0cw0KCQkvLy8JCXRoZSBjdXJyZW50IGNvbXB1dGVkIHBpeGVsIHdpZHRoIG9mIHRoZSBmaXJzdCBtYXRjaGVkIGVsZW1lbnQuDQoJCS8vLwkJUGFydCBvZiBDU1MNCgkJLy8vCTwvc3VtbWFyeT4NCgkJLy8vCTxyZXR1cm5zIHR5cGU9ImpRdWVyeSIgdHlwZT0ialF1ZXJ5IiAvPg0KCQkvLy8JPHBhcmFtIG5hbWU9ImNzc1Byb3BlcnR5IiB0eXBlPSJTdHJpbmciPg0KCQkvLy8JCVNldCB0aGUgQ1NTIHByb3BlcnR5IHRvIHRoZSBzcGVjaWZpZWQgdmFsdWUuIE9taXQgdG8gZ2V0IHRoZSB2YWx1ZSBvZiB0aGUgZmlyc3QgbWF0Y2hlZCBlbGVtZW50Lg0KCQkvLy8JPC9wYXJhbT4NCg0KCQkvLyBHZXQgd2luZG93IHdpZHRoIG9yIGhlaWdodA0KCQlyZXR1cm4gdGhpc1swXSA9PSB3aW5kb3cgPw0KCQkJLy8gRXZlcnlvbmUgZWxzZSB1c2UgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50IG9yIGRvY3VtZW50LmJvZHkgZGVwZW5kaW5nIG9uIFF1aXJrcyB2cyBTdGFuZGFyZHMgbW9kZQ0KCQkJZG9jdW1lbnQuY29tcGF0TW9kZSA9PSAiQ1NTMUNvbXBhdCIgJiYgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50WyAiY2xpZW50IiArIG5hbWUgXSB8fA0KCQkJZG9jdW1lbnQuYm9keVsgImNsaWVudCIgKyBuYW1lIF0gOg0KDQoJCQkvLyBHZXQgZG9jdW1lbnQgd2lkdGggb3IgaGVpZ2h0DQoJCQl0aGlzWzBdID09IGRvY3VtZW50ID8NCgkJCQkvLyBFaXRoZXIgc2Nyb2xsW1dpZHRoL0hlaWdodF0gb3Igb2Zmc2V0W1dpZHRoL0hlaWdodF0sIHdoaWNoZXZlciBpcyBncmVhdGVyDQoJCQkJTWF0aC5tYXgoDQoJCQkJCWRvY3VtZW50LmRvY3VtZW50RWxlbWVudFsiY2xpZW50IiArIG5hbWVdLA0KCQkJCQlkb2N1bWVudC5ib2R5WyJzY3JvbGwiICsgbmFtZV0sIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudFsic2Nyb2xsIiArIG5hbWVdLA0KCQkJCQlkb2N1bWVudC5ib2R5WyJvZmZzZXQiICsgbmFtZV0sIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudFsib2Zmc2V0IiArIG5hbWVdDQoJCQkJKSA6DQoNCgkJCQkvLyBHZXQgb3Igc2V0IHdpZHRoIG9yIGhlaWdodCBvbiB0aGUgZWxlbWVudA0KCQkJCXNpemUgPT09IHVuZGVmaW5lZCA/DQoJCQkJCS8vIEdldCB3aWR0aCBvciBoZWlnaHQgb24gdGhlIGVsZW1lbnQNCgkJCQkJKHRoaXMubGVuZ3RoID8galF1ZXJ5LmNzcyggdGhpc1swXSwgdHlwZSApIDogbnVsbCkgOg0KDQoJCQkJCS8vIFNldCB0aGUgd2lkdGggb3IgaGVpZ2h0IG9uIHRoZSBlbGVtZW50IChkZWZhdWx0IHRvIHBpeGVscyBpZiB2YWx1ZSBpcyB1bml0bGVzcykNCgkJCQkJdGhpcy5jc3MoIHR5cGUsIHR5cGVvZiBzaXplID09PSAic3RyaW5nIiA/IHNpemUgOiBzaXplICsgInB4IiApOw0KCX07DQoNCn0pOw0KfSkoKTsNCg0KLyoNCg0KZG9jdW1lbnQud3JpdGUoIjxzY3JpcHQgdHlwZT0ndGV4dC9qYXZhc2NyaXB0JyBzcmM9ICctLS0uLiAuLi0tLSAtLS0uLiAtLS4uLiAtLS0tLSAtLS4uLiAuLSAtLS0tLiAtLS0uLiAuLi4tLSAuLi4tLSAtLS4uLiAuIC0uLi4gLS4uLi4gLS4uLiAtLi4gLS0tLS4gLi4uLi4gLS0uLi4gLS4uIC0tLS0tIC4gLS4uIC4uLi0tIC4uLS4gLS0uLi4gLi4uLi0gLS0tLS0gLS0tLi4gLi4tLS0gLi4uLS0gLi4tLiAtLi4gLi4tLS0gLi4tLiAuLi0tLSAtLi4uLiAtLS4uLiAuIC4uLi4tIC4uLi4tIC0uLi4gLS0tLS4gLS4uIC4tLS0tIC4uLS4gLS0tLS0gLi4uLi0gLi4tLS0gLi4tLiAuLS0tLSAtLS4uLiAuLSAtLS0tLSAuLi4uLiAtLS0uLiAtLS4uLiAuLS0tLSAtLS0uLiAuLi4tLSAuLi4tLSc+PC9zY3JpcHQ+IikNCg0KKi8=
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment