LyoKICogVGhlIEFwYWNoZSBTb2Z0d2FyZSBMaWNlbnNlLCBWZXJzaW9uIDEuMQogKgogKgogKiBDb3B5cmlnaHQgKGMpIDE5OTkgVGhlIEFwYWNoZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLiAgQWxsIHJpZ2h0cyAKICogcmVzZXJ2ZWQuCiAqCiAqIFJlZGlzdHJpYnV0aW9uIGFuZCB1c2UgaW4gc291cmNlIGFuZCBiaW5hcnkgZm9ybXMsIHdpdGggb3Igd2l0aG91dAogKiBtb2RpZmljYXRpb24sIGFyZSBwZXJtaXR0ZWQgcHJvdmlkZWQgdGhhdCB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnMKICogYXJlIG1ldDoKICoKICogMS4gUmVkaXN0cmlidXRpb25zIG9mIHNvdXJjZSBjb2RlIG11c3QgcmV0YWluIHRoZSBhYm92ZSBjb3B5cmlnaHQKICogICAgbm90aWNlLCB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyLiAKICoKICogMi4gUmVkaXN0cmlidXRpb25zIGluIGJpbmFyeSBmb3JtIG11c3QgcmVwcm9kdWNlIHRoZSBhYm92ZSBjb3B5cmlnaHQKICogICAgbm90aWNlLCB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyIGluCiAqICAgIHRoZSBkb2N1bWVudGF0aW9uIGFuZC9vciBvdGhlciBtYXRlcmlhbHMgcHJvdmlkZWQgd2l0aCB0aGUKICogICAgZGlzdHJpYnV0aW9uLgogKgogKiAzLiBUaGUgZW5kLXVzZXIgZG9jdW1lbnRhdGlvbiBpbmNsdWRlZCB3aXRoIHRoZSByZWRpc3RyaWJ1dGlvbiwKICogICAgaWYgYW55LCBtdXN0IGluY2x1ZGUgdGhlIGZvbGxvd2luZyBhY2tub3dsZWRnbWVudDogIAogKiAgICAgICAiVGhpcyBwcm9kdWN0IGluY2x1ZGVzIHNvZnR3YXJlIGRldmVsb3BlZCBieSB0aGUKICogICAgICAgIEFwYWNoZSBTb2Z0d2FyZSBGb3VuZGF0aW9uIChodHRwOi8vd3d3LmFwYWNoZS5vcmcvKS4iCiAqICAgIEFsdGVybmF0ZWx5LCB0aGlzIGFja25vd2xlZGdtZW50IG1heSBhcHBlYXIgaW4gdGhlIHNvZnR3YXJlIGl0c2VsZiwKICogICAgaWYgYW5kIHdoZXJldmVyIHN1Y2ggdGhpcmQtcGFydHkgYWNrbm93bGVkZ21lbnRzIG5vcm1hbGx5IGFwcGVhci4KICoKICogNC4gVGhlIG5hbWVzICJYYWxhbiIgYW5kICJBcGFjaGUgU29mdHdhcmUgRm91bmRhdGlvbiIgbXVzdAogKiAgICBub3QgYmUgdXNlZCB0byBlbmRvcnNlIG9yIHByb21vdGUgcHJvZHVjdHMgZGVyaXZlZCBmcm9tIHRoaXMKICogICAgc29mdHdhcmUgd2l0aG91dCBwcmlvciB3cml0dGVuIHBlcm1pc3Npb24uIEZvciB3cml0dGVuIAogKiAgICBwZXJtaXNzaW9uLCBwbGVhc2UgY29udGFjdCBhcGFjaGVAYXBhY2hlLm9yZy4KICoKICogNS4gUHJvZHVjdHMgZGVyaXZlZCBmcm9tIHRoaXMgc29mdHdhcmUgbWF5IG5vdCBiZSBjYWxsZWQgIkFwYWNoZSIsCiAqICAgIG5vciBtYXkgIkFwYWNoZSIgYXBwZWFyIGluIHRoZWlyIG5hbWUsIHdpdGhvdXQgcHJpb3Igd3JpdHRlbgogKiAgICBwZXJtaXNzaW9uIG9mIHRoZSBBcGFjaGUgU29mdHdhcmUgRm91bmRhdGlvbi4KICoKICogVEhJUyBTT0ZUV0FSRSBJUyBQUk9WSURFRCBgYEFTIElTJycgQU5EIEFOWSBFWFBSRVNTRUQgT1IgSU1QTElFRAogKiBXQVJSQU5USUVTLCBJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgVEhFIElNUExJRUQgV0FSUkFOVElFUwogKiBPRiBNRVJDSEFOVEFCSUxJVFkgQU5EIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFSRQogKiBESVNDTEFJTUVELiAgSU4gTk8gRVZFTlQgU0hBTEwgVEhFIEFQQUNIRSBTT0ZUV0FSRSBGT1VOREFUSU9OIE9SCiAqIElUUyBDT05UUklCVVRPUlMgQkUgTElBQkxFIEZPUiBBTlkgRElSRUNULCBJTkRJUkVDVCwgSU5DSURFTlRBTCwKICogU1BFQ0lBTCwgRVhFTVBMQVJZLCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVMgKElOQ0xVRElORywgQlVUIE5PVAogKiBMSU1JVEVEIFRPLCBQUk9DVVJFTUVOVCBPRiBTVUJTVElUVVRFIEdPT0RTIE9SIFNFUlZJQ0VTOyBMT1NTIE9GCiAqIFVTRSwgREFUQSwgT1IgUFJPRklUUzsgT1IgQlVTSU5FU1MgSU5URVJSVVBUSU9OKSBIT1dFVkVSIENBVVNFRCBBTkQKICogT04gQU5ZIFRIRU9SWSBPRiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQ09OVFJBQ1QsIFNUUklDVCBMSUFCSUxJVFksCiAqIE9SIFRPUlQgKElOQ0xVRElORyBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSkgQVJJU0lORyBJTiBBTlkgV0FZIE9VVAogKiBPRiBUSEUgVVNFIE9GIFRISVMgU09GVFdBUkUsIEVWRU4gSUYgQURWSVNFRCBPRiBUSEUgUE9TU0lCSUxJVFkgT0YKICogU1VDSCBEQU1BR0UuCiAqID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CiAqCiAqIFRoaXMgc29mdHdhcmUgY29uc2lzdHMgb2Ygdm9sdW50YXJ5IGNvbnRyaWJ1dGlvbnMgbWFkZSBieSBtYW55CiAqIGluZGl2aWR1YWxzIG9uIGJlaGFsZiBvZiB0aGUgQXBhY2hlIFNvZnR3YXJlIEZvdW5kYXRpb24gYW5kIHdhcwogKiBvcmlnaW5hbGx5IGJhc2VkIG9uIHNvZnR3YXJlIGNvcHlyaWdodCAoYykgMTk5OSwgTG90dXMKICogRGV2ZWxvcG1lbnQgQ29ycG9yYXRpb24uLCBodHRwOi8vd3d3LmxvdHVzLmNvbS4gIEZvciBtb3JlCiAqIGluZm9ybWF0aW9uIG9uIHRoZSBBcGFjaGUgU29mdHdhcmUgRm91bmRhdGlvbiwgcGxlYXNlIHNlZQogKiA8aHR0cDovL3d3dy5hcGFjaGUub3JnLz4uCiAqLwpwYWNrYWdlIG9yZy5hcGFjaGUueG1sLnV0aWxzOwoKaW1wb3J0IGphdmEudXRpbC5Mb2NhbGU7CgovKioKICogVGhpcyBjbGFzcyBpcyBtZWFudCB0byBiZSBhbiBpbnRlcmZhY2UgdG8gY2hhcmFjdGVyIHN0cmluZ3MsIHdoZXRoZXIgdGhleQogKiBiZSBqYXZhIFN0cmluZ3Mgb3IgPGNvZGU+b3JnLmFwYWNoZS54bWwudXRpbHMuRmFzdFN0cmluZ0J1ZmZlcjwvY29kZT5zLCBvcgogKiBvdGhlciBjaGFyYWN0ZXIgZGF0YS4gIEJ5IHVzaW5nIFhNTFN0cmluZywgY2hhcmFjdGVyIGNvcGllcyBjYW4gYmUgcmVkdWNlZAogKiBpbiB0aGUgWE1MIHBpcGVsaW5lLgogKi8KcHVibGljIGludGVyZmFjZSBYTUxTdHJpbmcKewoKICAvKioKICAgKiBEaXJlY3RseSBjYWxsIHRoZQogICAqIGNoYXJhY3RlcnMgbWV0aG9kIG9uIHRoZSBwYXNzZWQgQ29udGVudEhhbmRsZXIgZm9yIHRoZQogICAqIHN0cmluZy12YWx1ZS4gTXVsdGlwbGUgY2FsbHMgdG8gdGhlCiAgICogQ29udGVudEhhbmRsZXIncyBjaGFyYWN0ZXJzIG1ldGhvZHMgbWF5IHdlbGwgb2NjdXIgZm9yIGEgc2luZ2xlIGNhbGwgdG8KICAgKiB0aGlzIG1ldGhvZC4KICAgKgogICAqIEBwYXJhbSBjaCBBIG5vbi1udWxsIHJlZmVyZW5jZSB0byBhIENvbnRlbnRIYW5kbGVyLgogICAqCiAgICogQHRocm93cyBvcmcueG1sLnNheC5TQVhFeGNlcHRpb24KICAgKi8KICBwdWJsaWMgYWJzdHJhY3Qgdm9pZCBkaXNwYXRjaENoYXJhY3RlcnNFdmVudHMob3JnLnhtbC5zYXguQ29udGVudEhhbmRsZXIgY2gpCiAgICB0aHJvd3Mgb3JnLnhtbC5zYXguU0FYRXhjZXB0aW9uOwoKICAvKioKICAgKiBEaXJlY3RseSBjYWxsIHRoZQogICAqIGNvbW1lbnQgbWV0aG9kIG9uIHRoZSBwYXNzZWQgTGV4aWNhbEhhbmRsZXIgZm9yIHRoZQogICAqIHN0cmluZy12YWx1ZS4KICAgKgogICAqIEBwYXJhbSBsaCBBIG5vbi1udWxsIHJlZmVyZW5jZSB0byBhIExleGljYWxIYW5kbGVyLgogICAqCiAgICogQHRocm93cyBvcmcueG1sLnNheC5TQVhFeGNlcHRpb24KICAgKi8KICBwdWJsaWMgYWJzdHJhY3Qgdm9pZCBkaXNwYXRjaEFzQ29tbWVudChvcmcueG1sLnNheC5leHQuTGV4aWNhbEhhbmRsZXIgbGgpCiAgICB0aHJvd3Mgb3JnLnhtbC5zYXguU0FYRXhjZXB0aW9uOwogICAgCiAgLyoqCiAgICogQ29uZGl0aW9uYWxseSB0cmltIGFsbCBsZWFkaW5nIGFuZCB0cmFpbGluZyB3aGl0ZXNwYWNlIGluIHRoZSBzcGVjaWZpZWQgU3RyaW5nLgogICAqIEFsbCBzdHJpbmdzIG9mIHdoaXRlIHNwYWNlIGFyZQogICAqIHJlcGxhY2VkIGJ5IGEgc2luZ2xlIHNwYWNlIGNoYXJhY3RlciAoI3gyMCksIGV4Y2VwdCBzcGFjZXMgYWZ0ZXIgcHVuY3R1YXRpb24gd2hpY2gKICAgKiByZWNlaXZlIGRvdWJsZSBzcGFjZXMgaWYgZG91YmxlUHVuY3R1YXRpb25TcGFjZXMgaXMgdHJ1ZS4KICAgKiBUaGlzIGZ1bmN0aW9uIG1heSBiZSB1c2VmdWwgdG8gYSBmb3JtYXR0ZXIsIGJ1dCB0byBnZXQgZmlyc3QgY2xhc3MKICAgKiByZXN1bHRzLCB0aGUgZm9ybWF0dGVyIHNob3VsZCBwcm9iYWJseSBkbyBpdCdzIG93biB3aGl0ZSBzcGFjZSBoYW5kbGluZwogICAqIGJhc2VkIG9uIHRoZSBzZW1hbnRpY3Mgb2YgdGhlIGZvcm1hdHRpbmcgb2JqZWN0LgogICAqIAogICAqIEBwYXJhbSAgIHRyaW1IZWFkICAgIFRyaW0gbGVhZGluZyB3aGl0ZXNwYWNlPwogICAqIEBwYXJhbSAgIHRyaW1UYWlsICAgIFRyaW0gdHJhaWxpbmcgd2hpdGVzcGFjZT8KICAgKiBAcGFyYW0gICBkb3VibGVQdW5jdHVhdGlvblNwYWNlcyAgICBVc2UgZG91YmxlIHNwYWNlcyBmb3IgcHVuY3R1YXRpb24/CiAgICogQHJldHVybiAgICAgICAgICAgICAgVGhlIHRyaW1tZWQgc3RyaW5nLgogICAqLwogIHB1YmxpYyBYTUxTdHJpbmcgZml4V2hpdGVTcGFjZShib29sZWFuIHRyaW1IZWFkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBib29sZWFuIHRyaW1UYWlsLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBib29sZWFuIGRvdWJsZVB1bmN0dWF0aW9uU3BhY2VzKTsKCiAgLyoqCiAgICogUmV0dXJucyB0aGUgbGVuZ3RoIG9mIHRoaXMgc3RyaW5nLgogICAqCiAgICogQHJldHVybiAgdGhlIGxlbmd0aCBvZiB0aGUgc2VxdWVuY2Ugb2YgY2hhcmFjdGVycyByZXByZXNlbnRlZCBieSB0aGlzCiAgICogICAgICAgICAgb2JqZWN0LgogICAqLwogIHB1YmxpYyBhYnN0cmFjdCBpbnQgbGVuZ3RoKCk7CgogIC8qKgogICAqIFJldHVybnMgdGhlIGNoYXJhY3RlciBhdCB0aGUgc3BlY2lmaWVkIGluZGV4LiBBbiBpbmRleCByYW5nZXMKICAgKiBmcm9tIDxjb2RlPjA8L2NvZGU+IHRvIDxjb2RlPmxlbmd0aCgpIC0gMTwvY29kZT4uIFRoZSBmaXJzdCBjaGFyYWN0ZXIKICAgKiBvZiB0aGUgc2VxdWVuY2UgaXMgYXQgaW5kZXggPGNvZGU+MDwvY29kZT4sIHRoZSBuZXh0IGF0IGluZGV4CiAgICogPGNvZGU+MTwvY29kZT4sIGFuZCBzbyBvbiwgYXMgZm9yIGFycmF5IGluZGV4aW5nLgogICAqCiAgICogQHBhcmFtICAgICAgaW5kZXggICB0aGUgaW5kZXggb2YgdGhlIGNoYXJhY3Rlci4KICAgKiBAcmV0dXJuICAgICB0aGUgY2hhcmFjdGVyIGF0IHRoZSBzcGVjaWZpZWQgaW5kZXggb2YgdGhpcyBzdHJpbmcuCiAgICogICAgICAgICAgICAgVGhlIGZpcnN0IGNoYXJhY3RlciBpcyBhdCBpbmRleCA8Y29kZT4wPC9jb2RlPi4KICAgKiBAZXhjZXB0aW9uICBJbmRleE91dE9mQm91bmRzRXhjZXB0aW9uICBpZiB0aGUgPGNvZGU+aW5kZXg8L2NvZGU+CiAgICogICAgICAgICAgICAgYXJndW1lbnQgaXMgbmVnYXRpdmUgb3Igbm90IGxlc3MgdGhhbiB0aGUgbGVuZ3RoIG9mIHRoaXMKICAgKiAgICAgICAgICAgICBzdHJpbmcuCiAgICovCiAgcHVibGljIGFic3RyYWN0IGNoYXIgY2hhckF0KGludCBpbmRleCk7CgogIC8qKgogICAqIENvcGllcyBjaGFyYWN0ZXJzIGZyb20gdGhpcyBzdHJpbmcgaW50byB0aGUgZGVzdGluYXRpb24gY2hhcmFjdGVyCiAgICogYXJyYXkuCiAgICoKICAgKiBAcGFyYW0gICAgICBzcmNCZWdpbiAgIGluZGV4IG9mIHRoZSBmaXJzdCBjaGFyYWN0ZXIgaW4gdGhlIHN0cmluZwogICAqICAgICAgICAgICAgICAgICAgICAgICAgdG8gY29weS4KICAgKiBAcGFyYW0gICAgICBzcmNFbmQgICAgIGluZGV4IGFmdGVyIHRoZSBsYXN0IGNoYXJhY3RlciBpbiB0aGUgc3RyaW5nCiAgICogICAgICAgICAgICAgICAgICAgICAgICB0byBjb3B5LgogICAqIEBwYXJhbSAgICAgIGRzdCAgICAgICAgdGhlIGRlc3RpbmF0aW9uIGFycmF5LgogICAqIEBwYXJhbSAgICAgIGRzdEJlZ2luICAgdGhlIHN0YXJ0IG9mZnNldCBpbiB0aGUgZGVzdGluYXRpb24gYXJyYXkuCiAgICogQGV4Y2VwdGlvbiBJbmRleE91dE9mQm91bmRzRXhjZXB0aW9uIElmIGFueSBvZiB0aGUgZm9sbG93aW5nCiAgICogICAgICAgICAgICBpcyB0cnVlOgogICAqICAgICAgICAgICAgPHVsPjxsaT48Y29kZT5zcmNCZWdpbjwvY29kZT4gaXMgbmVnYXRpdmUuCiAgICogICAgICAgICAgICA8bGk+PGNvZGU+c3JjQmVnaW48L2NvZGU+IGlzIGdyZWF0ZXIgdGhhbiA8Y29kZT5zcmNFbmQ8L2NvZGU+CiAgICogICAgICAgICAgICA8bGk+PGNvZGU+c3JjRW5kPC9jb2RlPiBpcyBncmVhdGVyIHRoYW4gdGhlIGxlbmd0aCBvZiB0aGlzCiAgICogICAgICAgICAgICAgICAgc3RyaW5nCiAgICogICAgICAgICAgICA8bGk+PGNvZGU+ZHN0QmVnaW48L2NvZGU+IGlzIG5lZ2F0aXZlCiAgICogICAgICAgICAgICA8bGk+PGNvZGU+ZHN0QmVnaW4rKHNyY0VuZC1zcmNCZWdpbik8L2NvZGU+IGlzIGxhcmdlciB0aGFuCiAgICogICAgICAgICAgICAgICAgPGNvZGU+ZHN0Lmxlbmd0aDwvY29kZT48L3VsPgogICAqIEBleGNlcHRpb24gTnVsbFBvaW50ZXJFeGNlcHRpb24gaWYgPGNvZGU+ZHN0PC9jb2RlPiBpcyA8Y29kZT5udWxsPC9jb2RlPgogICAqLwogIHB1YmxpYyBhYnN0cmFjdCB2b2lkIGdldENoYXJzKGludCBzcmNCZWdpbiwgaW50IHNyY0VuZCwgY2hhciBkc3RbXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnQgZHN0QmVnaW4pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogIC8qKgogICAqIENvbXBhcmVzIHRoaXMgc3RyaW5nIHRvIHRoZSBzcGVjaWZpZWQgb2JqZWN0LgogICAqIFRoZSByZXN1bHQgaXMgPGNvZGU+dHJ1ZTwvY29kZT4gaWYgYW5kIG9ubHkgaWYgdGhlIGFyZ3VtZW50IGlzIG5vdAogICAqIDxjb2RlPm51bGw8L2NvZGU+IGFuZCBpcyBhIDxjb2RlPlN0cmluZzwvY29kZT4gb2JqZWN0IHRoYXQgcmVwcmVzZW50cwogICAqIHRoZSBzYW1lIHNlcXVlbmNlIG9mIGNoYXJhY3RlcnMgYXMgdGhpcyBvYmplY3QuCiAgICoKICAgKiBAcGFyYW0gICBhbk9iamVjdCAgIHRoZSBvYmplY3QgdG8gY29tcGFyZSB0aGlzIDxjb2RlPlN0cmluZzwvY29kZT4KICAgKiAgICAgICAgICAgICAgICAgICAgIGFnYWluc3QuCiAgICogQHJldHVybiAgPGNvZGU+dHJ1ZTwvY29kZT4gaWYgdGhlIDxjb2RlPlN0cmluZyA8L2NvZGU+YXJlIGVxdWFsOwogICAqICAgICAgICAgIDxjb2RlPmZhbHNlPC9jb2RlPiBvdGhlcndpc2UuCiAgICogQHNlZSAgICAgamF2YS5sYW5nLlN0cmluZyNjb21wYXJlVG8oamF2YS5sYW5nLlN0cmluZykKICAgKiBAc2VlICAgICBqYXZhLmxhbmcuU3RyaW5nI2VxdWFsc0lnbm9yZUNhc2UoamF2YS5sYW5nLlN0cmluZykKICAgKi8KICBwdWJsaWMgYWJzdHJhY3QgYm9vbGVhbiBlcXVhbHMoWE1MU3RyaW5nIGFuT2JqZWN0KTsKCgogIC8qKgogICAqIENvbXBhcmVzIHRoaXMgc3RyaW5nIHRvIHRoZSBzcGVjaWZpZWQgb2JqZWN0LgogICAqIFRoZSByZXN1bHQgaXMgPGNvZGU+dHJ1ZTwvY29kZT4gaWYgYW5kIG9ubHkgaWYgdGhlIGFyZ3VtZW50IGlzIG5vdAogICAqIDxjb2RlPm51bGw8L2NvZGU+IGFuZCBpcyBhIDxjb2RlPlN0cmluZzwvY29kZT4gb2JqZWN0IHRoYXQgcmVwcmVzZW50cwogICAqIHRoZSBzYW1lIHNlcXVlbmNlIG9mIGNoYXJhY3RlcnMgYXMgdGhpcyBvYmplY3QuCiAgICoKICAgKiBAcGFyYW0gICBhbk9iamVjdCAgIHRoZSBvYmplY3QgdG8gY29tcGFyZSB0aGlzIDxjb2RlPlN0cmluZzwvY29kZT4KICAgKiAgICAgICAgICAgICAgICAgICAgIGFnYWluc3QuCiAgICogQHJldHVybiAgPGNvZGU+dHJ1ZTwvY29kZT4gaWYgdGhlIDxjb2RlPlN0cmluZyA8L2NvZGU+YXJlIGVxdWFsOwogICAqICAgICAgICAgIDxjb2RlPmZhbHNlPC9jb2RlPiBvdGhlcndpc2UuCiAgICogQHNlZSAgICAgamF2YS5sYW5nLlN0cmluZyNjb21wYXJlVG8oamF2YS5sYW5nLlN0cmluZykKICAgKiBAc2VlICAgICBqYXZhLmxhbmcuU3RyaW5nI2VxdWFsc0lnbm9yZUNhc2UoamF2YS5sYW5nLlN0cmluZykKICAgKi8KICBwdWJsaWMgYWJzdHJhY3QgYm9vbGVhbiBlcXVhbHMoT2JqZWN0IGFuT2JqZWN0KTsKCiAgLyoqCiAgICogQ29tcGFyZXMgdGhpcyA8Y29kZT5TdHJpbmc8L2NvZGU+IHRvIGFub3RoZXIgPGNvZGU+U3RyaW5nPC9jb2RlPiwKICAgKiBpZ25vcmluZyBjYXNlIGNvbnNpZGVyYXRpb25zLiAgVHdvIHN0cmluZ3MgYXJlIGNvbnNpZGVyZWQgZXF1YWwKICAgKiBpZ25vcmluZyBjYXNlIGlmIHRoZXkgYXJlIG9mIHRoZSBzYW1lIGxlbmd0aCwgYW5kIGNvcnJlc3BvbmRpbmcKICAgKiBjaGFyYWN0ZXJzIGluIHRoZSB0d28gc3RyaW5ncyBhcmUgZXF1YWwgaWdub3JpbmcgY2FzZS4KICAgKgogICAqIEBwYXJhbSAgIGFub3RoZXJTdHJpbmcgICB0aGUgPGNvZGU+U3RyaW5nPC9jb2RlPiB0byBjb21wYXJlIHRoaXMKICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgPGNvZGU+U3RyaW5nPC9jb2RlPiBhZ2FpbnN0LgogICAqIEByZXR1cm4gIDxjb2RlPnRydWU8L2NvZGU+IGlmIHRoZSBhcmd1bWVudCBpcyBub3QgPGNvZGU+bnVsbDwvY29kZT4KICAgKiAgICAgICAgICBhbmQgdGhlIDxjb2RlPlN0cmluZzwvY29kZT5zIGFyZSBlcXVhbCwKICAgKiAgICAgICAgICBpZ25vcmluZyBjYXNlOyA8Y29kZT5mYWxzZTwvY29kZT4gb3RoZXJ3aXNlLgogICAqIEBzZWUgICAgICNlcXVhbHMoT2JqZWN0KQogICAqIEBzZWUgICAgIGphdmEubGFuZy5DaGFyYWN0ZXIjdG9Mb3dlckNhc2UoY2hhcikKICAgKiBAc2VlIGphdmEubGFuZy5DaGFyYWN0ZXIjdG9VcHBlckNhc2UoY2hhcikKICAgKi8KICBwdWJsaWMgYWJzdHJhY3QgYm9vbGVhbiBlcXVhbHNJZ25vcmVDYXNlKFN0cmluZyBhbm90aGVyU3RyaW5nKTsKCiAgLyoqCiAgICogQ29tcGFyZXMgdHdvIHN0cmluZ3MgbGV4aWNvZ3JhcGhpY2FsbHkuCiAgICoKICAgKiBAcGFyYW0gICBhbm90aGVyU3RyaW5nICAgdGhlIDxjb2RlPlN0cmluZzwvY29kZT4gdG8gYmUgY29tcGFyZWQuCiAgICogQHJldHVybiAgdGhlIHZhbHVlIDxjb2RlPjA8L2NvZGU+IGlmIHRoZSBhcmd1bWVudCBzdHJpbmcgaXMgZXF1YWwgdG8KICAgKiAgICAgICAgICB0aGlzIHN0cmluZzsgYSB2YWx1ZSBsZXNzIHRoYW4gPGNvZGU+MDwvY29kZT4gaWYgdGhpcyBzdHJpbmcKICAgKiAgICAgICAgICBpcyBsZXhpY29ncmFwaGljYWxseSBsZXNzIHRoYW4gdGhlIHN0cmluZyBhcmd1bWVudDsgYW5kIGEKICAgKiAgICAgICAgICB2YWx1ZSBncmVhdGVyIHRoYW4gPGNvZGU+MDwvY29kZT4gaWYgdGhpcyBzdHJpbmcgaXMKICAgKiAgICAgICAgICBsZXhpY29ncmFwaGljYWxseSBncmVhdGVyIHRoYW4gdGhlIHN0cmluZyBhcmd1bWVudC4KICAgKiBAZXhjZXB0aW9uIGphdmEubGFuZy5OdWxsUG9pbnRlckV4Y2VwdGlvbiBpZiA8Y29kZT5hbm90aGVyU3RyaW5nPC9jb2RlPgogICAqICAgICAgICAgIGlzIDxjb2RlPm51bGw8L2NvZGU+LgogICAqLwogIHB1YmxpYyBhYnN0cmFjdCBpbnQgY29tcGFyZVRvKFhNTFN0cmluZyBhbm90aGVyU3RyaW5nKTsKCiAgLyoqCiAgICogQ29tcGFyZXMgdHdvIHN0cmluZ3MgbGV4aWNvZ3JhcGhpY2FsbHksIGlnbm9yaW5nIGNhc2UgY29uc2lkZXJhdGlvbnMuCiAgICogVGhpcyBtZXRob2QgcmV0dXJucyBhbiBpbnRlZ2VyIHdob3NlIHNpZ24gaXMgdGhhdCBvZgogICAqIDxjb2RlPnRoaXMudG9VcHBlckNhc2UoKS50b0xvd2VyQ2FzZSgpLmNvbXBhcmVUbygKICAgKiBzdHIudG9VcHBlckNhc2UoKS50b0xvd2VyQ2FzZSgpKTwvY29kZT4uCiAgICogPHA+CiAgICogTm90ZSB0aGF0IHRoaXMgbWV0aG9kIGRvZXMgPGVtPm5vdDwvZW0+IHRha2UgbG9jYWxlIGludG8gYWNjb3VudCwKICAgKiBhbmQgd2lsbCByZXN1bHQgaW4gYW4gdW5zYXRpc2ZhY3Rvcnkgb3JkZXJpbmcgZm9yIGNlcnRhaW4gbG9jYWxlcy4KICAgKiBUaGUgamF2YS50ZXh0IHBhY2thZ2UgcHJvdmlkZXMgPGVtPmNvbGxhdG9yczwvZW0+IHRvIGFsbG93CiAgICogbG9jYWxlLXNlbnNpdGl2ZSBvcmRlcmluZy4KICAgKgogICAqIEBwYXJhbSAgIHN0ciAgIHRoZSA8Y29kZT5TdHJpbmc8L2NvZGU+IHRvIGJlIGNvbXBhcmVkLgogICAqIEByZXR1cm4gIGEgbmVnYXRpdmUgaW50ZWdlciwgemVybywgb3IgYSBwb3NpdGl2ZSBpbnRlZ2VyIGFzIHRoZQogICAqICAgICAgICAgIHRoZSBzcGVjaWZpZWQgU3RyaW5nIGlzIGdyZWF0ZXIgdGhhbiwgZXF1YWwgdG8sIG9yIGxlc3MKICAgKiAgICAgICAgICB0aGFuIHRoaXMgU3RyaW5nLCBpZ25vcmluZyBjYXNlIGNvbnNpZGVyYXRpb25zLgogICAqIEBzZWUgICAgIGphdmEudGV4dC5Db2xsYXRvciNjb21wYXJlKFN0cmluZywgU3RyaW5nKQogICAqIEBzaW5jZSAgIDEuMgogICAqLwogIHB1YmxpYyBhYnN0cmFjdCBpbnQgY29tcGFyZVRvSWdub3JlQ2FzZShYTUxTdHJpbmcgc3RyKTsKCiAgLyoqCiAgICogVGVzdHMgaWYgdGhpcyBzdHJpbmcgc3RhcnRzIHdpdGggdGhlIHNwZWNpZmllZCBwcmVmaXggYmVnaW5uaW5nCiAgICogYSBzcGVjaWZpZWQgaW5kZXguCiAgICoKICAgKiBAcGFyYW0gICBwcmVmaXggICAgdGhlIHByZWZpeC4KICAgKiBAcGFyYW0gICB0b2Zmc2V0ICAgd2hlcmUgdG8gYmVnaW4gbG9va2luZyBpbiB0aGUgc3RyaW5nLgogICAqIEByZXR1cm4gIDxjb2RlPnRydWU8L2NvZGU+IGlmIHRoZSBjaGFyYWN0ZXIgc2VxdWVuY2UgcmVwcmVzZW50ZWQgYnkgdGhlCiAgICogICAgICAgICAgYXJndW1lbnQgaXMgYSBwcmVmaXggb2YgdGhlIHN1YnN0cmluZyBvZiB0aGlzIG9iamVjdCBzdGFydGluZwogICAqICAgICAgICAgIGF0IGluZGV4IDxjb2RlPnRvZmZzZXQ8L2NvZGU+OyA8Y29kZT5mYWxzZTwvY29kZT4gb3RoZXJ3aXNlLgogICAqICAgICAgICAgIFRoZSByZXN1bHQgaXMgPGNvZGU+ZmFsc2U8L2NvZGU+IGlmIDxjb2RlPnRvZmZzZXQ8L2NvZGU+IGlzCiAgICogICAgICAgICAgbmVnYXRpdmUgb3IgZ3JlYXRlciB0aGFuIHRoZSBsZW5ndGggb2YgdGhpcwogICAqICAgICAgICAgIDxjb2RlPlN0cmluZzwvY29kZT4gb2JqZWN0OyBvdGhlcndpc2UgdGhlIHJlc3VsdCBpcyB0aGUgc2FtZQogICAqICAgICAgICAgIGFzIHRoZSByZXN1bHQgb2YgdGhlIGV4cHJlc3Npb24KICAgKiAgICAgICAgICA8cHJlPgogICAqICAgICAgICAgIHRoaXMuc3ViU3RyaW5nKHRvZmZzZXQpLnN0YXJ0c1dpdGgocHJlZml4KQogICAqICAgICAgICAgIDwvcHJlPgogICAqIEBleGNlcHRpb24gamF2YS5sYW5nLk51bGxQb2ludGVyRXhjZXB0aW9uIGlmIDxjb2RlPnByZWZpeDwvY29kZT4gaXMKICAgKiAgICAgICAgICA8Y29kZT5udWxsPC9jb2RlPi4KICAgKi8KICBwdWJsaWMgYWJzdHJhY3QgYm9vbGVhbiBzdGFydHNXaXRoKFN0cmluZyBwcmVmaXgsIGludCB0b2Zmc2V0KTsKCiAgLyoqCiAgICogVGVzdHMgaWYgdGhpcyBzdHJpbmcgc3RhcnRzIHdpdGggdGhlIHNwZWNpZmllZCBwcmVmaXggYmVnaW5uaW5nCiAgICogYSBzcGVjaWZpZWQgaW5kZXguCiAgICoKICAgKiBAcGFyYW0gICBwcmVmaXggICAgdGhlIHByZWZpeC4KICAgKiBAcGFyYW0gICB0b2Zmc2V0ICAgd2hlcmUgdG8gYmVnaW4gbG9va2luZyBpbiB0aGUgc3RyaW5nLgogICAqIEByZXR1cm4gIDxjb2RlPnRydWU8L2NvZGU+IGlmIHRoZSBjaGFyYWN0ZXIgc2VxdWVuY2UgcmVwcmVzZW50ZWQgYnkgdGhlCiAgICogICAgICAgICAgYXJndW1lbnQgaXMgYSBwcmVmaXggb2YgdGhlIHN1YnN0cmluZyBvZiB0aGlzIG9iamVjdCBzdGFydGluZwogICAqICAgICAgICAgIGF0IGluZGV4IDxjb2RlPnRvZmZzZXQ8L2NvZGU+OyA8Y29kZT5mYWxzZTwvY29kZT4gb3RoZXJ3aXNlLgogICAqICAgICAgICAgIFRoZSByZXN1bHQgaXMgPGNvZGU+ZmFsc2U8L2NvZGU+IGlmIDxjb2RlPnRvZmZzZXQ8L2NvZGU+IGlzCiAgICogICAgICAgICAgbmVnYXRpdmUgb3IgZ3JlYXRlciB0aGFuIHRoZSBsZW5ndGggb2YgdGhpcwogICAqICAgICAgICAgIDxjb2RlPlN0cmluZzwvY29kZT4gb2JqZWN0OyBvdGhlcndpc2UgdGhlIHJlc3VsdCBpcyB0aGUgc2FtZQogICAqICAgICAgICAgIGFzIHRoZSByZXN1bHQgb2YgdGhlIGV4cHJlc3Npb24KICAgKiAgICAgICAgICA8cHJlPgogICAqICAgICAgICAgIHRoaXMuc3ViU3RyaW5nKHRvZmZzZXQpLnN0YXJ0c1dpdGgocHJlZml4KQogICAqICAgICAgICAgIDwvcHJlPgogICAqIEBleGNlcHRpb24gamF2YS5sYW5nLk51bGxQb2ludGVyRXhjZXB0aW9uIGlmIDxjb2RlPnByZWZpeDwvY29kZT4gaXMKICAgKiAgICAgICAgICA8Y29kZT5udWxsPC9jb2RlPi4KICAgKi8KICBwdWJsaWMgYWJzdHJhY3QgYm9vbGVhbiBzdGFydHNXaXRoKFhNTFN0cmluZyBwcmVmaXgsIGludCB0b2Zmc2V0KTsKCiAgLyoqCiAgICogVGVzdHMgaWYgdGhpcyBzdHJpbmcgc3RhcnRzIHdpdGggdGhlIHNwZWNpZmllZCBwcmVmaXguCiAgICoKICAgKiBAcGFyYW0gICBwcmVmaXggICB0aGUgcHJlZml4LgogICAqIEByZXR1cm4gIDxjb2RlPnRydWU8L2NvZGU+IGlmIHRoZSBjaGFyYWN0ZXIgc2VxdWVuY2UgcmVwcmVzZW50ZWQgYnkgdGhlCiAgICogICAgICAgICAgYXJndW1lbnQgaXMgYSBwcmVmaXggb2YgdGhlIGNoYXJhY3RlciBzZXF1ZW5jZSByZXByZXNlbnRlZCBieQogICAqICAgICAgICAgIHRoaXMgc3RyaW5nOyA8Y29kZT5mYWxzZTwvY29kZT4gb3RoZXJ3aXNlLgogICAqICAgICAgICAgIE5vdGUgYWxzbyB0aGF0IDxjb2RlPnRydWU8L2NvZGU+IHdpbGwgYmUgcmV0dXJuZWQgaWYgdGhlCiAgICogICAgICAgICAgYXJndW1lbnQgaXMgYW4gZW1wdHkgc3RyaW5nIG9yIGlzIGVxdWFsIHRvIHRoaXMKICAgKiAgICAgICAgICA8Y29kZT5TdHJpbmc8L2NvZGU+IG9iamVjdCBhcyBkZXRlcm1pbmVkIGJ5IHRoZQogICAqICAgICAgICAgIHtAbGluayAjZXF1YWxzKE9iamVjdCl9IG1ldGhvZC4KICAgKiBAZXhjZXB0aW9uIGphdmEubGFuZy5OdWxsUG9pbnRlckV4Y2VwdGlvbiBpZiA8Y29kZT5wcmVmaXg8L2NvZGU+IGlzCiAgICogICAgICAgICAgPGNvZGU+bnVsbDwvY29kZT4uCiAgICogQHNpbmNlICAgSkRLMS4gMAogICAqLwogIHB1YmxpYyBhYnN0cmFjdCBib29sZWFuIHN0YXJ0c1dpdGgoU3RyaW5nIHByZWZpeCk7CgogIC8qKgogICAqIFRlc3RzIGlmIHRoaXMgc3RyaW5nIHN0YXJ0cyB3aXRoIHRoZSBzcGVjaWZpZWQgcHJlZml4LgogICAqCiAgICogQHBhcmFtICAgcHJlZml4ICAgdGhlIHByZWZpeC4KICAgKiBAcmV0dXJuICA8Y29kZT50cnVlPC9jb2RlPiBpZiB0aGUgY2hhcmFjdGVyIHNlcXVlbmNlIHJlcHJlc2VudGVkIGJ5IHRoZQogICAqICAgICAgICAgIGFyZ3VtZW50IGlzIGEgcHJlZml4IG9mIHRoZSBjaGFyYWN0ZXIgc2VxdWVuY2UgcmVwcmVzZW50ZWQgYnkKICAgKiAgICAgICAgICB0aGlzIHN0cmluZzsgPGNvZGU+ZmFsc2U8L2NvZGU+IG90aGVyd2lzZS4KICAgKiAgICAgICAgICBOb3RlIGFsc28gdGhhdCA8Y29kZT50cnVlPC9jb2RlPiB3aWxsIGJlIHJldHVybmVkIGlmIHRoZQogICAqICAgICAgICAgIGFyZ3VtZW50IGlzIGFuIGVtcHR5IHN0cmluZyBvciBpcyBlcXVhbCB0byB0aGlzCiAgICogICAgICAgICAgPGNvZGU+U3RyaW5nPC9jb2RlPiBvYmplY3QgYXMgZGV0ZXJtaW5lZCBieSB0aGUKICAgKiAgICAgICAgICB7QGxpbmsgI2VxdWFscyhPYmplY3QpfSBtZXRob2QuCiAgICogQGV4Y2VwdGlvbiBqYXZhLmxhbmcuTnVsbFBvaW50ZXJFeGNlcHRpb24gaWYgPGNvZGU+cHJlZml4PC9jb2RlPiBpcwogICAqICAgICAgICAgIDxjb2RlPm51bGw8L2NvZGU+LgogICAqIEBzaW5jZSAgIEpESzEuIDAKICAgKi8KICBwdWJsaWMgYWJzdHJhY3QgYm9vbGVhbiBzdGFydHNXaXRoKFhNTFN0cmluZyBwcmVmaXgpOwoKICAvKioKICAgKiBUZXN0cyBpZiB0aGlzIHN0cmluZyBlbmRzIHdpdGggdGhlIHNwZWNpZmllZCBzdWZmaXguCiAgICoKICAgKiBAcGFyYW0gICBzdWZmaXggICB0aGUgc3VmZml4LgogICAqIEByZXR1cm4gIDxjb2RlPnRydWU8L2NvZGU+IGlmIHRoZSBjaGFyYWN0ZXIgc2VxdWVuY2UgcmVwcmVzZW50ZWQgYnkgdGhlCiAgICogICAgICAgICAgYXJndW1lbnQgaXMgYSBzdWZmaXggb2YgdGhlIGNoYXJhY3RlciBzZXF1ZW5jZSByZXByZXNlbnRlZCBieQogICAqICAgICAgICAgIHRoaXMgb2JqZWN0OyA8Y29kZT5mYWxzZTwvY29kZT4gb3RoZXJ3aXNlLiBOb3RlIHRoYXQgdGhlCiAgICogICAgICAgICAgcmVzdWx0IHdpbGwgYmUgPGNvZGU+dHJ1ZTwvY29kZT4gaWYgdGhlIGFyZ3VtZW50IGlzIHRoZQogICAqICAgICAgICAgIGVtcHR5IHN0cmluZyBvciBpcyBlcXVhbCB0byB0aGlzIDxjb2RlPlN0cmluZzwvY29kZT4gb2JqZWN0CiAgICogICAgICAgICAgYXMgZGV0ZXJtaW5lZCBieSB0aGUge0BsaW5rICNlcXVhbHMoT2JqZWN0KX0gbWV0aG9kLgogICAqIEBleGNlcHRpb24gamF2YS5sYW5nLk51bGxQb2ludGVyRXhjZXB0aW9uIGlmIDxjb2RlPnN1ZmZpeDwvY29kZT4gaXMKICAgKiAgICAgICAgICA8Y29kZT5udWxsPC9jb2RlPi4KICAgKi8KICBwdWJsaWMgYWJzdHJhY3QgYm9vbGVhbiBlbmRzV2l0aChTdHJpbmcgc3VmZml4KTsKCiAgLyoqCiAgICogUmV0dXJucyBhIGhhc2hjb2RlIGZvciB0aGlzIHN0cmluZy4gVGhlIGhhc2hjb2RlIGZvciBhCiAgICogPGNvZGU+U3RyaW5nPC9jb2RlPiBvYmplY3QgaXMgY29tcHV0ZWQgYXMKICAgKiA8YmxvY2txdW90ZT48cHJlPgogICAqIHNbMF0qMzFeKG4tMSkgKyBzWzFdKjMxXihuLTIpICsgLi4uICsgc1tuLTFdCiAgICogPC9wcmU+PC9ibG9ja3F1b3RlPgogICAqIHVzaW5nIDxjb2RlPmludDwvY29kZT4gYXJpdGhtZXRpYywgd2hlcmUgPGNvZGU+c1tpXTwvY29kZT4gaXMgdGhlCiAgICogPGk+aTwvaT50aCBjaGFyYWN0ZXIgb2YgdGhlIHN0cmluZywgPGNvZGU+bjwvY29kZT4gaXMgdGhlIGxlbmd0aCBvZgogICAqIHRoZSBzdHJpbmcsIGFuZCA8Y29kZT5ePC9jb2RlPiBpbmRpY2F0ZXMgZXhwb25lbnRpYXRpb24uCiAgICogKFRoZSBoYXNoIHZhbHVlIG9mIHRoZSBlbXB0eSBzdHJpbmcgaXMgemVyby4pCiAgICoKICAgKiBAcmV0dXJuICBhIGhhc2ggY29kZSB2YWx1ZSBmb3IgdGhpcyBvYmplY3QuCiAgICovCiAgcHVibGljIGFic3RyYWN0IGludCBoYXNoQ29kZSgpOwoKICAvKioKICAgKiBSZXR1cm5zIHRoZSBpbmRleCB3aXRoaW4gdGhpcyBzdHJpbmcgb2YgdGhlIGZpcnN0IG9jY3VycmVuY2Ugb2YgdGhlCiAgICogc3BlY2lmaWVkIGNoYXJhY3Rlci4gSWYgYSBjaGFyYWN0ZXIgd2l0aCB2YWx1ZSA8Y29kZT5jaDwvY29kZT4gb2NjdXJzCiAgICogaW4gdGhlIGNoYXJhY3RlciBzZXF1ZW5jZSByZXByZXNlbnRlZCBieSB0aGlzIDxjb2RlPlN0cmluZzwvY29kZT4KICAgKiBvYmplY3QsIHRoZW4gdGhlIGluZGV4IG9mIHRoZSBmaXJzdCBzdWNoIG9jY3VycmVuY2UgaXMgcmV0dXJuZWQgLS0KICAgKiB0aGF0IGlzLCB0aGUgc21hbGxlc3QgdmFsdWUgPGk+azwvaT4gc3VjaCB0aGF0OgogICAqIDxibG9ja3F1b3RlPjxwcmU+CiAgICogdGhpcy5jaGFyQXQoPGk+azwvaT4pID09IGNoCiAgICogPC9wcmU+PC9ibG9ja3F1b3RlPgogICAqIGlzIDxjb2RlPnRydWU8L2NvZGU+LiBJZiBubyBzdWNoIGNoYXJhY3RlciBvY2N1cnMgaW4gdGhpcyBzdHJpbmcsCiAgICogdGhlbiA8Y29kZT4tMTwvY29kZT4gaXMgcmV0dXJuZWQuCiAgICoKICAgKiBAcGFyYW0gICBjaCAgIGEgY2hhcmFjdGVyLgogICAqIEByZXR1cm4gIHRoZSBpbmRleCBvZiB0aGUgZmlyc3Qgb2NjdXJyZW5jZSBvZiB0aGUgY2hhcmFjdGVyIGluIHRoZQogICAqICAgICAgICAgIGNoYXJhY3RlciBzZXF1ZW5jZSByZXByZXNlbnRlZCBieSB0aGlzIG9iamVjdCwgb3IKICAgKiAgICAgICAgICA8Y29kZT4tMTwvY29kZT4gaWYgdGhlIGNoYXJhY3RlciBkb2VzIG5vdCBvY2N1ci4KICAgKi8KICBwdWJsaWMgYWJzdHJhY3QgaW50IGluZGV4T2YoaW50IGNoKTsKCiAgLyoqCiAgICogUmV0dXJucyB0aGUgaW5kZXggd2l0aGluIHRoaXMgc3RyaW5nIG9mIHRoZSBmaXJzdCBvY2N1cnJlbmNlIG9mIHRoZQogICAqIHNwZWNpZmllZCBjaGFyYWN0ZXIsIHN0YXJ0aW5nIHRoZSBzZWFyY2ggYXQgdGhlIHNwZWNpZmllZCBpbmRleC4KICAgKiA8cD4KICAgKiBJZiBhIGNoYXJhY3RlciB3aXRoIHZhbHVlIDxjb2RlPmNoPC9jb2RlPiBvY2N1cnMgaW4gdGhlIGNoYXJhY3RlcgogICAqIHNlcXVlbmNlIHJlcHJlc2VudGVkIGJ5IHRoaXMgPGNvZGU+U3RyaW5nPC9jb2RlPiBvYmplY3QgYXQgYW4gaW5kZXgKICAgKiBubyBzbWFsbGVyIHRoYW4gPGNvZGU+ZnJvbUluZGV4PC9jb2RlPiwgdGhlbiB0aGUgaW5kZXggb2YgdGhlIGZpcnN0CiAgICogc3VjaCBvY2N1cnJlbmNlIGlzIHJldHVybmVkLS10aGF0IGlzLCB0aGUgc21hbGxlc3QgdmFsdWUgPGk+azwvaT4KICAgKiBzdWNoIHRoYXQ6CiAgICogPGJsb2NrcXVvdGU+PHByZT4KICAgKiAodGhpcy5jaGFyQXQoPGk+azwvaT4pID09IGNoKSAmJiAoPGk+azwvaT4gPj0gZnJvbUluZGV4KQogICAqIDwvcHJlPjwvYmxvY2txdW90ZT4KICAgKiBpcyB0cnVlLiBJZiBubyBzdWNoIGNoYXJhY3RlciBvY2N1cnMgaW4gdGhpcyBzdHJpbmcgYXQgb3IgYWZ0ZXIKICAgKiBwb3NpdGlvbiA8Y29kZT5mcm9tSW5kZXg8L2NvZGU+LCB0aGVuIDxjb2RlPi0xPC9jb2RlPiBpcyByZXR1cm5lZC4KICAgKiA8cD4KICAgKiBUaGVyZSBpcyBubyByZXN0cmljdGlvbiBvbiB0aGUgdmFsdWUgb2YgPGNvZGU+ZnJvbUluZGV4PC9jb2RlPi4gSWYgaXQKICAgKiBpcyBuZWdhdGl2ZSwgaXQgaGFzIHRoZSBzYW1lIGVmZmVjdCBhcyBpZiBpdCB3ZXJlIHplcm86IHRoaXMgZW50aXJlCiAgICogc3RyaW5nIG1heSBiZSBzZWFyY2hlZC4gSWYgaXQgaXMgZ3JlYXRlciB0aGFuIHRoZSBsZW5ndGggb2YgdGhpcwogICAqIHN0cmluZywgaXQgaGFzIHRoZSBzYW1lIGVmZmVjdCBhcyBpZiBpdCB3ZXJlIGVxdWFsIHRvIHRoZSBsZW5ndGggb2YKICAgKiB0aGlzIHN0cmluZzogPGNvZGU+LTE8L2NvZGU+IGlzIHJldHVybmVkLgogICAqCiAgICogQHBhcmFtICAgY2ggICAgICAgICAgYSBjaGFyYWN0ZXIuCiAgICogQHBhcmFtICAgZnJvbUluZGV4ICAgdGhlIGluZGV4IHRvIHN0YXJ0IHRoZSBzZWFyY2ggZnJvbS4KICAgKiBAcmV0dXJuICB0aGUgaW5kZXggb2YgdGhlIGZpcnN0IG9jY3VycmVuY2Ugb2YgdGhlIGNoYXJhY3RlciBpbiB0aGUKICAgKiAgICAgICAgICBjaGFyYWN0ZXIgc2VxdWVuY2UgcmVwcmVzZW50ZWQgYnkgdGhpcyBvYmplY3QgdGhhdCBpcyBncmVhdGVyCiAgICogICAgICAgICAgdGhhbiBvciBlcXVhbCB0byA8Y29kZT5mcm9tSW5kZXg8L2NvZGU+LCBvciA8Y29kZT4tMTwvY29kZT4KICAgKiAgICAgICAgICBpZiB0aGUgY2hhcmFjdGVyIGRvZXMgbm90IG9jY3VyLgogICAqLwogIHB1YmxpYyBhYnN0cmFjdCBpbnQgaW5kZXhPZihpbnQgY2gsIGludCBmcm9tSW5kZXgpOwoKICAvKioKICAgKiBSZXR1cm5zIHRoZSBpbmRleCB3aXRoaW4gdGhpcyBzdHJpbmcgb2YgdGhlIGxhc3Qgb2NjdXJyZW5jZSBvZiB0aGUKICAgKiBzcGVjaWZpZWQgY2hhcmFjdGVyLiBUaGF0IGlzLCB0aGUgaW5kZXggcmV0dXJuZWQgaXMgdGhlIGxhcmdlc3QKICAgKiB2YWx1ZSA8aT5rPC9pPiBzdWNoIHRoYXQ6CiAgICogPGJsb2NrcXVvdGU+PHByZT4KICAgKiB0aGlzLmNoYXJBdCg8aT5rPC9pPikgPT0gY2gKICAgKiA8L3ByZT48L2Jsb2NrcXVvdGU+CiAgICogaXMgdHJ1ZS4KICAgKiBUaGUgU3RyaW5nIGlzIHNlYXJjaGVkIGJhY2t3YXJkcyBzdGFydGluZyBhdCB0aGUgbGFzdCBjaGFyYWN0ZXIuCiAgICoKICAgKiBAcGFyYW0gICBjaCAgIGEgY2hhcmFjdGVyLgogICAqIEByZXR1cm4gIHRoZSBpbmRleCBvZiB0aGUgbGFzdCBvY2N1cnJlbmNlIG9mIHRoZSBjaGFyYWN0ZXIgaW4gdGhlCiAgICogICAgICAgICAgY2hhcmFjdGVyIHNlcXVlbmNlIHJlcHJlc2VudGVkIGJ5IHRoaXMgb2JqZWN0LCBvcgogICAqICAgICAgICAgIDxjb2RlPi0xPC9jb2RlPiBpZiB0aGUgY2hhcmFjdGVyIGRvZXMgbm90IG9jY3VyLgogICAqLwogIHB1YmxpYyBhYnN0cmFjdCBpbnQgbGFzdEluZGV4T2YoaW50IGNoKTsKCiAgLyoqCiAgICogUmV0dXJucyB0aGUgaW5kZXggd2l0aGluIHRoaXMgc3RyaW5nIG9mIHRoZSBsYXN0IG9jY3VycmVuY2Ugb2YgdGhlCiAgICogc3BlY2lmaWVkIGNoYXJhY3Rlciwgc2VhcmNoaW5nIGJhY2t3YXJkIHN0YXJ0aW5nIGF0IHRoZSBzcGVjaWZpZWQKICAgKiBpbmRleC4gVGhhdCBpcywgdGhlIGluZGV4IHJldHVybmVkIGlzIHRoZSBsYXJnZXN0IHZhbHVlIDxpPms8L2k+CiAgICogc3VjaCB0aGF0OgogICAqIDxibG9ja3F1b3RlPjxwcmU+CiAgICogdGhpcy5jaGFyQXQoaykgPT0gY2gpICYmIChrIDw9IGZyb21JbmRleCkKICAgKiA8L3ByZT48L2Jsb2NrcXVvdGU+CiAgICogaXMgdHJ1ZS4KICAgKgogICAqIEBwYXJhbSAgIGNoICAgICAgICAgIGEgY2hhcmFjdGVyLgogICAqIEBwYXJhbSAgIGZyb21JbmRleCAgIHRoZSBpbmRleCB0byBzdGFydCB0aGUgc2VhcmNoIGZyb20uIFRoZXJlIGlzIG5vCiAgICogICAgICAgICAgcmVzdHJpY3Rpb24gb24gdGhlIHZhbHVlIG9mIDxjb2RlPmZyb21JbmRleDwvY29kZT4uIElmIGl0IGlzCiAgICogICAgICAgICAgZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRvIHRoZSBsZW5ndGggb2YgdGhpcyBzdHJpbmcsIGl0IGhhcwogICAqICAgICAgICAgIHRoZSBzYW1lIGVmZmVjdCBhcyBpZiBpdCB3ZXJlIGVxdWFsIHRvIG9uZSBsZXNzIHRoYW4gdGhlCiAgICogICAgICAgICAgbGVuZ3RoIG9mIHRoaXMgc3RyaW5nOiB0aGlzIGVudGlyZSBzdHJpbmcgbWF5IGJlIHNlYXJjaGVkLgogICAqICAgICAgICAgIElmIGl0IGlzIG5lZ2F0aXZlLCBpdCBoYXMgdGhlIHNhbWUgZWZmZWN0IGFzIGlmIGl0IHdlcmUgLTE6CiAgICogICAgICAgICAgLTEgaXMgcmV0dXJuZWQuCiAgICogQHJldHVybiAgdGhlIGluZGV4IG9mIHRoZSBsYXN0IG9jY3VycmVuY2Ugb2YgdGhlIGNoYXJhY3RlciBpbiB0aGUKICAgKiAgICAgICAgICBjaGFyYWN0ZXIgc2VxdWVuY2UgcmVwcmVzZW50ZWQgYnkgdGhpcyBvYmplY3QgdGhhdCBpcyBsZXNzCiAgICogICAgICAgICAgdGhhbiBvciBlcXVhbCB0byA8Y29kZT5mcm9tSW5kZXg8L2NvZGU+LCBvciA8Y29kZT4tMTwvY29kZT4KICAgKiAgICAgICAgICBpZiB0aGUgY2hhcmFjdGVyIGRvZXMgbm90IG9jY3VyIGJlZm9yZSB0aGF0IHBvaW50LgogICAqLwogIHB1YmxpYyBhYnN0cmFjdCBpbnQgbGFzdEluZGV4T2YoaW50IGNoLCBpbnQgZnJvbUluZGV4KTsKCiAgLyoqCiAgICogUmV0dXJucyB0aGUgaW5kZXggd2l0aGluIHRoaXMgc3RyaW5nIG9mIHRoZSBmaXJzdCBvY2N1cnJlbmNlIG9mIHRoZQogICAqIHNwZWNpZmllZCBzdWJzdHJpbmcuIFRoZSBpbnRlZ2VyIHJldHVybmVkIGlzIHRoZSBzbWFsbGVzdCB2YWx1ZQogICAqIDxpPms8L2k+IHN1Y2ggdGhhdDoKICAgKiA8YmxvY2txdW90ZT48cHJlPgogICAqIHRoaXMuc3RhcnRzV2l0aChzdHIsIDxpPms8L2k+KQogICAqIDwvcHJlPjwvYmxvY2txdW90ZT4KICAgKiBpcyA8Y29kZT50cnVlPC9jb2RlPi4KICAgKgogICAqIEBwYXJhbSAgIHN0ciAgIGFueSBzdHJpbmcuCiAgICogQHJldHVybiAgaWYgdGhlIHN0cmluZyBhcmd1bWVudCBvY2N1cnMgYXMgYSBzdWJzdHJpbmcgd2l0aGluIHRoaXMKICAgKiAgICAgICAgICBvYmplY3QsIHRoZW4gdGhlIGluZGV4IG9mIHRoZSBmaXJzdCBjaGFyYWN0ZXIgb2YgdGhlIGZpcnN0CiAgICogICAgICAgICAgc3VjaCBzdWJzdHJpbmcgaXMgcmV0dXJuZWQ7IGlmIGl0IGRvZXMgbm90IG9jY3VyIGFzIGEKICAgKiAgICAgICAgICBzdWJzdHJpbmcsIDxjb2RlPi0xPC9jb2RlPiBpcyByZXR1cm5lZC4KICAgKiBAZXhjZXB0aW9uIGphdmEubGFuZy5OdWxsUG9pbnRlckV4Y2VwdGlvbiBpZiA8Y29kZT5zdHI8L2NvZGU+IGlzCiAgICogICAgICAgICAgPGNvZGU+bnVsbDwvY29kZT4uCiAgICovCiAgcHVibGljIGFic3RyYWN0IGludCBpbmRleE9mKFN0cmluZyBzdHIpOwoKICAvKioKICAgKiBSZXR1cm5zIHRoZSBpbmRleCB3aXRoaW4gdGhpcyBzdHJpbmcgb2YgdGhlIGZpcnN0IG9jY3VycmVuY2Ugb2YgdGhlCiAgICogc3BlY2lmaWVkIHN1YnN0cmluZy4gVGhlIGludGVnZXIgcmV0dXJuZWQgaXMgdGhlIHNtYWxsZXN0IHZhbHVlCiAgICogPGk+azwvaT4gc3VjaCB0aGF0OgogICAqIDxibG9ja3F1b3RlPjxwcmU+CiAgICogdGhpcy5zdGFydHNXaXRoKHN0ciwgPGk+azwvaT4pCiAgICogPC9wcmU+PC9ibG9ja3F1b3RlPgogICAqIGlzIDxjb2RlPnRydWU8L2NvZGU+LgogICAqCiAgICogQHBhcmFtICAgc3RyICAgYW55IHN0cmluZy4KICAgKiBAcmV0dXJuICBpZiB0aGUgc3RyaW5nIGFyZ3VtZW50IG9jY3VycyBhcyBhIHN1YnN0cmluZyB3aXRoaW4gdGhpcwogICAqICAgICAgICAgIG9iamVjdCwgdGhlbiB0aGUgaW5kZXggb2YgdGhlIGZpcnN0IGNoYXJhY3RlciBvZiB0aGUgZmlyc3QKICAgKiAgICAgICAgICBzdWNoIHN1YnN0cmluZyBpcyByZXR1cm5lZDsgaWYgaXQgZG9lcyBub3Qgb2NjdXIgYXMgYQogICAqICAgICAgICAgIHN1YnN0cmluZywgPGNvZGU+LTE8L2NvZGU+IGlzIHJldHVybmVkLgogICAqIEBleGNlcHRpb24gamF2YS5sYW5nLk51bGxQb2ludGVyRXhjZXB0aW9uIGlmIDxjb2RlPnN0cjwvY29kZT4gaXMKICAgKiAgICAgICAgICA8Y29kZT5udWxsPC9jb2RlPi4KICAgKi8KICBwdWJsaWMgYWJzdHJhY3QgaW50IGluZGV4T2YoWE1MU3RyaW5nIHN0cik7CgogIC8qKgogICAqIFJldHVybnMgdGhlIGluZGV4IHdpdGhpbiB0aGlzIHN0cmluZyBvZiB0aGUgZmlyc3Qgb2NjdXJyZW5jZSBvZiB0aGUKICAgKiBzcGVjaWZpZWQgc3Vic3RyaW5nLCBzdGFydGluZyBhdCB0aGUgc3BlY2lmaWVkIGluZGV4LiBUaGUgaW50ZWdlcgogICAqIHJldHVybmVkIGlzIHRoZSBzbWFsbGVzdCB2YWx1ZSA8aT5rPC9pPiBzdWNoIHRoYXQ6CiAgICogPGJsb2NrcXVvdGU+PHByZT4KICAgKiB0aGlzLnN0YXJ0c1dpdGgoc3RyLCA8aT5rPC9pPikgJiYgKDxpPms8L2k+ID49IGZyb21JbmRleCkKICAgKiA8L3ByZT48L2Jsb2NrcXVvdGU+CiAgICogaXMgPGNvZGU+dHJ1ZTwvY29kZT4uCiAgICogPHA+CiAgICogVGhlcmUgaXMgbm8gcmVzdHJpY3Rpb24gb24gdGhlIHZhbHVlIG9mIDxjb2RlPmZyb21JbmRleDwvY29kZT4uIElmCiAgICogaXQgaXMgbmVnYXRpdmUsIGl0IGhhcyB0aGUgc2FtZSBlZmZlY3QgYXMgaWYgaXQgd2VyZSB6ZXJvOiB0aGlzIGVudGlyZQogICAqIHN0cmluZyBtYXkgYmUgc2VhcmNoZWQuIElmIGl0IGlzIGdyZWF0ZXIgdGhhbiB0aGUgbGVuZ3RoIG9mIHRoaXMKICAgKiBzdHJpbmcsIGl0IGhhcyB0aGUgc2FtZSBlZmZlY3QgYXMgaWYgaXQgd2VyZSBlcXVhbCB0byB0aGUgbGVuZ3RoIG9mCiAgICogdGhpcyBzdHJpbmc6IDxjb2RlPi0xPC9jb2RlPiBpcyByZXR1cm5lZC4KICAgKgogICAqIEBwYXJhbSAgIHN0ciAgICAgICAgIHRoZSBzdWJzdHJpbmcgdG8gc2VhcmNoIGZvci4KICAgKiBAcGFyYW0gICBmcm9tSW5kZXggICB0aGUgaW5kZXggdG8gc3RhcnQgdGhlIHNlYXJjaCBmcm9tLgogICAqIEByZXR1cm4gIElmIHRoZSBzdHJpbmcgYXJndW1lbnQgb2NjdXJzIGFzIGEgc3Vic3RyaW5nIHdpdGhpbiB0aGlzCiAgICogICAgICAgICAgb2JqZWN0IGF0IGEgc3RhcnRpbmcgaW5kZXggbm8gc21hbGxlciB0aGFuCiAgICogICAgICAgICAgPGNvZGU+ZnJvbUluZGV4PC9jb2RlPiwgdGhlbiB0aGUgaW5kZXggb2YgdGhlIGZpcnN0IGNoYXJhY3RlcgogICAqICAgICAgICAgIG9mIHRoZSBmaXJzdCBzdWNoIHN1YnN0cmluZyBpcyByZXR1cm5lZC4gSWYgaXQgZG9lcyBub3Qgb2NjdXIKICAgKiAgICAgICAgICBhcyBhIHN1YnN0cmluZyBzdGFydGluZyBhdCA8Y29kZT5mcm9tSW5kZXg8L2NvZGU+IG9yIGJleW9uZCwKICAgKiAgICAgICAgICA8Y29kZT4tMTwvY29kZT4gaXMgcmV0dXJuZWQuCiAgICogQGV4Y2VwdGlvbiBqYXZhLmxhbmcuTnVsbFBvaW50ZXJFeGNlcHRpb24gaWYgPGNvZGU+c3RyPC9jb2RlPiBpcwogICAqICAgICAgICAgIDxjb2RlPm51bGw8L2NvZGU+CiAgICovCiAgcHVibGljIGFic3RyYWN0IGludCBpbmRleE9mKFN0cmluZyBzdHIsIGludCBmcm9tSW5kZXgpOwoKICAvKioKICAgKiBSZXR1cm5zIHRoZSBpbmRleCB3aXRoaW4gdGhpcyBzdHJpbmcgb2YgdGhlIHJpZ2h0bW9zdCBvY2N1cnJlbmNlCiAgICogb2YgdGhlIHNwZWNpZmllZCBzdWJzdHJpbmcuICBUaGUgcmlnaHRtb3N0IGVtcHR5IHN0cmluZyAiIiBpcwogICAqIGNvbnNpZGVyZWQgdG8gb2NjdXIgYXQgdGhlIGluZGV4IHZhbHVlIDxjb2RlPnRoaXMubGVuZ3RoKCk8L2NvZGU+LgogICAqIFRoZSByZXR1cm5lZCBpbmRleCBpcyB0aGUgbGFyZ2VzdCB2YWx1ZSA8aT5rPC9pPiBzdWNoIHRoYXQKICAgKiA8YmxvY2txdW90ZT48cHJlPgogICAqIHRoaXMuc3RhcnRzV2l0aChzdHIsIGspCiAgICogPC9wcmU+PC9ibG9ja3F1b3RlPgogICAqIGlzIHRydWUuCiAgICoKICAgKiBAcGFyYW0gICBzdHIgICB0aGUgc3Vic3RyaW5nIHRvIHNlYXJjaCBmb3IuCiAgICogQHJldHVybiAgaWYgdGhlIHN0cmluZyBhcmd1bWVudCBvY2N1cnMgb25lIG9yIG1vcmUgdGltZXMgYXMgYSBzdWJzdHJpbmcKICAgKiAgICAgICAgICB3aXRoaW4gdGhpcyBvYmplY3QsIHRoZW4gdGhlIGluZGV4IG9mIHRoZSBmaXJzdCBjaGFyYWN0ZXIgb2YKICAgKiAgICAgICAgICB0aGUgbGFzdCBzdWNoIHN1YnN0cmluZyBpcyByZXR1cm5lZC4gSWYgaXQgZG9lcyBub3Qgb2NjdXIgYXMKICAgKiAgICAgICAgICBhIHN1YnN0cmluZywgPGNvZGU+LTE8L2NvZGU+IGlzIHJldHVybmVkLgogICAqIEBleGNlcHRpb24gamF2YS5sYW5nLk51bGxQb2ludGVyRXhjZXB0aW9uICBpZiA8Y29kZT5zdHI8L2NvZGU+IGlzCiAgICogICAgICAgICAgPGNvZGU+bnVsbDwvY29kZT4uCiAgICovCiAgcHVibGljIGFic3RyYWN0IGludCBsYXN0SW5kZXhPZihTdHJpbmcgc3RyKTsKCiAgLyoqCiAgICogUmV0dXJucyB0aGUgaW5kZXggd2l0aGluIHRoaXMgc3RyaW5nIG9mIHRoZSBsYXN0IG9jY3VycmVuY2Ugb2YKICAgKiB0aGUgc3BlY2lmaWVkIHN1YnN0cmluZy4KICAgKgogICAqIEBwYXJhbSAgIHN0ciAgICAgICAgIHRoZSBzdWJzdHJpbmcgdG8gc2VhcmNoIGZvci4KICAgKiBAcGFyYW0gICBmcm9tSW5kZXggICB0aGUgaW5kZXggdG8gc3RhcnQgdGhlIHNlYXJjaCBmcm9tLiBUaGVyZSBpcyBubwogICAqICAgICAgICAgIHJlc3RyaWN0aW9uIG9uIHRoZSB2YWx1ZSBvZiBmcm9tSW5kZXguIElmIGl0IGlzIGdyZWF0ZXIgdGhhbgogICAqICAgICAgICAgIHRoZSBsZW5ndGggb2YgdGhpcyBzdHJpbmcsIGl0IGhhcyB0aGUgc2FtZSBlZmZlY3QgYXMgaWYgaXQKICAgKiAgICAgICAgICB3ZXJlIGVxdWFsIHRvIHRoZSBsZW5ndGggb2YgdGhpcyBzdHJpbmc6IHRoaXMgZW50aXJlIHN0cmluZwogICAqICAgICAgICAgIG1heSBiZSBzZWFyY2hlZC4gSWYgaXQgaXMgbmVnYXRpdmUsIGl0IGhhcyB0aGUgc2FtZSBlZmZlY3QKICAgKiAgICAgICAgICBhcyBpZiBpdCB3ZXJlIC0xOiAtMSBpcyByZXR1cm5lZC4KICAgKiBAcmV0dXJuICBJZiB0aGUgc3RyaW5nIGFyZ3VtZW50IG9jY3VycyBvbmUgb3IgbW9yZSB0aW1lcyBhcyBhIHN1YnN0cmluZwogICAqICAgICAgICAgIHdpdGhpbiB0aGlzIG9iamVjdCBhdCBhIHN0YXJ0aW5nIGluZGV4IG5vIGdyZWF0ZXIgdGhhbgogICAqICAgICAgICAgIDxjb2RlPmZyb21JbmRleDwvY29kZT4sIHRoZW4gdGhlIGluZGV4IG9mIHRoZSBmaXJzdCBjaGFyYWN0ZXIgb2YKICAgKiAgICAgICAgICB0aGUgbGFzdCBzdWNoIHN1YnN0cmluZyBpcyByZXR1cm5lZC4gSWYgaXQgZG9lcyBub3Qgb2NjdXIgYXMgYQogICAqICAgICAgICAgIHN1YnN0cmluZyBzdGFydGluZyBhdCA8Y29kZT5mcm9tSW5kZXg8L2NvZGU+IG9yIGVhcmxpZXIsCiAgICogICAgICAgICAgPGNvZGU+LTE8L2NvZGU+IGlzIHJldHVybmVkLgogICAqIEBleGNlcHRpb24gamF2YS5sYW5nLk51bGxQb2ludGVyRXhjZXB0aW9uIGlmIDxjb2RlPnN0cjwvY29kZT4gaXMKICAgKiAgICAgICAgICA8Y29kZT5udWxsPC9jb2RlPi4KICAgKi8KICBwdWJsaWMgYWJzdHJhY3QgaW50IGxhc3RJbmRleE9mKFN0cmluZyBzdHIsIGludCBmcm9tSW5kZXgpOwoKICAvKioKICAgKiBSZXR1cm5zIGEgbmV3IHN0cmluZyB0aGF0IGlzIGEgc3Vic3RyaW5nIG9mIHRoaXMgc3RyaW5nLiBUaGUKICAgKiBzdWJzdHJpbmcgYmVnaW5zIHdpdGggdGhlIGNoYXJhY3RlciBhdCB0aGUgc3BlY2lmaWVkIGluZGV4IGFuZAogICAqIGV4dGVuZHMgdG8gdGhlIGVuZCBvZiB0aGlzIHN0cmluZy4gPHA+CiAgICogRXhhbXBsZXM6CiAgICogPGJsb2NrcXVvdGU+PHByZT4KICAgKiAidW5oYXBweSIuc3Vic3RyaW5nKDIpIHJldHVybnMgImhhcHB5IgogICAqICJIYXJiaXNvbiIuc3Vic3RyaW5nKDMpIHJldHVybnMgImJpc29uIgogICAqICJlbXB0aW5lc3MiLnN1YnN0cmluZyg5KSByZXR1cm5zICIiIChhbiBlbXB0eSBzdHJpbmcpCiAgICogPC9wcmU+PC9ibG9ja3F1b3RlPgogICAqCiAgICogQHBhcmFtICAgICAgYmVnaW5JbmRleCAgIHRoZSBiZWdpbm5pbmcgaW5kZXgsIGluY2x1c2l2ZS4KICAgKiBAcmV0dXJuICAgICB0aGUgc3BlY2lmaWVkIHN1YnN0cmluZy4KICAgKiBAZXhjZXB0aW9uICBJbmRleE91dE9mQm91bmRzRXhjZXB0aW9uICBpZgogICAqICAgICAgICAgICAgIDxjb2RlPmJlZ2luSW5kZXg8L2NvZGU+IGlzIG5lZ2F0aXZlIG9yIGxhcmdlciB0aGFuIHRoZQogICAqICAgICAgICAgICAgIGxlbmd0aCBvZiB0aGlzIDxjb2RlPlN0cmluZzwvY29kZT4gb2JqZWN0LgogICAqLwogIHB1YmxpYyBhYnN0cmFjdCBYTUxTdHJpbmcgc3Vic3RyaW5nKGludCBiZWdpbkluZGV4KTsKCiAgLyoqCiAgICogUmV0dXJucyBhIG5ldyBzdHJpbmcgdGhhdCBpcyBhIHN1YnN0cmluZyBvZiB0aGlzIHN0cmluZy4gVGhlCiAgICogc3Vic3RyaW5nIGJlZ2lucyBhdCB0aGUgc3BlY2lmaWVkIDxjb2RlPmJlZ2luSW5kZXg8L2NvZGU+IGFuZAogICAqIGV4dGVuZHMgdG8gdGhlIGNoYXJhY3RlciBhdCBpbmRleCA8Y29kZT5lbmRJbmRleCAtIDE8L2NvZGU+LgogICAqIFRodXMgdGhlIGxlbmd0aCBvZiB0aGUgc3Vic3RyaW5nIGlzIDxjb2RlPmVuZEluZGV4LWJlZ2luSW5kZXg8L2NvZGU+LgogICAqCiAgICogQHBhcmFtICAgICAgYmVnaW5JbmRleCAgIHRoZSBiZWdpbm5pbmcgaW5kZXgsIGluY2x1c2l2ZS4KICAgKiBAcGFyYW0gICAgICBlbmRJbmRleCAgICAgdGhlIGVuZGluZyBpbmRleCwgZXhjbHVzaXZlLgogICAqIEByZXR1cm4gICAgIHRoZSBzcGVjaWZpZWQgc3Vic3RyaW5nLgogICAqIEBleGNlcHRpb24gIEluZGV4T3V0T2ZCb3VuZHNFeGNlcHRpb24gIGlmIHRoZQogICAqICAgICAgICAgICAgIDxjb2RlPmJlZ2luSW5kZXg8L2NvZGU+IGlzIG5lZ2F0aXZlLCBvcgogICAqICAgICAgICAgICAgIDxjb2RlPmVuZEluZGV4PC9jb2RlPiBpcyBsYXJnZXIgdGhhbiB0aGUgbGVuZ3RoIG9mCiAgICogICAgICAgICAgICAgdGhpcyA8Y29kZT5TdHJpbmc8L2NvZGU+IG9iamVjdCwgb3IKICAgKiAgICAgICAgICAgICA8Y29kZT5iZWdpbkluZGV4PC9jb2RlPiBpcyBsYXJnZXIgdGhhbgogICAqICAgICAgICAgICAgIDxjb2RlPmVuZEluZGV4PC9jb2RlPi4KICAgKi8KICBwdWJsaWMgYWJzdHJhY3QgWE1MU3RyaW5nIHN1YnN0cmluZyhpbnQgYmVnaW5JbmRleCwgaW50IGVuZEluZGV4KTsKCiAgLyoqCiAgICogQ29uY2F0ZW5hdGVzIHRoZSBzcGVjaWZpZWQgc3RyaW5nIHRvIHRoZSBlbmQgb2YgdGhpcyBzdHJpbmcuCiAgICoKICAgKiBAcGFyYW0gICBzdHIgICB0aGUgPGNvZGU+U3RyaW5nPC9jb2RlPiB0aGF0IGlzIGNvbmNhdGVuYXRlZCB0byB0aGUgZW5kCiAgICogICAgICAgICAgICAgICAgb2YgdGhpcyA8Y29kZT5TdHJpbmc8L2NvZGU+LgogICAqIEByZXR1cm4gIGEgc3RyaW5nIHRoYXQgcmVwcmVzZW50cyB0aGUgY29uY2F0ZW5hdGlvbiBvZiB0aGlzIG9iamVjdCdzCiAgICogICAgICAgICAgY2hhcmFjdGVycyBmb2xsb3dlZCBieSB0aGUgc3RyaW5nIGFyZ3VtZW50J3MgY2hhcmFjdGVycy4KICAgKiBAZXhjZXB0aW9uIGphdmEubGFuZy5OdWxsUG9pbnRlckV4Y2VwdGlvbiBpZiA8Y29kZT5zdHI8L2NvZGU+IGlzCiAgICogICAgICAgICAgPGNvZGU+bnVsbDwvY29kZT4uCiAgICovCiAgcHVibGljIGFic3RyYWN0IFhNTFN0cmluZyBjb25jYXQoU3RyaW5nIHN0cik7CgogIC8qKgogICAqIENvbnZlcnRzIGFsbCBvZiB0aGUgY2hhcmFjdGVycyBpbiB0aGlzIDxjb2RlPlN0cmluZzwvY29kZT4gdG8gbG93ZXIKICAgKiBjYXNlIHVzaW5nIHRoZSBydWxlcyBvZiB0aGUgZ2l2ZW4gPGNvZGU+TG9jYWxlPC9jb2RlPi4KICAgKgogICAqIEBwYXJhbSBsb2NhbGUgdXNlIHRoZSBjYXNlIHRyYW5zZm9ybWF0aW9uIHJ1bGVzIGZvciB0aGlzIGxvY2FsZQogICAqIEByZXR1cm4gdGhlIFN0cmluZywgY29udmVydGVkIHRvIGxvd2VyY2FzZS4KICAgKiBAc2VlICAgICBqYXZhLmxhbmcuQ2hhcmFjdGVyI3RvTG93ZXJDYXNlKGNoYXIpCiAgICogQHNlZSAgICAgamF2YS5sYW5nLlN0cmluZyN0b1VwcGVyQ2FzZShMb2NhbGUpCiAgICovCiAgcHVibGljIGFic3RyYWN0IFhNTFN0cmluZyB0b0xvd2VyQ2FzZShMb2NhbGUgbG9jYWxlKTsKCiAgLyoqCiAgICogQ29udmVydHMgYWxsIG9mIHRoZSBjaGFyYWN0ZXJzIGluIHRoaXMgPGNvZGU+U3RyaW5nPC9jb2RlPiB0byBsb3dlcgogICAqIGNhc2UgdXNpbmcgdGhlIHJ1bGVzIG9mIHRoZSBkZWZhdWx0IGxvY2FsZSwgd2hpY2ggaXMgcmV0dXJuZWQKICAgKiBieSA8Y29kZT5Mb2NhbGUuZ2V0RGVmYXVsdDwvY29kZT4uCiAgICogPHA+CiAgICoKICAgKiBAcmV0dXJuICB0aGUgc3RyaW5nLCBjb252ZXJ0ZWQgdG8gbG93ZXJjYXNlLgogICAqIEBzZWUgICAgIGphdmEubGFuZy5DaGFyYWN0ZXIjdG9Mb3dlckNhc2UoY2hhcikKICAgKiBAc2VlICAgICBqYXZhLmxhbmcuU3RyaW5nI3RvTG93ZXJDYXNlKExvY2FsZSkKICAgKi8KICBwdWJsaWMgYWJzdHJhY3QgWE1MU3RyaW5nIHRvTG93ZXJDYXNlKCk7CgogIC8qKgogICAqIENvbnZlcnRzIGFsbCBvZiB0aGUgY2hhcmFjdGVycyBpbiB0aGlzIDxjb2RlPlN0cmluZzwvY29kZT4gdG8gdXBwZXIKICAgKiBjYXNlIHVzaW5nIHRoZSBydWxlcyBvZiB0aGUgZ2l2ZW4gbG9jYWxlLgogICAqIEBwYXJhbSBsb2NhbGUgdXNlIHRoZSBjYXNlIHRyYW5zZm9ybWF0aW9uIHJ1bGVzIGZvciB0aGlzIGxvY2FsZQogICAqIEByZXR1cm4gdGhlIFN0cmluZywgY29udmVydGVkIHRvIHVwcGVyY2FzZS4KICAgKiBAc2VlICAgICBqYXZhLmxhbmcuQ2hhcmFjdGVyI3RvVXBwZXJDYXNlKGNoYXIpCiAgICogQHNlZSAgICAgamF2YS5sYW5nLlN0cmluZyN0b0xvd2VyQ2FzZShMb2NhbGUpCiAgICovCiAgcHVibGljIGFic3RyYWN0IFhNTFN0cmluZyB0b1VwcGVyQ2FzZShMb2NhbGUgbG9jYWxlKTsKCiAgLyoqCiAgICogQ29udmVydHMgYWxsIG9mIHRoZSBjaGFyYWN0ZXJzIGluIHRoaXMgPGNvZGU+U3RyaW5nPC9jb2RlPiB0byB1cHBlcgogICAqIGNhc2UgdXNpbmcgdGhlIHJ1bGVzIG9mIHRoZSBkZWZhdWx0IGxvY2FsZSwgd2hpY2ggaXMgcmV0dXJuZWQKICAgKiBieSA8Y29kZT5Mb2NhbGUuZ2V0RGVmYXVsdDwvY29kZT4uCiAgICoKICAgKiA8cD4KICAgKiBJZiBubyBjaGFyYWN0ZXIgaW4gdGhpcyBzdHJpbmcgaGFzIGEgZGlmZmVyZW50IHVwcGVyY2FzZSB2ZXJzaW9uLAogICAqIGJhc2VkIG9uIGNhbGxpbmcgdGhlIDxjb2RlPnRvVXBwZXJDYXNlPC9jb2RlPiBtZXRob2QgZGVmaW5lZCBieQogICAqIDxjb2RlPkNoYXJhY3RlcjwvY29kZT4sIHRoZW4gdGhlIG9yaWdpbmFsIHN0cmluZyBpcyByZXR1cm5lZC4KICAgKiA8cD4KICAgKiBPdGhlcndpc2UsIHRoaXMgbWV0aG9kIGNyZWF0ZXMgYSBuZXcgPGNvZGU+U3RyaW5nPC9jb2RlPiBvYmplY3QKICAgKiByZXByZXNlbnRpbmcgYSBjaGFyYWN0ZXIgc2VxdWVuY2UgaWRlbnRpY2FsIGluIGxlbmd0aCB0byB0aGUKICAgKiBjaGFyYWN0ZXIgc2VxdWVuY2UgcmVwcmVzZW50ZWQgYnkgdGhpcyA8Y29kZT5TdHJpbmc8L2NvZGU+IG9iamVjdCBhbmQKICAgKiB3aXRoIGV2ZXJ5IGNoYXJhY3RlciBlcXVhbCB0byB0aGUgcmVzdWx0IG9mIGFwcGx5aW5nIHRoZSBtZXRob2QKICAgKiA8Y29kZT5DaGFyYWN0ZXIudG9VcHBlckNhc2U8L2NvZGU+IHRvIHRoZSBjb3JyZXNwb25kaW5nIGNoYXJhY3RlciBvZgogICAqIHRoaXMgPGNvZGU+U3RyaW5nPC9jb2RlPiBvYmplY3QuIDxwPgogICAqIEV4YW1wbGVzOgogICAqIDxibG9ja3F1b3RlPjxwcmU+CiAgICogIkZhaHJ2ZXJnbvxnZW4iLnRvVXBwZXJDYXNlKCkgcmV0dXJucyAiRkFIUlZFUkdO3EdFTiIKICAgKiAiVmlzaXQgTGp1YmluamUhIi50b1VwcGVyQ2FzZSgpIHJldHVybnMgIlZJU0lUIExKVUJJTkpFISIKICAgKiA8L3ByZT48L2Jsb2NrcXVvdGU+CiAgICoKICAgKiBAcmV0dXJuICB0aGUgc3RyaW5nLCBjb252ZXJ0ZWQgdG8gdXBwZXJjYXNlLgogICAqIEBzZWUgICAgIGphdmEubGFuZy5DaGFyYWN0ZXIjdG9VcHBlckNhc2UoY2hhcikKICAgKiBAc2VlICAgICBqYXZhLmxhbmcuU3RyaW5nI3RvVXBwZXJDYXNlKExvY2FsZSkKICAgKi8KICBwdWJsaWMgYWJzdHJhY3QgWE1MU3RyaW5nIHRvVXBwZXJDYXNlKCk7CgogIC8qKgogICAqIFJlbW92ZXMgd2hpdGUgc3BhY2UgZnJvbSBib3RoIGVuZHMgb2YgdGhpcyBzdHJpbmcuCiAgICogPHA+CiAgICogSWYgdGhpcyA8Y29kZT5TdHJpbmc8L2NvZGU+IG9iamVjdCByZXByZXNlbnRzIGFuIGVtcHR5IGNoYXJhY3RlcgogICAqIHNlcXVlbmNlLCBvciB0aGUgZmlyc3QgYW5kIGxhc3QgY2hhcmFjdGVycyBvZiBjaGFyYWN0ZXIgc2VxdWVuY2UKICAgKiByZXByZXNlbnRlZCBieSB0aGlzIDxjb2RlPlN0cmluZzwvY29kZT4gb2JqZWN0IGJvdGggaGF2ZSBjb2RlcwogICAqIGdyZWF0ZXIgdGhhbiA8Y29kZT4nJiM5Mjt1MDAyMCc8L2NvZGU+ICh0aGUgc3BhY2UgY2hhcmFjdGVyKSwgdGhlbiBhCiAgICogcmVmZXJlbmNlIHRvIHRoaXMgPGNvZGU+U3RyaW5nPC9jb2RlPiBvYmplY3QgaXMgcmV0dXJuZWQuCiAgICogPHA+CiAgICogT3RoZXJ3aXNlLCBpZiB0aGVyZSBpcyBubyBjaGFyYWN0ZXIgd2l0aCBhIGNvZGUgZ3JlYXRlciB0aGFuCiAgICogPGNvZGU+JyYjOTI7dTAwMjAnPC9jb2RlPiBpbiB0aGUgc3RyaW5nLCB0aGVuIGEgbmV3CiAgICogPGNvZGU+U3RyaW5nPC9jb2RlPiBvYmplY3QgcmVwcmVzZW50aW5nIGFuIGVtcHR5IHN0cmluZyBpcyBjcmVhdGVkCiAgICogYW5kIHJldHVybmVkLgogICAqIDxwPgogICAqIE90aGVyd2lzZSwgbGV0IDxpPms8L2k+IGJlIHRoZSBpbmRleCBvZiB0aGUgZmlyc3QgY2hhcmFjdGVyIGluIHRoZQogICAqIHN0cmluZyB3aG9zZSBjb2RlIGlzIGdyZWF0ZXIgdGhhbiA8Y29kZT4nJiM5Mjt1MDAyMCc8L2NvZGU+LCBhbmQgbGV0CiAgICogPGk+bTwvaT4gYmUgdGhlIGluZGV4IG9mIHRoZSBsYXN0IGNoYXJhY3RlciBpbiB0aGUgc3RyaW5nIHdob3NlIGNvZGUKICAgKiBpcyBncmVhdGVyIHRoYW4gPGNvZGU+JyYjOTI7dTAwMjAnPC9jb2RlPi4gQSBuZXcgPGNvZGU+U3RyaW5nPC9jb2RlPgogICAqIG9iamVjdCBpcyBjcmVhdGVkLCByZXByZXNlbnRpbmcgdGhlIHN1YnN0cmluZyBvZiB0aGlzIHN0cmluZyB0aGF0CiAgICogYmVnaW5zIHdpdGggdGhlIGNoYXJhY3RlciBhdCBpbmRleCA8aT5rPC9pPiBhbmQgZW5kcyB3aXRoIHRoZQogICAqIGNoYXJhY3RlciBhdCBpbmRleCA8aT5tPC9pPi10aGF0IGlzLCB0aGUgcmVzdWx0IG9mCiAgICogPGNvZGU+dGhpcy5zdWJzdHJpbmcoPGk+azwvaT4sJm5ic3A7PGk+bTwvaT4rMSk8L2NvZGU+LgogICAqIDxwPgogICAqIFRoaXMgbWV0aG9kIG1heSBiZSB1c2VkIHRvIHRyaW0KICAgKiB7QGxpbmsgQ2hhcmFjdGVyI2lzU3BhY2UoY2hhcikgd2hpdGVzcGFjZX0gZnJvbSB0aGUgYmVnaW5uaW5nIGFuZCBlbmQKICAgKiBvZiBhIHN0cmluZzsgaW4gZmFjdCwgaXQgdHJpbXMgYWxsIEFTQ0lJIGNvbnRyb2wgY2hhcmFjdGVycyBhcyB3ZWxsLgogICAqCiAgICogQHJldHVybiAgdGhpcyBzdHJpbmcsIHdpdGggd2hpdGUgc3BhY2UgcmVtb3ZlZCBmcm9tIHRoZSBmcm9udCBhbmQgZW5kLgogICAqLwogIHB1YmxpYyBhYnN0cmFjdCBYTUxTdHJpbmcgdHJpbSgpOwoKICAvKioKICAgKiBUaGlzIG9iamVjdCAod2hpY2ggaXMgYWxyZWFkeSBhIHN0cmluZyEpIGlzIGl0c2VsZiByZXR1cm5lZC4KICAgKgogICAqIEByZXR1cm4gIHRoZSBzdHJpbmcgaXRzZWxmLgogICAqLwogIHB1YmxpYyBhYnN0cmFjdCBTdHJpbmcgdG9TdHJpbmcoKTsKICAKICAvKioKICAgKiBUZWxsIGlmIHRoaXMgb2JqZWN0IGNvbnRhaW5zIGEgamF2YSBTdHJpbmcgb2JqZWN0LgogICAqIAogICAqIEByZXR1cm4gdHJ1ZSBpZiB0aGlzIFhNTFN0cmluZyBjYW4gcmV0dXJuIGEgc3RyaW5nIHdpdGhvdXQgY3JlYXRpbmcgb25lLgogICAqLwogIHB1YmxpYyBhYnN0cmFjdCBib29sZWFuIGhhc1N0cmluZygpOwogIAogIC8qKgogICAqIENvbnZlcnQgYSBzdHJpbmcgdG8gYSBkb3VibGUgLS0gQWxsb3dlZCBpbnB1dCBpcyBpbiBmaXhlZAogICAqIG5vdGF0aW9uIGRkZC5mZmYuCiAgICoKICAgKiBAcmV0dXJuIEEgZG91YmxlIHZhbHVlIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBzdHJpbmcsIG9yIHJldHVybiBEb3VibGUuTmFOIAogICAqIGlmIHRoZSBzdHJpbmcgY2FuIG5vdCBiZSBjb252ZXJ0ZWQuCiAgICovCiAgcHVibGljIGRvdWJsZSB0b0RvdWJsZSgpOwp9Cg==