LyoKICogVHJlZXZpZXcgMS4yIC0galF1ZXJ5IHBsdWdpbiB0byBoaWRlIGFuZCBzaG93IGJyYW5jaGVzIG9mIGEgdHJlZQogKgogKiBDb3B5cmlnaHQgKGMpIDIwMDYgSvZybiBaYWVmZmVyZXIsIE15bGVzIEFuZ2VsbAogKgogKiBEdWFsIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgYW5kIEdQTCBsaWNlbnNlczoKICogICBodHRwOi8vd3d3Lm9wZW5zb3VyY2Uub3JnL2xpY2Vuc2VzL21pdC1saWNlbnNlLnBocAogKiAgIGh0dHA6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy9ncGwuaHRtbAogKgogKiBSZXZpc2lvbjogJElkJAogKgogKi8KCi8qKgogKiBUYWtlcyBhbiB1bm9yZGVyZWQgbGlzdCBhbmQgbWFrZXMgYWxsIGJyYW5jaGVzIGNvbGxhcHNhYmxlLgogKgogKiBUaGUgInRyZWV2aWV3IiBjbGFzcyBpcyBhZGRlZCBpZiBub3QgYWxyZWFkeSBwcmVzZW50LgogKgogKiBUbyBoaWRlIGJyYW5jaGVzIG9uIGZpcnN0IGRpc3BsYXksIG1hcmsgdGhlaXIgbGkgZWxlbWVudHMgd2l0aAogKiB0aGUgY2xhc3MgImNsb3NlZCIuIElmIHRoZSAiY29sbGFwc2VkIiBvcHRpb24gaXMgdXNlZCwgbWFyayBpbnRpYWxseSBvcGVuCiAqIGJyYW5jaGVzIHdpdGggY2xhc3MgIm9wZW4iLgogKgogKiBAZXhhbXBsZSAudHJlZXZpZXcsIC50cmVldmlldyB1bCB7IAogKiAJcGFkZGluZzogMDsKICogCW1hcmdpbjogMDsKICogCWxpc3Qtc3R5bGU6IG5vbmU7CiAqIH0JCiAqIAogKiAudHJlZXZpZXcgbGkgeyAKICogCW1hcmdpbjogMDsKICogCXBhZGRpbmc6IDRweCAwIDNweCAyMHB4OwogKiB9CiAqIAogKiAudHJlZXZpZXcgbGkgeyBiYWNrZ3JvdW5kOiB1cmwoaW1hZ2VzL3R2LWl0ZW0uZ2lmKSAwIDAgbm8tcmVwZWF0OyB9CiAqIC50cmVldmlldyAuY29sbGFwc2FibGUgeyBiYWNrZ3JvdW5kLWltYWdlOiB1cmwoaW1hZ2VzL3R2LWNvbGxhcHNhYmxlLmdpZik7IH0KICogLnRyZWV2aWV3IC5leHBhbmRhYmxlIHsgYmFja2dyb3VuZC1pbWFnZTogdXJsKGltYWdlcy90di1leHBhbmRhYmxlLmdpZik7IH0KICogLnRyZWV2aWV3IC5sYXN0IHsgYmFja2dyb3VuZC1pbWFnZTogdXJsKGltYWdlcy90di1pdGVtLWxhc3QuZ2lmKTsgfQogKiAudHJlZXZpZXcgLmxhc3RDb2xsYXBzYWJsZSB7IGJhY2tncm91bmQtaW1hZ2U6IHVybChpbWFnZXMvdHYtY29sbGFwc2FibGUtbGFzdC5naWYpOyB9CiAqIC50cmVldmlldyAubGFzdEV4cGFuZGFibGUgeyBiYWNrZ3JvdW5kLWltYWdlOiB1cmwoaW1hZ2VzL3R2LWV4cGFuZGFibGUtbGFzdC5naWYpOyB9CiAqIEBkZXNjIFRoZSBmb2xsb3dpbmcgc3R5bGVzIGFyZSBuZWNlc3NhcnkgaW4geW91ciBzdHlsZXNoZWV0LiBUaGVyZSBpcyBhcmUgYWx0ZXJuYXRpdmUgc2V0cyBvZiBpbWFnZXMgYXZhaWxhYmxlLgogKgogKiBAZXhhbXBsZSAkKCJ1bCIpLlRyZWV2aWV3KCk7CiAqIEBiZWZvcmUgPHVsPgogKiAgIDxsaT5JdGVtIDEKICogICAgIDx1bD4KICogICAgICAgPGxpPkl0ZW0gMS4xPC9saT4KICogICAgIDwvdWw+CiAqICAgPC9saT4KICogICA8bGkgY2xhc3M9ImNsb3NlZCI+SXRlbSAyIChzdGFydHMgY2xvc2VkKQogKiAgICAgPHVsPgogKiAgICAgICA8bGk+SXRlbSAyLjEKICogICAgICAgICA8dWw+CiAqICAgICAgICAgICA8bGk+SXRlbSAyLjEuMTwvbGk+CiAqICAgICAgICAgICA8bGk+SXRlbSAyLjEuMjwvbGk+CiAqICAgICAgICAgPC91bD4KICogICAgICAgPC9saT4KICogICAgICAgPGxpPkl0ZW0gMi4yPC9saT4KICogICAgIDwvdWw+CiAqICAgPC9saT4KICogICA8bGk+SXRlbSAzPC9saT4KICogPC91bD4KICogQGRlc2MgQmFzaWMgdXNhZ2UgZXhhbXBsZQogKgogKiBAZXhhbXBsZSAkKCJ1bCIpLlRyZWV2aWV3KHsgc3BlZWQ6ICJmYXN0IiwgY29sbGFwc2VkOiB0cnVlfSk7CiAqIEBiZWZvcmUgPHVsPgogKiAgIDxsaSBjbGFzcz0ib3BlbiI+SXRlbSAxIChzdGFydHMgb3BlbikKICogICAgIDx1bD4KICogICAgICAgPGxpPkl0ZW0gMS4xPC9saT4KICogICAgIDwvdWw+CiAqICAgPC9saT4KICogICA8bGk+SXRlbSAyCiAqICAgICA8dWw+CiAqICAgICAgIDxsaT5JdGVtIDIuMTwvbGk+CiAqICAgICAgIDxsaT5JdGVtIDIuMjwvbGk+CiAqICAgICA8L3VsPgogKiAgIDwvbGk+CiAqIDwvdWw+CiAqIEBkZXNjIENyZWF0ZSBhIHRyZWV2aWV3IHRoYXQgc3RhcnRzIGNvbGxhcHNlZC4gVG9nZ2xpbmcgYnJhbmNoZXMgaXMgYW5pbWF0ZWQuCiAqCiAqIEBleGFtcGxlICQoInVsIikuVHJlZXZpZXcoeyBjb250cm9sOiAjdHJlZWNvbnRyb2wgfSk7CiAqIEBiZWZvcmUgPGRpdiBpZD0idHJlZWNvbnRyb2wiPgogKiAgIDxhIGhyZWY9IiMiPkNvbGxhcHNlIEFsbDwvYT4KICogICA8YSBocmVmPSIjIj5FeHBhbmQgQWxsPC9hPgogKiAgIDxhIGhyZWY9IiMiPlRvZ2dsZSBBbGw8L2E+CiAqIDwvZGl2PgogKiBAZGVzYyBDcmVhdGVzIGEgdHJlZXZpZXcgdGhhdCBjYW4gYmUgY29udHJvbGxlZCB3aXRoIGEgZmV3IGxpbmtzLgogKiBWZXJ5IGxpa2VseSB0byBiZSBjaGFuZ2VkL2ltcHJvdmVkIGluIGZ1dHVyZSB2ZXJzaW9ucy4KICoKICogQHBhcmFtIE1hcCBvcHRpb25zIE9wdGlvbmFsIHNldHRpbmdzIHRvIGNvbmZpZ3VyZSB0cmVldmlldwogKiBAb3B0aW9uIFN0cmluZ3xOdW1iZXIgc3BlZWQgU3BlZWQgb2YgYW5pbWF0aW9uLCBzZWUgYW5pbWF0ZSgpIGZvciBkZXRhaWxzLiBEZWZhdWx0OiBub25lLCBubyBhbmltYXRpb24KICogQG9wdGlvbiBCb29sZWFuIGNvbGxhcHNlZCBTdGFydCB3aXRoIGFsbCBicmFuY2hlcyBjb2xsYXBzZWQuIERlZmF1bHQ6IG5vbmUsIGFsbCBleHBhbmRlZAogKiBAb3B0aW9uIDxDb250ZW50PiBjb250cm9sIENvbnRhaW5lciBmb3IgYSB0cmVlY29udHJvbCwgc2VlIGxhc3QgZXhhbXBsZS4KICogQG9wdGlvbiBCb29sZWFuIHVuaXF1ZSBTZXQgdG8gYWxsb3cgb25seSBvbmUgYnJhbmNoIG9uIG9uZSBsZXZlbCB0byBiZSBvcGVuCiAqCQkgICAoY2xvc2luZyBzaWJsaW5ncyB3aGljaCBvcGVuaW5nKS4gRGVmYXVsdDogbm9uZQogKiBAb3B0aW9uIEZ1bmN0aW9uIHRvZ2dsZSBDYWxsYmFjayB3aGVuIHRvZ2dsaW5nIGEgYnJhbmNoLgogKiAJCSAgIEFyZ3VtZW50czogInRoaXMiIHJlZmVycyB0byB0aGUgVUwgdGhhdCB3YXMgc2hvd24gb3IgaGlkZGVuLgogKiAJCSAgIFdvcmtzIG9ubHkgd2l0aCBzcGVlZCBvcHRpb24gc2V0IChzZXQgc3BlZWQ6IDEgdG8gZW5hYmxlIGNhbGxiYWNrIHdpdGhvdXQgYW5pbWF0aW9ucykuCiAqCQkgICBEZWZhdWx0OiBub25lCiAqIEB0eXBlIGpRdWVyeQogKiBAbmFtZSBUcmVldmlldwogKiBAY2F0IFBsdWdpbnMvVHJlZXZpZXcKICovCgooZnVuY3Rpb24oJCkgewoKCS8vIGNsYXNzZXMgdXNlZCBieSB0aGUgcGx1Z2luCgkvLyBuZWVkIHRvIGJlIHN0eWxlZCB2aWEgZXh0ZXJuYWwgc3R5bGVzaGVldCwgc2VlIGZpcnN0IGV4YW1wbGUKCXZhciBDTEFTU0VTID0gewoJCW9wZW46ICJvcGVuIiwKCQljbG9zZWQ6ICJjbG9zZWQiLAoJCWV4cGFuZGFibGU6ICJleHBhbmRhYmxlIiwKCQljb2xsYXBzYWJsZTogImNvbGxhcHNhYmxlIiwKCQlsYXN0Q29sbGFwc2FibGU6ICJsYXN0Q29sbGFwc2FibGUiLAoJCWxhc3RFeHBhbmRhYmxlOiAibGFzdEV4cGFuZGFibGUiLAoJCWxhc3Q6ICJsYXN0IiwKCQloaXRhcmVhOiAiaGl0YXJlYSIKCX07CgkKCS8vIHN0eWxlcyBmb3IgaGl0YXJlYXMKCXZhciBoaXRhcmVhQ1NTID0gewoJCWhlaWdodDogMTUsCgkJd2lkdGg6IDMwLCAvLyBjdXN0b20gc2l6ZSB1c2VkIGluIHhvb2tpCgkJbWFyZ2luTGVmdDogIi0zMHB4IiwgLy8gY3VzdG9tIHNpemUgdXNlZCBpbiB4b29raQoJCSJmbG9hdCI6ICJsZWZ0IiwKCQljdXJzb3I6ICJwb2ludGVyIgoJfTsKCQoJLy8gaWUgc3BlY2lmaWMgc3R5bGVzIGZvciBoaXRhcmVhcwoJaWYoICQuYnJvd3Nlci5tc2llICkgewoJCSQuZXh0ZW5kKCBoaXRhcmVhQ1NTLCB7CgkJCWJhY2tncm91bmQ6ICIjZmZmIiwKCQkJZmlsdGVyOiAiYWxwaGEob3BhY2l0eT0wKSIsCgkJCWRpc3BsYXk6ICJpbmxpbmUiCgkJfSk7Cgl9CgoJJC5leHRlbmQoJC5mbiwgewoJCXN3YXBDbGFzczogZnVuY3Rpb24oYzEsIGMyKSB7CgkJCXJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24oKSB7CgkJCQl2YXIgJHRoaXMgPSAkKHRoaXMpOwoJCQkJaWYgKCAkLmNsYXNzTmFtZS5oYXModGhpcywgYzEpICkKCQkJCQkkdGhpcy5yZW1vdmVDbGFzcyhjMSkuYWRkQ2xhc3MoYzIpOwoJCQkJZWxzZSBpZiAoICQuY2xhc3NOYW1lLmhhcyh0aGlzLCBjMikgKQoJCQkJCSR0aGlzLnJlbW92ZUNsYXNzKGMyKS5hZGRDbGFzcyhjMSk7CgkJCX0pOwoJCX0sCgkJcmVwbGFjZWNsYXNzOiBmdW5jdGlvbihjMSwgYzIpIHsKCQkJcmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbigpIHsKCQkJCXZhciAkdGhpcyA9ICQodGhpcyk7CgkJCQlpZiAoICQuY2xhc3NOYW1lLmhhcyh0aGlzLCBjMSkgKQoJCQkJCSR0aGlzLnJlbW92ZUNsYXNzKGMxKS5hZGRDbGFzcyhjMik7CgkJCX0pOwoJCX0sCgkJVHJlZXZpZXc6IGZ1bmN0aW9uKHNldHRpbmdzKSB7CgkJCgkJCS8vIGN1cnJlbnRseSBubyBkZWZhdWx0cyBuZWNlc3NhcnksIGFsbCBpbXBsaWNpdAoJCQlzZXR0aW5ncyA9ICQuZXh0ZW5kKHt9LCBzZXR0aW5ncyk7CgkJCgkJCS8vIGZhY3RvcnkgZm9yIHRyZWVjb250cm9sbGVyCgkJCWZ1bmN0aW9uIHRyZWVDb250cm9sbGVyKHRyZWUsIGNvbnRyb2wpIHsKCQkJCS8vIGZhY3RvcnkgZm9yIGNsaWNrIGhhbmRsZXJzCgkJCQlmdW5jdGlvbiBoYW5kbGVyKGZpbHRlcikgewoJCQkJCXJldHVybiBmdW5jdGlvbigpIHsKCQkJCQkJLy8gcmV1c2UgdG9nZ2xlIGV2ZW50IGhhbmRsZXIsIGFwcGx5aW5nIHRoZSBlbGVtZW50cyB0byB0b2dnbGUKCQkJCQkJLy8gc3RhcnQgc2VhcmNoaW5nIGZvciBhbGwgaGl0YXJlYXMKCQkJCQkJdG9nZ2xlci5hcHBseSggJCgiZGl2LiIgKyBDTEFTU0VTLmhpdGFyZWEsIHRyZWUpLmZpbHRlcihmdW5jdGlvbigpIHsKCQkJCQkJCS8vIGZvciBwbGFpbiB0b2dnbGUsIG5vIGZpbHRlciBpcyBwcm92aWRlZCwgb3RoZXJ3aXNlIHdlIG5lZWQgdG8gY2hlY2sgdGhlIHBhcmVudCBlbGVtZW50CgkJCQkJCQlyZXR1cm4gZmlsdGVyID8gJCh0aGlzKS5wYXJlbnQoIi4iICsgZmlsdGVyKS5sZW5ndGggOiB0cnVlOwoJCQkJCQl9KSApOwoJCQkJCQlyZXR1cm4gZmFsc2U7CgkJCQkJfQoJCQkJfQoJCQkJLy8gY2xpY2sgb24gZmlyc3QgZWxlbWVudCB0byBjb2xsYXBzZSB0cmVlCgkJCQkkKCI6ZXEoMCkiLCBjb250cm9sKS5jbGljayggaGFuZGxlcihDTEFTU0VTLmNvbGxhcHNhYmxlKSApOwoJCQkJLy8gY2xpY2sgb24gc2Vjb25kIHRvIGV4cGFuZCB0cmVlCgkJCQkkKCI6ZXEoMSkiLCBjb250cm9sKS5jbGljayggaGFuZGxlcihDTEFTU0VTLmV4cGFuZGFibGUpICk7CgkJCQkvLyBjbGljayBvbiB0aGlyZCB0byB0b2dnbGUgdHJlZQoJCQkJJCgiOmVxKDIpIiwgY29udHJvbCkuY2xpY2soIGhhbmRsZXIoKSApOyAKCQkJfQoJCQoJCQkvLyBoYW5kbGUgdG9nZ2xlIGV2ZW50CgkJCWZ1bmN0aW9uIHRvZ2dsZXIoKSB7CgkJCQkvLyB0aGlzIHJlZmVycyB0byBoaXRhcmVhcywgd2UgbmVlZCB0byBmaW5kIHRoZSBwYXJlbnQgbGlzIGZpcnN0CgkJCQkkKCB0aGlzICkucGFyZW50KCkKCQkJCQkvLyBzd2FwIGNsYXNzZXMKCQkJCQkuc3dhcENsYXNzKCBDTEFTU0VTLmNvbGxhcHNhYmxlLCBDTEFTU0VTLmV4cGFuZGFibGUgKQoJCQkJCS5zd2FwQ2xhc3MoIENMQVNTRVMubGFzdENvbGxhcHNhYmxlLCBDTEFTU0VTLmxhc3RFeHBhbmRhYmxlICkKCQkJCQkvLyBmaW5kIGNoaWxkIGxpc3RzCgkJCQkJLmZpbmQoICI+dWwiICkKCQkJCQkvLyB0b2dnbGUgdGhlbQoJCQkJCS50b2dnbGUoIHNldHRpbmdzLnNwZWVkLCBzZXR0aW5ncy50b2dnbGUgKTsKCQkJCWlmICggc2V0dGluZ3MudW5pcXVlICkgewoJCQkJCSQoIHRoaXMgKS5wYXJlbnQoKQoJCQkJCQkuc2libGluZ3MoKQoJCQkJCQkucmVwbGFjZWNsYXNzKCBDTEFTU0VTLmNvbGxhcHNhYmxlLCBDTEFTU0VTLmV4cGFuZGFibGUgKQoJCQkJCQkucmVwbGFjZWNsYXNzKCBDTEFTU0VTLmxhc3RDb2xsYXBzYWJsZSwgQ0xBU1NFUy5sYXN0RXhwYW5kYWJsZSApCgkJCQkJCS5maW5kKCAiPnVsIiApCgkJCQkJCS5oaWRlKCBzZXR0aW5ncy5zcGVlZCwgc2V0dGluZ3MudG9nZ2xlICk7CgkJCQl9CgkJCX0KCQoJCQkvLyBhZGQgdHJlZXZpZXcgY2xhc3MgdG8gYWN0aXZhdGUgc3R5bGVzCgkJCXRoaXMuYWRkQ2xhc3MoInRyZWV2aWV3Iik7CgkJCQoJCQkvLyBtYXJrIGxhc3QgdHJlZSBpdGVtcwoJCQkkKCJsaTpsYXN0LWNoaWxkIiwgdGhpcykuYWRkQ2xhc3MoQ0xBU1NFUy5sYXN0KTsKCQkJCgkJCS8vIGNvbGxhcHNlIHdob2xlIHRyZWUsIG9yIG9ubHkgdGhvc2UgbWFya2VkIGFzIGNsb3NlZCwgYW55d2F5IGV4Y2VwdCB0aG9zZSBtYXJrZWQgYXMgb3BlbgoJCQkkKCAoc2V0dGluZ3MuY29sbGFwc2VkID8gImxpIiA6ICJsaS4iICsgQ0xBU1NFUy5jbG9zZWQpICsgIjpub3QoLiIgKyBDTEFTU0VTLm9wZW4gKyAiKSA+IHVsIiwgdGhpcykuaGlkZSgpOwoJCQkKCQkJLy8gZmluZCBhbGwgdHJlZSBpdGVtcyB3aXRoIGNoaWxkIGxpc3RzCgkJCSQoImxpW3VsXSIsIHRoaXMpCgkJCQkvLyBoYW5kbGUgY2xvc2VkIG9uZXMgZmlyc3QKCQkJCS5maWx0ZXIoIls+dWw6aGlkZGVuXSIpCgkJCQkJLmFkZENsYXNzKENMQVNTRVMuZXhwYW5kYWJsZSkKCQkJCQkuc3dhcENsYXNzKENMQVNTRVMubGFzdCwgQ0xBU1NFUy5sYXN0RXhwYW5kYWJsZSkKCQkJCQkuZW5kKCkKCQkJCS8vIGhhbmRsZSBvcGVuIG9uZXMKCQkJCS5ub3QoIls+dWw6aGlkZGVuXSIpCgkJCQkJLmFkZENsYXNzKENMQVNTRVMuY29sbGFwc2FibGUpCgkJCQkJLnN3YXBDbGFzcyhDTEFTU0VTLmxhc3QsIENMQVNTRVMubGFzdENvbGxhcHNhYmxlKQoJCQkJCS5lbmQoKQoJCQkJLy8gYXBwZW5kIGhpdGFyZWEKCQkJCS5wcmVwZW5kKCI8ZGl2IGNsYXNzPVwiIiArIENMQVNTRVMuaGl0YXJlYSArICJcIj4iKQoJCQkJLy8gZmluZCBoaXRhcmVhCgkJCQkuZmluZCgiZGl2LiIgKyBDTEFTU0VTLmhpdGFyZWEpCgkJCQkvLyBhcHBseSBzdHlsZXMgdG8gaGl0YXJlYQoJCQkJLmNzcyhoaXRhcmVhQ1NTKQoJCQkJLy8gYXBwbHkgdG9nZ2xlIGV2ZW50IHRvIGhpdGFyZWEKCQkJCS50b2dnbGUoIHRvZ2dsZXIsIHRvZ2dsZXIgKTsKCQkJCgkJCS8vIGlmIGNvbnRyb2wgb3B0aW9uIGlzIHNldCwgY3JlYXRlIHRoZSB0cmVlY29udHJvbGxlcgoJCQlpZiAoIHNldHRpbmdzLmNvbnRyb2wgKQoJCQkJdHJlZUNvbnRyb2xsZXIodGhpcywgc2V0dGluZ3MuY29udHJvbCk7CgkJCQoJCQlyZXR1cm4gdGhpczsKCQl9Cgl9KTsKfSkoalF1ZXJ5KTs=