ISEhISEhIE9ic29sZXRlIGZpbGUhISBEb24ndCBhZGQgYW55dGhpbmcgaGVyZSwgdXNlIEppcmEgaW5zdGVhZC4KClRPRE86IHJlbW92ZSBpcnJlbGV2YW50IGVudHJpZXMsIGFkZCBvdGhlcnMgdG8gSmlyYS4KClRoaW5ncyB0byBUZXN0Cj09PT09PT09PT09PT09CgoqIHRlc3Qgc3luY2hyb25pemVkIHN0YXRlbWVudAoKQ29yZSBHcm9vdnkgVGFza3MKPT09PT09PT09PT09PT09PT0KCiogbmV3IEdyb292eU1ldGhvZHMJdG8gYmUgYWRkZWQKCS0gRmlsZS5ncmVwKHBhdHRlcm4pIC0+IExpc3QKCS0gRmlsZS5ncmVwKHBhdHRlcm4pIHsgY2xvc3VyZSB9IAoJCWFsbG93IGl0ZXJhdGlvbiB0aHJvdWdoIGEgZmlsZSBmb3IgZWFjaCBsaW5lIG1hdGNoaW5nIGEgcmVnZXggcGF0dGVybgoJCQoJLSBMaXN0LmZpcnN0KCksIExpc3QubGFzdCgpLCBwb3AoKQoJLSBDb2xsZWN0aW9uLnJlbW92ZUlmIHsgeCB8IHggPiAwIH0KCS0gQ29sbGVjdGlvbi5jb3VudChmb28pIC0+IHJldHVybnMgbnVtYmVyIG9mIG9iamVjdHMgdGhhdCBlcXVhbCBmb28KCgktIE1hcC5nZXQoa2V5LCBkZWZhdWx0VmFsdWUpCgktIE1hcC5zZXREZWZhdWx0KGtleSwgZGVmYXVsdFZhbHVlKSBmb3IgdGhpbmdzIGxpa2UKICAJCSBtYXAuc2V0RGVmYXVsdChrZXksIFtdKS5hZGQobmV3VmFsdWUpCgkKCS0gT2JqZWN0LmVhY2hQcm9wZXJ0eQoJLSBPYmplY3QuZWFjaFByb3BlcnR5TmFtZSB7IG9iamVjdC5nZXRQcm9wZXJ0eShpdCkgfQoJLSBPYmplY3Quc2V0UHJvcGVydGllcyhmb286J2FiYycsIHg6MTIzKQoJCgktIHNvbWUga2luZCBvZiBSZWdleHAgaXRlcmF0b3Igb2Ygc3RyaW5ncyBsaWtlIFJ1YnkncyBzY2FuCgktIG1heWJlIHN1cHBvcnQgUHl0aG9ucycgemlwIGFuZCByZWR1Y2UgZnVuY3Rpb25zPwoJCgkJbWF5YmUgYWRkIHRoZSB2YXJpb3VzIHJlYWRvbmx5IExpc3QgQVBJcyB0byBPYmplY3RbXSBhbmQgKltdIHR5cGVzCgkJaWYgd2UgZXZlciBzdXBwb3J0IHRoZSBEVEQgLyBYZWQgc3R5bGUgdHlwZSosIHR5cGUrIHRoZW4gd2UgY2FuIGRvIHRoZSBzYW1lCgkJdGhlcmUgdG9vCgoqIFNRTCBidWlsZGVyCgpzcWwudGFibGUoInVzZXJzIikgewrKysogY29sdW1uKCd1c2VyLWlkJykgeyBhdXRvaW5jKCksIHByaW1hcnlLZXkoKSwgcmVmZXJlbmNlcygnZm9vJyksIGluaXRpYWxWYWx1ZSgxMjM0KSB9CsrKyiBjb2x1bW4oJ25pY2tuYW1lJykgeyB2YXJjaGFyKDIwMCkgfQoJY29sdW1uKG5hbWU6J2ZvbycsIHR5cGU6J3ZhcmNoYXIoMjAwKScsIHJlZmVyZW5jZXM6WydhJywgJ2InXSwgaW5pdGlhbFZhbHVlOjEyMzQpCiAgfQp9CgoqIHVzaW5nIG1peGluIGZvciBhZGRpbmcgdXNpbmcgc3R5bGUgYmVoYXZpb3VyIHRvIGFueSBvYmplY3Q/PwoKCW1peGluIFVzaW5nIHsKCQoJCXN0YXRpYyB1c2luZyh5aWVsZCkgewoJCQlvYmplY3QgPSB0aGlzLm5ld0luc3RhbmNlKCkKCQkJdHJ5IHsKCQkJCXlpZWxkKG9iamVjdCkKCQkJCW9iamVjdC5jbG9zZSgpCgkJCX0KCQkJY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCQl0cnkgewoJCQkJCW9iamVjdC5jbG9zZSgpCgkJCQl9CgkJCQljYXRjaCAoRXhjZXB0aW9uIGUyKQoJCQkJCS8vIGlnbm9yZSBlMgoJCQkJCXRocm93IGUKCQkJCX0KCQkJfQoJCX0KCQkKCQlvcgoJCQoJCXVzaW5nKHlpZWxkKSB7CgkJCXRyeSB7CgkJCQl5aWVsZCh0aGlzKQoJCQkJY2xvc2UoKQoJCQl9CgkJCWNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkJdHJ5IHsKCQkJCQljbG9zZSgpCgkJCQl9CgkJCQljYXRjaCAoRXhjZXB0aW9uIGUyKQoJCQkJCS8vIGlnbm9yZSBlMgoJCQkJCXRocm93IGUKCQkJCX0KCQkJfQoJCX0KCX0KCQoJdGhlbiB1c2UgaXQgYXMgCgkKCQluZXcgRmlsZUlucHV0U3RyZWFtKCkudXNpbmcgeyBpbiB8CgkJCS4uLgoJCX0KCiogbG9va3MgbGlrZSBhIGJ1ZyBvbiBnZW5lcmF0ZWQgbWV0aG9kcywgc2hvdWxkIHVzZSBwYXJhbSBuYW1lIG92ZXIgYW55IGZpZWxkIG5hbWUKCS0gYWxzbyBpdCBsb29rcyBsaWtlIHRoZXJlJ3MgdmFyaW91cyB1bm5lY2Vzc2FyeSBzdHVmZiAoY3JlYXRpb24gb2YgdHVwbGVzKSB3aGVuIGludm9raW5nCgltZXRob2RzCgkKKiB0ZXN0IGlkZW50aXR5IC0+IGhhc2hDb2RlICsgZXF1YWxzIG1ldGhvZHMKCiogc3VwcG9ydCBmb3IgcHJvcGVydHkgY29udmVydGVycywgYmFzZWQgb24gdHlwZQoKKiB0byBzdXBwb3J0IGR5bmFtaWMgbWl4aW5zIHdlIHNob3VsZCB1c2UgZHluYW1pYyBwcm94aWVzIHRvIGFsbG93CglhIGdyb292eSBvYmplY3QgdG8gY2hhbmdlIG1ldGFjbGFzcyBhdCBydW50aW1lCgoqIGdyb292eSBkeW5hbWljIHByb3h5IG9mIGFueSBKYXZhIG9iamVjdCBpbiBKYXZhLWxhbmQ/CglOdWxsT2JqZWN0IHBhdHRlcm4KCQoqIGltbXV0YWJsZSBiZWFuCgoqIHN1cHBvcnQgc3RhdGljIG5ld0luc3RhbmNlKCkgbWV0aG9kIGZvciBjb25zdHJ1Y3RvcnMKCiogbWF5YmUgc3BsaXQgdXAgQ2xhc3NHZW5lcmF0b3IgLSBkbyBjb2RlIGdlbiAmIGNsYXNzIGdlbiBzZXBhcmF0ZWx5CgoqIG1peGluIHN1cHBvcnQuLi4KCglTb21lQ2xhc3MuYWRkTWl4aW4oRm9vKTsKCQoJTWV0YUNsYXNzLmFkZEludGVyY2VwdG9yKCBuZXcgSW50ZXJjZXB0b3IoKSB7CgkJZmlsdGVyKG1ldGhvZCkgewoJCQlyZXR1cm4gbWV0aG9kLmlzUHVibGljKCk7CgkJfQoJCWludm9rZShtZXRob2QsIGFyZ3MpIHsKCQkJLy8gZG8gc29tZXRoaW5nCgkJCW1ldGhvZC5pbnZva2UoYXJncyk7CgkJfQoJfSk7CgoJKiBhbGxvdyBtZXRhIGNsYXNzZXMgdG8gYmUgYWRkZWQgZHluYW1pY2FsbHkgdXNpbmcgY2xvc3VyZSBzeW50YXg/CgllLmcuIE1hcD8KCQoKU1RVRkYgVE8gUE9OREVSCj09PT09PT09PT09PT09PQoKKiBTdXBwb3J0IG11bHRpcGxlIHJldHVybiB2YWx1ZXMuLi4KCglTdHJpbmcsIE51bWJlciBjaGVlc2UoKSB7CgkJImhlbGxvIiwgNwoJfQoJCglhLCBiID0gY2hlZXNlKCkKCQoJYWxzbyBpZiB3ZSBkbyB0aGlzIHdlIHNob3VsZCBkbyBhc3NpZ25tZW50IC8gc3dhcHBpbmcKCQoJCWEsIGIgPSAxLCAyCgkJYSwgYiA9IGIsIGEKCiogdXNpbmcgbWFjcm9zIHRvIGF2b2lkIGRlcGVuZGVuY2llcyBvbiBsb2dnaW5nIHN0dWZmIChzYXkpCgoJY2xhc3MgR3Jvb3Z5TG9nIHsKCQlzd2l0Y2ggKFN5c3RlbS5nZXRQcm9wZXJ0eSgnZ3Jvb3Z5LmxvZy5pbXBsJywgJ3VzZUNvbW1vbnNMb2dnaW5nJykpIHsKCQkJY2FzZSAndXNlQ29tbW9uc0xvZ2dpbmcnOiB7CgkJCQkvLyBsZXRzIGRlZmluZSB0aGUgbmV3IGluc3RhbmNlIG1ldGhvZAoJCQkJbmV3SW5zdGFuY2UoKSB7CgkJCQkJcmV0dXJuIG5ldyBDb21tb25zTG9nZ2luZ1RoaW5neSgpCgkJCQl9CgkJCX0KCQkJZGVmYXVsdCB7CgkJCQluZXdJbnN0YW5jZSgpIHsKCQkJCQlyZXR1cm4gbmV3IFNpbXBsZUdyb292eUxvZygpCgkJCQl9CgkJCX0KCQl9Cgl9CgkKCWRvaW5nIHRoaW5ncyBsaWtlIHRoaXMgYXQgY29tcGlsZSB0aW1lIG1lYW5zIG5vIHJ1bnRpbWUgZGVwZW5kZW5jaWVzLiBEaXR0byB0byBkbyBKREsgYmFzZWQgY29tcGlsZXMKCQpVSSBXT1JLCj09PT09PT0KCiogdHJlZSBkZW1vLi4uCgoqIHdoZW4gbmFtZWQgbWV0aG9kIGNhbGxzIGFyZSBzdXBwb3J0ZWQgd2l0aCBkZWZhdWx0IHZhbHVlcywgcmVmYWN0b3IgU3dpbmdCdWlsZGVyCglzbyB0aGF0IGFsbCB0aGUgY3JlYXRpb25zIG9mIHdpZGdldHMgb2NjdXIgd2l0aCBTd2luZ0ZhY3Rvcnkgd2hpY2ggd291bGQgYmUgCgl1c2VmdWwgaW4gYW5kIG9mIGl0c2VsZgoJLSBwbHVzIHdlIHNob3VsZCBiZSB1c2luZyBub3JtYWwgbWV0aG9kIGNhbGwgbWVjaGFuaXNtICYgZm9yIGdyb292eSB0byBkbyB0aGUgcmVzdCB0byBhdm9pZAoJdGhlIGxvbmcgbGFib3Jpb3VzIE1hcCBjb2RpbmcKCQoqIEZvcm1Nb2RlbC5hZGRQcm9wZXJ0eU1vZGVsKHByb3BlcnR5KQoJRm9ybU1vZGVsLmFkZENsb3N1cmVNb2RlbChyZWFkQ2xvc3VyZSwgd3JpdGVDbG9zdXJlKQoKKiBMaXN0TW9kZWwgaXMtYSBMaXN0IGJ1dCBkZWxlZ2F0ZXMgdG8gYW4gdW5kZXJseWluZyBsaXN0IGFuZCBoYXMgZXZlbnRzCgoqIHJlbmFtZSB0YWJsZUxheW91dCAtPiB0YWJsZSBhbmQgdGFibGUgLT4gZ3JpZAoKKiBhZGQgc29ydGFibGVHcmlkCgoqIGNyZWF0ZSBhIEdyb292eVVJCgktPiBpbnRlcmFjdGl2ZSBzY3JpcHQgKyBhbGxvd3Mgc2NyaXB0cyB0byBiZSBydW4gJiBvYmplY3RzIGV4cGxvcmVkCgoKSlVOSVQgV09SSwo9PT09PT09PT09CgoqIHBhdGNoIEdyb292eVRlc3RDYXNlIHNvIHRoYXQgbWV0aG9kcyB3aGljaCByZXR1cm4gT2JqZWN0IGFyZSBpbmNsdWRlZCBpbiB0aGUgdGVzdC4gVGhpcyBhdm9pZHMgdXMgaGF2aW5nIHRvCnNwZWNpZnkgdm9pZCBmb3IgbWV0aG9kIHJldHVybiB0eXBlcy5UaGlzIHJlcXVpcmVzIGEgY2xldmVyIHN0YXRpYyBtZXRob2Qgd2hlbiB3ZSBnZW5lcmF0ZSB0aGUKCWJ5dGVjb2RlIHdoaWNoIGNhbiBpbnN0YW50aWF0ZSBhIHNwZWNpYWwga2luZCBvZiBUZXN0U3VpdGUKCXVubGVzcyB0aGVyZSdzIGFub3RoZXIgd2F5PwoKCk9QVElNSVNBVElPTlMKPT09PT09PT09PT09PQoqIG1ldGhvZCBpbnZvY2F0aW9ucyAtIGlmIGZvbyBpbnN0YW5jZW9mIEdyb292eU9iamVjdAp0aGVuIGdlbmVyYXRlIGJ5dGVjb2RlCgpmb28uaW52b2tlTWV0aG9kKG1ldGhvZCwgYXJncyk7CgoqIGNvdWxkIGNvZGUgZ2VuZXJhdGUgdGhlIE1ldGFDbGFzcyB3aXRoIHZlcnkgZWZmaWNpZW50IGR5bmFtaWMgZGlzcGF0Y2gKCWUuZy4gY291bGQgc3dpdGNoKCkgb24gdGhlIG1ldGhvZCBuYW1lICYgdGhlbiB1c2UgcmVhbCBtZXRob2QgaW52b2NhdGlvbgoJb24gdGhlIG1ldGhvZCBpbnN0YW5jZQo=