LyoKICogVGhlIEFwYWNoZSBTb2Z0d2FyZSBMaWNlbnNlLCBWZXJzaW9uIDEuMQogKgogKgogKiBDb3B5cmlnaHQgKGMpIDE5OTkgVGhlIEFwYWNoZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLiAgQWxsIHJpZ2h0cyAKICogcmVzZXJ2ZWQuCiAqCiAqIFJlZGlzdHJpYnV0aW9uIGFuZCB1c2UgaW4gc291cmNlIGFuZCBiaW5hcnkgZm9ybXMsIHdpdGggb3Igd2l0aG91dAogKiBtb2RpZmljYXRpb24sIGFyZSBwZXJtaXR0ZWQgcHJvdmlkZWQgdGhhdCB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnMKICogYXJlIG1ldDoKICoKICogMS4gUmVkaXN0cmlidXRpb25zIG9mIHNvdXJjZSBjb2RlIG11c3QgcmV0YWluIHRoZSBhYm92ZSBjb3B5cmlnaHQKICogICAgbm90aWNlLCB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyLiAKICoKICogMi4gUmVkaXN0cmlidXRpb25zIGluIGJpbmFyeSBmb3JtIG11c3QgcmVwcm9kdWNlIHRoZSBhYm92ZSBjb3B5cmlnaHQKICogICAgbm90aWNlLCB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyIGluCiAqICAgIHRoZSBkb2N1bWVudGF0aW9uIGFuZC9vciBvdGhlciBtYXRlcmlhbHMgcHJvdmlkZWQgd2l0aCB0aGUKICogICAgZGlzdHJpYnV0aW9uLgogKgogKiAzLiBUaGUgZW5kLXVzZXIgZG9jdW1lbnRhdGlvbiBpbmNsdWRlZCB3aXRoIHRoZSByZWRpc3RyaWJ1dGlvbiwKICogICAgaWYgYW55LCBtdXN0IGluY2x1ZGUgdGhlIGZvbGxvd2luZyBhY2tub3dsZWRnbWVudDogIAogKiAgICAgICAiVGhpcyBwcm9kdWN0IGluY2x1ZGVzIHNvZnR3YXJlIGRldmVsb3BlZCBieSB0aGUKICogICAgICAgIEFwYWNoZSBTb2Z0d2FyZSBGb3VuZGF0aW9uIChodHRwOi8vd3d3LmFwYWNoZS5vcmcvKS4iCiAqICAgIEFsdGVybmF0ZWx5LCB0aGlzIGFja25vd2xlZGdtZW50IG1heSBhcHBlYXIgaW4gdGhlIHNvZnR3YXJlIGl0c2VsZiwKICogICAgaWYgYW5kIHdoZXJldmVyIHN1Y2ggdGhpcmQtcGFydHkgYWNrbm93bGVkZ21lbnRzIG5vcm1hbGx5IGFwcGVhci4KICoKICogNC4gVGhlIG5hbWVzICJYYWxhbiIgYW5kICJBcGFjaGUgU29mdHdhcmUgRm91bmRhdGlvbiIgbXVzdAogKiAgICBub3QgYmUgdXNlZCB0byBlbmRvcnNlIG9yIHByb21vdGUgcHJvZHVjdHMgZGVyaXZlZCBmcm9tIHRoaXMKICogICAgc29mdHdhcmUgd2l0aG91dCBwcmlvciB3cml0dGVuIHBlcm1pc3Npb24uIEZvciB3cml0dGVuIAogKiAgICBwZXJtaXNzaW9uLCBwbGVhc2UgY29udGFjdCBhcGFjaGVAYXBhY2hlLm9yZy4KICoKICogNS4gUHJvZHVjdHMgZGVyaXZlZCBmcm9tIHRoaXMgc29mdHdhcmUgbWF5IG5vdCBiZSBjYWxsZWQgIkFwYWNoZSIsCiAqICAgIG5vciBtYXkgIkFwYWNoZSIgYXBwZWFyIGluIHRoZWlyIG5hbWUsIHdpdGhvdXQgcHJpb3Igd3JpdHRlbgogKiAgICBwZXJtaXNzaW9uIG9mIHRoZSBBcGFjaGUgU29mdHdhcmUgRm91bmRhdGlvbi4KICoKICogVEhJUyBTT0ZUV0FSRSBJUyBQUk9WSURFRCBgYEFTIElTJycgQU5EIEFOWSBFWFBSRVNTRUQgT1IgSU1QTElFRAogKiBXQVJSQU5USUVTLCBJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgVEhFIElNUExJRUQgV0FSUkFOVElFUwogKiBPRiBNRVJDSEFOVEFCSUxJVFkgQU5EIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFSRQogKiBESVNDTEFJTUVELiAgSU4gTk8gRVZFTlQgU0hBTEwgVEhFIEFQQUNIRSBTT0ZUV0FSRSBGT1VOREFUSU9OIE9SCiAqIElUUyBDT05UUklCVVRPUlMgQkUgTElBQkxFIEZPUiBBTlkgRElSRUNULCBJTkRJUkVDVCwgSU5DSURFTlRBTCwKICogU1BFQ0lBTCwgRVhFTVBMQVJZLCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVMgKElOQ0xVRElORywgQlVUIE5PVAogKiBMSU1JVEVEIFRPLCBQUk9DVVJFTUVOVCBPRiBTVUJTVElUVVRFIEdPT0RTIE9SIFNFUlZJQ0VTOyBMT1NTIE9GCiAqIFVTRSwgREFUQSwgT1IgUFJPRklUUzsgT1IgQlVTSU5FU1MgSU5URVJSVVBUSU9OKSBIT1dFVkVSIENBVVNFRCBBTkQKICogT04gQU5ZIFRIRU9SWSBPRiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQ09OVFJBQ1QsIFNUUklDVCBMSUFCSUxJVFksCiAqIE9SIFRPUlQgKElOQ0xVRElORyBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSkgQVJJU0lORyBJTiBBTlkgV0FZIE9VVAogKiBPRiBUSEUgVVNFIE9GIFRISVMgU09GVFdBUkUsIEVWRU4gSUYgQURWSVNFRCBPRiBUSEUgUE9TU0lCSUxJVFkgT0YKICogU1VDSCBEQU1BR0UuCiAqID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CiAqCiAqIFRoaXMgc29mdHdhcmUgY29uc2lzdHMgb2Ygdm9sdW50YXJ5IGNvbnRyaWJ1dGlvbnMgbWFkZSBieSBtYW55CiAqIGluZGl2aWR1YWxzIG9uIGJlaGFsZiBvZiB0aGUgQXBhY2hlIFNvZnR3YXJlIEZvdW5kYXRpb24gYW5kIHdhcwogKiBvcmlnaW5hbGx5IGJhc2VkIG9uIHNvZnR3YXJlIGNvcHlyaWdodCAoYykgMTk5OSwgTG90dXMKICogRGV2ZWxvcG1lbnQgQ29ycG9yYXRpb24uLCBodHRwOi8vd3d3LmxvdHVzLmNvbS4gIEZvciBtb3JlCiAqIGluZm9ybWF0aW9uIG9uIHRoZSBBcGFjaGUgU29mdHdhcmUgRm91bmRhdGlvbiwgcGxlYXNlIHNlZQogKiA8aHR0cDovL3d3dy5hcGFjaGUub3JnLz4uCiAqLwpwYWNrYWdlIG9yZy5hcGFjaGUueHBhdGgub2JqZWN0czsKCi8vaW1wb3J0IG9yZy53M2MuZG9tLio7CmltcG9ydCBqYXZhLnV0aWwuTG9jYWxlOwoKaW1wb3J0IG9yZy5hcGFjaGUueG1sLmR0bS5EVE07CmltcG9ydCBvcmcuYXBhY2hlLnhtbC51dGlscy5YTUxDaGFyYWN0ZXJSZWNvZ25pemVyOwppbXBvcnQgb3JnLmFwYWNoZS54bWwudXRpbHMuWE1MU3RyaW5nOwppbXBvcnQgb3JnLmFwYWNoZS54bWwudXRpbHMuWE1MU3RyaW5nRmFjdG9yeTsKaW1wb3J0IG9yZy5hcGFjaGUueHBhdGguRXhwcmVzc2lvbk93bmVyOwppbXBvcnQgb3JnLmFwYWNoZS54cGF0aC5YUGF0aENvbnRleHQ7CmltcG9ydCBvcmcuYXBhY2hlLnhwYXRoLlhQYXRoVmlzaXRvcjsKaW1wb3J0IG9yZy54bWwuc2F4LkNvbnRlbnRIYW5kbGVyOwppbXBvcnQgb3JnLnhtbC5zYXguU0FYRXhjZXB0aW9uOwppbXBvcnQgb3JnLnhtbC5zYXguZXh0LkxleGljYWxIYW5kbGVyOwoKLyoqCiAqIDxtZXRhIG5hbWU9InVzYWdlIiBjb250ZW50PSJnZW5lcmFsIi8+CiAqIFRoaXMgY2xhc3MgcmVwcmVzZW50cyBhbiBYUGF0aCBzdHJpbmcgb2JqZWN0LCBhbmQgaXMgY2FwYWJsZSBvZgogKiBjb252ZXJ0aW5nIHRoZSBzdHJpbmcgdG8gb3RoZXIgdHlwZXMsIHN1Y2ggYXMgYSBudW1iZXIuCiAqLwpwdWJsaWMgY2xhc3MgWFN0cmluZyBleHRlbmRzIFhPYmplY3QgaW1wbGVtZW50cyBYTUxTdHJpbmcKewoKICAvKiogRW1wdHkgc3RyaW5nIFhTdHJpbmcgb2JqZWN0ICovCiAgcHVibGljIHN0YXRpYyBYU3RyaW5nIEVNUFRZU1RSSU5HID0gbmV3IFhTdHJpbmcoIiIpOwoKICAvKioKICAgKiBDb25zdHJ1Y3QgYSBYU3RyaW5nIG9iamVjdC4gIFRoaXMgY29uc3RydWN0b3IgZXhpc3RzIGZvciBkZXJpdmVkIGNsYXNzZXMuCiAgICoKICAgKiBAcGFyYW0gdmFsIFN0cmluZyBvYmplY3QgdGhpcyB3aWxsIHdyYXAuCiAgICovCiAgcHJvdGVjdGVkIFhTdHJpbmcoT2JqZWN0IHZhbCkKICB7CiAgICBzdXBlcih2YWwpOwogIH0KCiAgLyoqCiAgICogQ29uc3RydWN0IGEgWE5vZGVTZXQgb2JqZWN0LgogICAqCiAgICogQHBhcmFtIHZhbCBTdHJpbmcgb2JqZWN0IHRoaXMgd2lsbCB3cmFwLgogICAqLwogIHB1YmxpYyBYU3RyaW5nKFN0cmluZyB2YWwpCiAgewogICAgc3VwZXIodmFsKTsKICB9CgogIC8qKgogICAqIFRlbGwgdGhhdCB0aGlzIGlzIGEgQ0xBU1NfU1RSSU5HLgogICAqCiAgICogQHJldHVybiB0eXBlIENMQVNTX1NUUklORwogICAqLwogIHB1YmxpYyBpbnQgZ2V0VHlwZSgpCiAgewogICAgcmV0dXJuIENMQVNTX1NUUklORzsKICB9CgogIC8qKgogICAqIEdpdmVuIGEgcmVxdWVzdCB0eXBlLCByZXR1cm4gdGhlIGVxdWl2YWxlbnQgc3RyaW5nLgogICAqIEZvciBkaWFnbm9zdGljIHB1cnBvc2VzLgogICAqCiAgICogQHJldHVybiB0eXBlIHN0cmluZyAiI1NUUklORyIKICAgKi8KICBwdWJsaWMgU3RyaW5nIGdldFR5cGVTdHJpbmcoKQogIHsKICAgIHJldHVybiAiI1NUUklORyI7CiAgfQoKICAvKioKICAgKiBUZWxsIGlmIHRoaXMgb2JqZWN0IGNvbnRhaW5zIGEgamF2YSBTdHJpbmcgb2JqZWN0LgogICAqCiAgICogQHJldHVybiB0cnVlIGlmIHRoaXMgWE1MU3RyaW5nIGNhbiByZXR1cm4gYSBzdHJpbmcgd2l0aG91dCBjcmVhdGluZyBvbmUuCiAgICovCiAgcHVibGljIGJvb2xlYW4gaGFzU3RyaW5nKCkKICB7CiAgICByZXR1cm4gdHJ1ZTsKICB9CgogIC8qKgogICAqIENhc3QgcmVzdWx0IG9iamVjdCB0byBhIG51bWJlci4KICAgKgogICAqIEByZXR1cm4gMC4wIGlmIHRoaXMgc3RyaW5nIGlzIG51bGwsIG51bWVyaWMgdmFsdWUgb2YgdGhpcyBzdHJpbmcKICAgKiBvciBOYU4KICAgKi8KICBwdWJsaWMgZG91YmxlIG51bSgpCiAgewogICAgcmV0dXJuIHRvRG91YmxlKCk7CiAgfQoKICAvKioKICAgKiBDb252ZXJ0IGEgc3RyaW5nIHRvIGEgZG91YmxlIC0tIEFsbG93ZWQgaW5wdXQgaXMgaW4gZml4ZWQKICAgKiBub3RhdGlvbiBkZGQuZmZmLgogICAqCiAgICogQHJldHVybiBBIGRvdWJsZSB2YWx1ZSByZXByZXNlbnRhdGlvbiBvZiB0aGUgc3RyaW5nLCBvciByZXR1cm4gRG91YmxlLk5hTgogICAqIGlmIHRoZSBzdHJpbmcgY2FuIG5vdCBiZSBjb252ZXJ0ZWQuCiAgICovCiAgcHVibGljIGRvdWJsZSB0b0RvdWJsZSgpCiAgewogICAgaW50IGVuZCA9IGxlbmd0aCgpOwogICAgCiAgICBpZigwID09IGVuZCkKICAgICAgcmV0dXJuIERvdWJsZS5OYU47CgogICAgZG91YmxlIHJlc3VsdCA9IDAuMDsKICAgIGludCBzdGFydCA9IDA7CiAgICBpbnQgcHVuY3RQb3MgPSBlbmQtMTsKCiAgICAvLyBTY2FuIHRvIGZpcnN0IHdoaXRlc3BhY2UgY2hhcmFjdGVyLgogICAgZm9yIChpbnQgaSA9IHN0YXJ0OyBpIDwgZW5kOyBpKyspCiAgICB7CiAgICAgIGNoYXIgYyA9IGNoYXJBdChpKTsKCiAgICAgIGlmICghWE1MQ2hhcmFjdGVyUmVjb2duaXplci5pc1doaXRlU3BhY2UoYykpCiAgICAgIHsKICAgICAgICBicmVhazsKICAgICAgfQogICAgICBlbHNlCiAgICAgICAgc3RhcnQrKzsKICAgIH0KCiAgICBkb3VibGUgc2lnbiA9IDEuMDsKCiAgICBpZiAoc3RhcnQgPCBlbmQgJiYgY2hhckF0KHN0YXJ0KSA9PSAnLScpCiAgICB7CiAgICAgIHNpZ24gPSAtMS4wOwoKICAgICAgc3RhcnQrKzsKICAgIH0KCiAgICBpbnQgZGlnaXRzRm91bmQgPSAwOwoKICAgIGZvciAoaW50IGkgPSBzdGFydDsgaSA8IGVuZDsgaSsrKSAgLy8gcGFyc2UgdGhlIHN0cmluZyBmcm9tIGxlZnQgdG8gcmlnaHQgY29udmVydGluZyB0aGUgaW50ZWdlciBwYXJ0CiAgICB7CiAgICAgIGNoYXIgYyA9IGNoYXJBdChpKTsKCiAgICAgIGlmIChjICE9ICcuJykKICAgICAgewogICAgICAgIGlmIChYTUxDaGFyYWN0ZXJSZWNvZ25pemVyLmlzV2hpdGVTcGFjZShjKSkKICAgICAgICAgIGJyZWFrOwogICAgICAgIGVsc2UgaWYgKENoYXJhY3Rlci5pc0RpZ2l0KGMpKQogICAgICAgIHsKICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdCAqIDEwLjAgKyAoYyAtIDB4MzApOwoKICAgICAgICAgIGRpZ2l0c0ZvdW5kKys7CiAgICAgICAgfQogICAgICAgIGVsc2UKICAgICAgICB7CiAgICAgICAgICByZXR1cm4gRG91YmxlLk5hTjsKICAgICAgICB9CiAgICAgIH0KICAgICAgZWxzZQogICAgICB7CiAgICAgICAgcHVuY3RQb3MgPSBpOwoKICAgICAgICBicmVhazsKICAgICAgfQogICAgfQoKICAgIGlmIChjaGFyQXQocHVuY3RQb3MpID09ICcuJykgIC8vIHBhcnNlIHRoZSBzdHJpbmcgZnJvbSB0aGUgZW5kIHRvIHRoZSAnLicgY29udmVydGluZyB0aGUgZnJhY3Rpb25hbCBwYXJ0CiAgICB7CiAgICAgIGRvdWJsZSBmcmFjdFBhcnQgPSAwLjA7CgogICAgICBmb3IgKGludCBpID0gZW5kIC0gMTsgaSA+IHB1bmN0UG9zOyBpLS0pCiAgICAgIHsKICAgICAgICBjaGFyIGMgPSBjaGFyQXQoaSk7CgogICAgICAgIGlmIChYTUxDaGFyYWN0ZXJSZWNvZ25pemVyLmlzV2hpdGVTcGFjZShjKSkKICAgICAgICAgIGJyZWFrOwogICAgICAgIGVsc2UgaWYgKENoYXJhY3Rlci5pc0RpZ2l0KGMpKQogICAgICAgIHsKICAgICAgICAgIGZyYWN0UGFydCA9IGZyYWN0UGFydCAvIDEwLjAgKyAoYyAtIDB4MzApOwoKICAgICAgICAgIGRpZ2l0c0ZvdW5kKys7CiAgICAgICAgfQogICAgICAgIGVsc2UKICAgICAgICB7CiAgICAgICAgICByZXR1cm4gRG91YmxlLk5hTjsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHJlc3VsdCArPSBmcmFjdFBhcnQgLyAxMC4wOwogICAgfQoKICAgIGlmICgwID09IGRpZ2l0c0ZvdW5kKQogICAgICByZXR1cm4gRG91YmxlLk5hTjsKCiAgICByZXR1cm4gcmVzdWx0ICogc2lnbjsKICB9CgogIC8qKgogICAqIENhc3QgcmVzdWx0IG9iamVjdCB0byBhIGJvb2xlYW4uCiAgICoKICAgKiBAcmV0dXJuIFRydWUgaWYgdGhlIGxlbmd0aCBvZiB0aGlzIHN0cmluZyBvYmplY3QgaXMgZ3JlYXRlcgogICAqIHRoYW4gMC4KICAgKi8KICBwdWJsaWMgYm9vbGVhbiBib29sKCkKICB7CiAgICByZXR1cm4gc3RyKCkubGVuZ3RoKCkgPiAwOwogIH0KCiAgLyoqCiAgICogQ2FzdCByZXN1bHQgb2JqZWN0IHRvIGEgc3RyaW5nLgogICAqCiAgICogQHJldHVybiBUaGUgc3RyaW5nIHRoaXMgd3JhcHMgb3IgdGhlIGVtcHR5IHN0cmluZyBpZiBudWxsCiAgICovCiAgcHVibGljIFhNTFN0cmluZyB4c3RyKCkKICB7CiAgICByZXR1cm4gdGhpczsKICB9CgogIC8qKgogICAqIENhc3QgcmVzdWx0IG9iamVjdCB0byBhIHN0cmluZy4KICAgKgogICAqIEByZXR1cm4gVGhlIHN0cmluZyB0aGlzIHdyYXBzIG9yIHRoZSBlbXB0eSBzdHJpbmcgaWYgbnVsbAogICAqLwogIHB1YmxpYyBTdHJpbmcgc3RyKCkKICB7CiAgICByZXR1cm4gKG51bGwgIT0gbV9vYmopID8gKChTdHJpbmcpIG1fb2JqKSA6ICIiOwogIH0KCiAgLyoqCiAgICogQ2FzdCByZXN1bHQgb2JqZWN0IHRvIGEgcmVzdWx0IHRyZWUgZnJhZ21lbnQuCiAgICoKICAgKiBAcGFyYW0gc3VwcG9ydCBYcGF0aCBjb250ZXh0IHRvIHVzZSBmb3IgdGhlIGNvbnZlcnNpb24KICAgKgogICAqIEByZXR1cm4gQSBkb2N1bWVudCBmcmFnbWVudCB3aXRoIHRoaXMgc3RyaW5nIGFzIGEgY2hpbGQgbm9kZQogICAqLwogIHB1YmxpYyBpbnQgcnRmKFhQYXRoQ29udGV4dCBzdXBwb3J0KQogIHsKCiAgICBEVE0gZnJhZyA9IHN1cHBvcnQuY3JlYXRlRG9jdW1lbnRGcmFnbWVudCgpOwoKICAgIGZyYWcuYXBwZW5kVGV4dENoaWxkKHN0cigpKTsKCiAgICByZXR1cm4gZnJhZy5nZXREb2N1bWVudCgpOwogIH0KCiAgLyoqCiAgICogRGlyZWN0bHkgY2FsbCB0aGUKICAgKiBjaGFyYWN0ZXJzIG1ldGhvZCBvbiB0aGUgcGFzc2VkIENvbnRlbnRIYW5kbGVyIGZvciB0aGUKICAgKiBzdHJpbmctdmFsdWUuIE11bHRpcGxlIGNhbGxzIHRvIHRoZQogICAqIENvbnRlbnRIYW5kbGVyJ3MgY2hhcmFjdGVycyBtZXRob2RzIG1heSB3ZWxsIG9jY3VyIGZvciBhIHNpbmdsZSBjYWxsIHRvCiAgICogdGhpcyBtZXRob2QuCiAgICoKICAgKiBAcGFyYW0gY2ggQSBub24tbnVsbCByZWZlcmVuY2UgdG8gYSBDb250ZW50SGFuZGxlci4KICAgKgogICAqIEB0aHJvd3Mgb3JnLnhtbC5zYXguU0FYRXhjZXB0aW9uCiAgICovCiAgcHVibGljIHZvaWQgZGlzcGF0Y2hDaGFyYWN0ZXJzRXZlbnRzKG9yZy54bWwuc2F4LkNvbnRlbnRIYW5kbGVyIGNoKQogICAgICAgICAgdGhyb3dzIG9yZy54bWwuc2F4LlNBWEV4Y2VwdGlvbgogIHsKCiAgICBTdHJpbmcgc3RyID0gc3RyKCk7CgogICAgY2guY2hhcmFjdGVycyhzdHIudG9DaGFyQXJyYXkoKSwgMCwgc3RyLmxlbmd0aCgpKTsKICB9CgogIC8qKgogICAqIERpcmVjdGx5IGNhbGwgdGhlCiAgICogY29tbWVudCBtZXRob2Qgb24gdGhlIHBhc3NlZCBMZXhpY2FsSGFuZGxlciBmb3IgdGhlCiAgICogc3RyaW5nLXZhbHVlLgogICAqCiAgICogQHBhcmFtIGxoIEEgbm9uLW51bGwgcmVmZXJlbmNlIHRvIGEgTGV4aWNhbEhhbmRsZXIuCiAgICoKICAgKiBAdGhyb3dzIG9yZy54bWwuc2F4LlNBWEV4Y2VwdGlvbgogICAqLwogIHB1YmxpYyB2b2lkIGRpc3BhdGNoQXNDb21tZW50KG9yZy54bWwuc2F4LmV4dC5MZXhpY2FsSGFuZGxlciBsaCkKICAgICAgICAgIHRocm93cyBvcmcueG1sLnNheC5TQVhFeGNlcHRpb24KICB7CgogICAgU3RyaW5nIHN0ciA9IHN0cigpOwoKICAgIGxoLmNvbW1lbnQoc3RyLnRvQ2hhckFycmF5KCksIDAsIHN0ci5sZW5ndGgoKSk7CiAgfQoKICAvKioKICAgKiBSZXR1cm5zIHRoZSBsZW5ndGggb2YgdGhpcyBzdHJpbmcuCiAgICoKICAgKiBAcmV0dXJuICB0aGUgbGVuZ3RoIG9mIHRoZSBzZXF1ZW5jZSBvZiBjaGFyYWN0ZXJzIHJlcHJlc2VudGVkIGJ5IHRoaXMKICAgKiAgICAgICAgICBvYmplY3QuCiAgICovCiAgcHVibGljIGludCBsZW5ndGgoKQogIHsKICAgIHJldHVybiBzdHIoKS5sZW5ndGgoKTsKICB9CgogIC8qKgogICAqIFJldHVybnMgdGhlIGNoYXJhY3RlciBhdCB0aGUgc3BlY2lmaWVkIGluZGV4LiBBbiBpbmRleCByYW5nZXMKICAgKiBmcm9tIDxjb2RlPjA8L2NvZGU+IHRvIDxjb2RlPmxlbmd0aCgpIC0gMTwvY29kZT4uIFRoZSBmaXJzdCBjaGFyYWN0ZXIKICAgKiBvZiB0aGUgc2VxdWVuY2UgaXMgYXQgaW5kZXggPGNvZGU+MDwvY29kZT4sIHRoZSBuZXh0IGF0IGluZGV4CiAgICogPGNvZGU+MTwvY29kZT4sIGFuZCBzbyBvbiwgYXMgZm9yIGFycmF5IGluZGV4aW5nLgogICAqCiAgICogQHBhcmFtICAgICAgaW5kZXggICB0aGUgaW5kZXggb2YgdGhlIGNoYXJhY3Rlci4KICAgKiBAcmV0dXJuICAgICB0aGUgY2hhcmFjdGVyIGF0IHRoZSBzcGVjaWZpZWQgaW5kZXggb2YgdGhpcyBzdHJpbmcuCiAgICogICAgICAgICAgICAgVGhlIGZpcnN0IGNoYXJhY3RlciBpcyBhdCBpbmRleCA8Y29kZT4wPC9jb2RlPi4KICAgKiBAZXhjZXB0aW9uICBJbmRleE91dE9mQm91bmRzRXhjZXB0aW9uICBpZiB0aGUgPGNvZGU+aW5kZXg8L2NvZGU+CiAgICogICAgICAgICAgICAgYXJndW1lbnQgaXMgbmVnYXRpdmUgb3Igbm90IGxlc3MgdGhhbiB0aGUgbGVuZ3RoIG9mIHRoaXMKICAgKiAgICAgICAgICAgICBzdHJpbmcuCiAgICovCiAgcHVibGljIGNoYXIgY2hhckF0KGludCBpbmRleCkKICB7CiAgICByZXR1cm4gc3RyKCkuY2hhckF0KGluZGV4KTsKICB9CgogIC8qKgogICAqIENvcGllcyBjaGFyYWN0ZXJzIGZyb20gdGhpcyBzdHJpbmcgaW50byB0aGUgZGVzdGluYXRpb24gY2hhcmFjdGVyCiAgICogYXJyYXkuCiAgICoKICAgKiBAcGFyYW0gICAgICBzcmNCZWdpbiAgIGluZGV4IG9mIHRoZSBmaXJzdCBjaGFyYWN0ZXIgaW4gdGhlIHN0cmluZwogICAqICAgICAgICAgICAgICAgICAgICAgICAgdG8gY29weS4KICAgKiBAcGFyYW0gICAgICBzcmNFbmQgICAgIGluZGV4IGFmdGVyIHRoZSBsYXN0IGNoYXJhY3RlciBpbiB0aGUgc3RyaW5nCiAgICogICAgICAgICAgICAgICAgICAgICAgICB0byBjb3B5LgogICAqIEBwYXJhbSAgICAgIGRzdCAgICAgICAgdGhlIGRlc3RpbmF0aW9uIGFycmF5LgogICAqIEBwYXJhbSAgICAgIGRzdEJlZ2luICAgdGhlIHN0YXJ0IG9mZnNldCBpbiB0aGUgZGVzdGluYXRpb24gYXJyYXkuCiAgICogQGV4Y2VwdGlvbiBJbmRleE91dE9mQm91bmRzRXhjZXB0aW9uIElmIGFueSBvZiB0aGUgZm9sbG93aW5nCiAgICogICAgICAgICAgICBpcyB0cnVlOgogICAqICAgICAgICAgICAgPHVsPjxsaT48Y29kZT5zcmNCZWdpbjwvY29kZT4gaXMgbmVnYXRpdmUuCiAgICogICAgICAgICAgICA8bGk+PGNvZGU+c3JjQmVnaW48L2NvZGU+IGlzIGdyZWF0ZXIgdGhhbiA8Y29kZT5zcmNFbmQ8L2NvZGU+CiAgICogICAgICAgICAgICA8bGk+PGNvZGU+c3JjRW5kPC9jb2RlPiBpcyBncmVhdGVyIHRoYW4gdGhlIGxlbmd0aCBvZiB0aGlzCiAgICogICAgICAgICAgICAgICAgc3RyaW5nCiAgICogICAgICAgICAgICA8bGk+PGNvZGU+ZHN0QmVnaW48L2NvZGU+IGlzIG5lZ2F0aXZlCiAgICogICAgICAgICAgICA8bGk+PGNvZGU+ZHN0QmVnaW4rKHNyY0VuZC1zcmNCZWdpbik8L2NvZGU+IGlzIGxhcmdlciB0aGFuCiAgICogICAgICAgICAgICAgICAgPGNvZGU+ZHN0Lmxlbmd0aDwvY29kZT48L3VsPgogICAqIEBleGNlcHRpb24gTnVsbFBvaW50ZXJFeGNlcHRpb24gaWYgPGNvZGU+ZHN0PC9jb2RlPiBpcyA8Y29kZT5udWxsPC9jb2RlPgogICAqLwogIHB1YmxpYyB2b2lkIGdldENoYXJzKGludCBzcmNCZWdpbiwgaW50IHNyY0VuZCwgY2hhciBkc3RbXSwgaW50IGRzdEJlZ2luKQogIHsKICAgIHN0cigpLmdldENoYXJzKHNyY0JlZ2luLCBzcmNFbmQsIGRzdCwgZHN0QmVnaW4pOwogIH0KCiAgLyoqCiAgICogVGVsbCBpZiB0d28gb2JqZWN0cyBhcmUgZnVuY3Rpb25hbGx5IGVxdWFsLgogICAqCiAgICogQHBhcmFtIG9iajIgT2JqZWN0IHRvIGNvbXBhcmUgdGhpcyB0bwogICAqCiAgICogQHJldHVybiB0cnVlIGlmIHRoZSB0d28gb2JqZWN0cyBhcmUgZXF1YWwKICAgKgogICAqIEB0aHJvd3MgamF2YXgueG1sLnRyYW5zZm9ybS5UcmFuc2Zvcm1lckV4Y2VwdGlvbgogICAqLwogIHB1YmxpYyBib29sZWFuIGVxdWFscyhYT2JqZWN0IG9iajIpCiAgewoKICAgIC8vIEluIG9yZGVyIHRvIGhhbmRsZSB0aGUgJ2FsbCcgc2VtYW50aWNzIG9mIAogICAgLy8gbm9kZXNldCBjb21wYXJpc29ucywgd2UgYWx3YXlzIGNhbGwgdGhlIAogICAgLy8gbm9kZXNldCBmdW5jdGlvbi4KICAgIGludCB0ID0gb2JqMi5nZXRUeXBlKCk7CiAgICBpZiAoKFhPYmplY3QuQ0xBU1NfTk9ERVNFVCA9PSB0KSB8fCAoWE9iamVjdC5DTEFTU19OVU1CRVIgPT0gdCkgKQogICAgICByZXR1cm4gb2JqMi5lcXVhbHModGhpcyk7CgogICAgcmV0dXJuIHN0cigpLmVxdWFscyhvYmoyLnN0cigpKTsKICB9CgogIC8qKgogICAqIENvbXBhcmVzIHRoaXMgc3RyaW5nIHRvIHRoZSBzcGVjaWZpZWQgb2JqZWN0LgogICAqIFRoZSByZXN1bHQgaXMgPGNvZGU+dHJ1ZTwvY29kZT4gaWYgYW5kIG9ubHkgaWYgdGhlIGFyZ3VtZW50IGlzIG5vdAogICAqIDxjb2RlPm51bGw8L2NvZGU+IGFuZCBpcyBhIDxjb2RlPlN0cmluZzwvY29kZT4gb2JqZWN0IHRoYXQgcmVwcmVzZW50cwogICAqIHRoZSBzYW1lIHNlcXVlbmNlIG9mIGNoYXJhY3RlcnMgYXMgdGhpcyBvYmplY3QuCiAgICoKICAgKiBAcGFyYW0gICBhbk9iamVjdCAgIHRoZSBvYmplY3QgdG8gY29tcGFyZSB0aGlzIDxjb2RlPlN0cmluZzwvY29kZT4KICAgKiAgICAgICAgICAgICAgICAgICAgIGFnYWluc3QuCiAgICoKICAgKiBORUVEU0RPQyBAcGFyYW0gb2JqMgogICAqIEByZXR1cm4gIDxjb2RlPnRydWU8L2NvZGU+IGlmIHRoZSA8Y29kZT5TdHJpbmcgPC9jb2RlPmFyZSBlcXVhbDsKICAgKiAgICAgICAgICA8Y29kZT5mYWxzZTwvY29kZT4gb3RoZXJ3aXNlLgogICAqIEBzZWUgICAgIGphdmEubGFuZy5TdHJpbmcjY29tcGFyZVRvKGphdmEubGFuZy5TdHJpbmcpCiAgICogQHNlZSAgICAgamF2YS5sYW5nLlN0cmluZyNlcXVhbHNJZ25vcmVDYXNlKGphdmEubGFuZy5TdHJpbmcpCiAgICovCiAgcHVibGljIGJvb2xlYW4gZXF1YWxzKFhNTFN0cmluZyBvYmoyKQogIHsKCiAgICBpZiAoIW9iajIuaGFzU3RyaW5nKCkpCiAgICAgIHJldHVybiBvYmoyLmVxdWFscyh0aGlzKTsKICAgIGVsc2UKICAgICAgcmV0dXJuIHN0cigpLmVxdWFscyhvYmoyLnRvU3RyaW5nKCkpOwogIH0KCiAgLyoqCiAgICogQ29tcGFyZXMgdGhpcyBzdHJpbmcgdG8gdGhlIHNwZWNpZmllZCBvYmplY3QuCiAgICogVGhlIHJlc3VsdCBpcyA8Y29kZT50cnVlPC9jb2RlPiBpZiBhbmQgb25seSBpZiB0aGUgYXJndW1lbnQgaXMgbm90CiAgICogPGNvZGU+bnVsbDwvY29kZT4gYW5kIGlzIGEgPGNvZGU+U3RyaW5nPC9jb2RlPiBvYmplY3QgdGhhdCByZXByZXNlbnRzCiAgICogdGhlIHNhbWUgc2VxdWVuY2Ugb2YgY2hhcmFjdGVycyBhcyB0aGlzIG9iamVjdC4KICAgKgogICAqIEBwYXJhbSAgIGFuT2JqZWN0ICAgdGhlIG9iamVjdCB0byBjb21wYXJlIHRoaXMgPGNvZGU+U3RyaW5nPC9jb2RlPgogICAqICAgICAgICAgICAgICAgICAgICAgYWdhaW5zdC4KICAgKgogICAqIE5FRURTRE9DIEBwYXJhbSBvYmoyCiAgICogQHJldHVybiAgPGNvZGU+dHJ1ZTwvY29kZT4gaWYgdGhlIDxjb2RlPlN0cmluZyA8L2NvZGU+YXJlIGVxdWFsOwogICAqICAgICAgICAgIDxjb2RlPmZhbHNlPC9jb2RlPiBvdGhlcndpc2UuCiAgICogQHNlZSAgICAgamF2YS5sYW5nLlN0cmluZyNjb21wYXJlVG8oamF2YS5sYW5nLlN0cmluZykKICAgKiBAc2VlICAgICBqYXZhLmxhbmcuU3RyaW5nI2VxdWFsc0lnbm9yZUNhc2UoamF2YS5sYW5nLlN0cmluZykKICAgKi8KICBwdWJsaWMgYm9vbGVhbiBlcXVhbHMoT2JqZWN0IG9iajIpCiAgewoKICAgIGlmIChudWxsID09IG9iajIpCiAgICAgIHJldHVybiBmYWxzZTsKCiAgICAgIC8vIEluIG9yZGVyIHRvIGhhbmRsZSB0aGUgJ2FsbCcgc2VtYW50aWNzIG9mIAogICAgICAvLyBub2Rlc2V0IGNvbXBhcmlzb25zLCB3ZSBhbHdheXMgY2FsbCB0aGUgCiAgICAgIC8vIG5vZGVzZXQgZnVuY3Rpb24uCiAgICBlbHNlIGlmIChvYmoyIGluc3RhbmNlb2YgWE5vZGVTZXQpCiAgICAgIHJldHVybiBvYmoyLmVxdWFscyh0aGlzKTsKICAgIGVsc2UgaWYob2JqMiBpbnN0YW5jZW9mIFhOdW1iZXIpCiAgICAJcmV0dXJuIG9iajIuZXF1YWxzKHRoaXMpOwogICAgZWxzZQogICAgICByZXR1cm4gc3RyKCkuZXF1YWxzKG9iajIudG9TdHJpbmcoKSk7CiAgfQoKICAvKioKICAgKiBDb21wYXJlcyB0aGlzIDxjb2RlPlN0cmluZzwvY29kZT4gdG8gYW5vdGhlciA8Y29kZT5TdHJpbmc8L2NvZGU+LAogICAqIGlnbm9yaW5nIGNhc2UgY29uc2lkZXJhdGlvbnMuICBUd28gc3RyaW5ncyBhcmUgY29uc2lkZXJlZCBlcXVhbAogICAqIGlnbm9yaW5nIGNhc2UgaWYgdGhleSBhcmUgb2YgdGhlIHNhbWUgbGVuZ3RoLCBhbmQgY29ycmVzcG9uZGluZwogICAqIGNoYXJhY3RlcnMgaW4gdGhlIHR3byBzdHJpbmdzIGFyZSBlcXVhbCBpZ25vcmluZyBjYXNlLgogICAqCiAgICogQHBhcmFtICAgYW5vdGhlclN0cmluZyAgIHRoZSA8Y29kZT5TdHJpbmc8L2NvZGU+IHRvIGNvbXBhcmUgdGhpcwogICAqICAgICAgICAgICAgICAgICAgICAgICAgICA8Y29kZT5TdHJpbmc8L2NvZGU+IGFnYWluc3QuCiAgICogQHJldHVybiAgPGNvZGU+dHJ1ZTwvY29kZT4gaWYgdGhlIGFyZ3VtZW50IGlzIG5vdCA8Y29kZT5udWxsPC9jb2RlPgogICAqICAgICAgICAgIGFuZCB0aGUgPGNvZGU+U3RyaW5nPC9jb2RlPnMgYXJlIGVxdWFsLAogICAqICAgICAgICAgIGlnbm9yaW5nIGNhc2U7IDxjb2RlPmZhbHNlPC9jb2RlPiBvdGhlcndpc2UuCiAgICogQHNlZSAgICAgI2VxdWFscyhPYmplY3QpCiAgICogQHNlZSAgICAgamF2YS5sYW5nLkNoYXJhY3RlciN0b0xvd2VyQ2FzZShjaGFyKQogICAqIEBzZWUgamF2YS5sYW5nLkNoYXJhY3RlciN0b1VwcGVyQ2FzZShjaGFyKQogICAqLwogIHB1YmxpYyBib29sZWFuIGVxdWFsc0lnbm9yZUNhc2UoU3RyaW5nIGFub3RoZXJTdHJpbmcpCiAgewogICAgcmV0dXJuIHN0cigpLmVxdWFsc0lnbm9yZUNhc2UoYW5vdGhlclN0cmluZyk7CiAgfQoKICAvKioKICAgKiBDb21wYXJlcyB0d28gc3RyaW5ncyBsZXhpY29ncmFwaGljYWxseS4KICAgKgogICAqIEBwYXJhbSAgIGFub3RoZXJTdHJpbmcgICB0aGUgPGNvZGU+U3RyaW5nPC9jb2RlPiB0byBiZSBjb21wYXJlZC4KICAgKgogICAqIE5FRURTRE9DIEBwYXJhbSB4c3RyCiAgICogQHJldHVybiAgdGhlIHZhbHVlIDxjb2RlPjA8L2NvZGU+IGlmIHRoZSBhcmd1bWVudCBzdHJpbmcgaXMgZXF1YWwgdG8KICAgKiAgICAgICAgICB0aGlzIHN0cmluZzsgYSB2YWx1ZSBsZXNzIHRoYW4gPGNvZGU+MDwvY29kZT4gaWYgdGhpcyBzdHJpbmcKICAgKiAgICAgICAgICBpcyBsZXhpY29ncmFwaGljYWxseSBsZXNzIHRoYW4gdGhlIHN0cmluZyBhcmd1bWVudDsgYW5kIGEKICAgKiAgICAgICAgICB2YWx1ZSBncmVhdGVyIHRoYW4gPGNvZGU+MDwvY29kZT4gaWYgdGhpcyBzdHJpbmcgaXMKICAgKiAgICAgICAgICBsZXhpY29ncmFwaGljYWxseSBncmVhdGVyIHRoYW4gdGhlIHN0cmluZyBhcmd1bWVudC4KICAgKiBAZXhjZXB0aW9uIGphdmEubGFuZy5OdWxsUG9pbnRlckV4Y2VwdGlvbiBpZiA8Y29kZT5hbm90aGVyU3RyaW5nPC9jb2RlPgogICAqICAgICAgICAgIGlzIDxjb2RlPm51bGw8L2NvZGU+LgogICAqLwogIHB1YmxpYyBpbnQgY29tcGFyZVRvKFhNTFN0cmluZyB4c3RyKQogIHsKCiAgICBpbnQgbGVuMSA9IHRoaXMubGVuZ3RoKCk7CiAgICBpbnQgbGVuMiA9IHhzdHIubGVuZ3RoKCk7CiAgICBpbnQgbiA9IE1hdGgubWluKGxlbjEsIGxlbjIpOwogICAgaW50IGkgPSAwOwogICAgaW50IGogPSAwOwoKICAgIHdoaWxlIChuLS0gIT0gMCkKICAgIHsKICAgICAgY2hhciBjMSA9IHRoaXMuY2hhckF0KGkpOwogICAgICBjaGFyIGMyID0geHN0ci5jaGFyQXQoaik7CgogICAgICBpZiAoYzEgIT0gYzIpCiAgICAgIHsKICAgICAgICByZXR1cm4gYzEgLSBjMjsKICAgICAgfQoKICAgICAgaSsrOwogICAgICBqKys7CiAgICB9CgogICAgcmV0dXJuIGxlbjEgLSBsZW4yOwogIH0KCiAgLyoqCiAgICogQ29tcGFyZXMgdHdvIHN0cmluZ3MgbGV4aWNvZ3JhcGhpY2FsbHksIGlnbm9yaW5nIGNhc2UgY29uc2lkZXJhdGlvbnMuCiAgICogVGhpcyBtZXRob2QgcmV0dXJucyBhbiBpbnRlZ2VyIHdob3NlIHNpZ24gaXMgdGhhdCBvZgogICAqIDxjb2RlPnRoaXMudG9VcHBlckNhc2UoKS50b0xvd2VyQ2FzZSgpLmNvbXBhcmVUbygKICAgKiBzdHIudG9VcHBlckNhc2UoKS50b0xvd2VyQ2FzZSgpKTwvY29kZT4uCiAgICogPHA+CiAgICogTm90ZSB0aGF0IHRoaXMgbWV0aG9kIGRvZXMgPGVtPm5vdDwvZW0+IHRha2UgbG9jYWxlIGludG8gYWNjb3VudCwKICAgKiBhbmQgd2lsbCByZXN1bHQgaW4gYW4gdW5zYXRpc2ZhY3Rvcnkgb3JkZXJpbmcgZm9yIGNlcnRhaW4gbG9jYWxlcy4KICAgKiBUaGUgamF2YS50ZXh0IHBhY2thZ2UgcHJvdmlkZXMgPGVtPmNvbGxhdG9yczwvZW0+IHRvIGFsbG93CiAgICogbG9jYWxlLXNlbnNpdGl2ZSBvcmRlcmluZy4KICAgKgogICAqIEBwYXJhbSAgIHN0ciAgIHRoZSA8Y29kZT5TdHJpbmc8L2NvZGU+IHRvIGJlIGNvbXBhcmVkLgogICAqIEByZXR1cm4gIGEgbmVnYXRpdmUgaW50ZWdlciwgemVybywgb3IgYSBwb3NpdGl2ZSBpbnRlZ2VyIGFzIHRoZQogICAqICAgICAgICAgIHRoZSBzcGVjaWZpZWQgU3RyaW5nIGlzIGdyZWF0ZXIgdGhhbiwgZXF1YWwgdG8sIG9yIGxlc3MKICAgKiAgICAgICAgICB0aGFuIHRoaXMgU3RyaW5nLCBpZ25vcmluZyBjYXNlIGNvbnNpZGVyYXRpb25zLgogICAqIEBzZWUgICAgIGphdmEudGV4dC5Db2xsYXRvciNjb21wYXJlKFN0cmluZywgU3RyaW5nKQogICAqIEBzaW5jZSAgIDEuMgogICAqLwogIHB1YmxpYyBpbnQgY29tcGFyZVRvSWdub3JlQ2FzZShYTUxTdHJpbmcgc3RyKQogIHsKICAgIC8vICVSRVZJRVclICBMaWtlIGl0IHNheXMsIEBzaW5jZSAxLjIuIERvZXNuJ3QgZXhpc3QgaW4gZWFybGllcgogICAgLy8gdmVyc2lvbnMgb2YgSmF2YSwgaGVuY2Ugd2UgY2FuJ3QgeWV0IHNoZWxsIG91dCB0byBpdC4gV2UgY2FuIGltcGxlbWVudAogICAgLy8gaXQgYXMgY2hhcmFjdGVyLWJ5LWNoYXJhY3RlciBjb21wYXJlLCBidXQgZG9pbmcgc28gZWZmaWNpZW50bHkKICAgIC8vIGlzIGxpa2VseSB0byBiZSAoYWhlbSkgaW50ZXJlc3RpbmcuCiAgICAvLyAgCiAgICAvLyBIb3dldmVyLCBzaW5jZSBub2JvZHkgaXMgYWN0dWFsbHkgX3VzaW5nXyB0aGlzIG1ldGhvZCB5ZXQ6CiAgICAvLyAgICByZXR1cm4gc3RyKCkuY29tcGFyZVRvSWdub3JlQ2FzZShzdHIudG9TdHJpbmcoKSk7CiAgICAKICAgIHRocm93IG5ldyBvcmcuYXBhY2hlLnhtbC51dGlscy5XcmFwcGVkUnVudGltZUV4Y2VwdGlvbigKICAgICAgbmV3IGphdmEubGFuZy5Ob1N1Y2hNZXRob2RFeGNlcHRpb24oCiAgICAgICAgIkphdmEgMS4yIG1ldGhvZCwgbm90IHlldCBpbXBsZW1lbnRlZCIpKTsKICB9CgogIC8qKgogICAqIFRlc3RzIGlmIHRoaXMgc3RyaW5nIHN0YXJ0cyB3aXRoIHRoZSBzcGVjaWZpZWQgcHJlZml4IGJlZ2lubmluZwogICAqIGEgc3BlY2lmaWVkIGluZGV4LgogICAqCiAgICogQHBhcmFtICAgcHJlZml4ICAgIHRoZSBwcmVmaXguCiAgICogQHBhcmFtICAgdG9mZnNldCAgIHdoZXJlIHRvIGJlZ2luIGxvb2tpbmcgaW4gdGhlIHN0cmluZy4KICAgKiBAcmV0dXJuICA8Y29kZT50cnVlPC9jb2RlPiBpZiB0aGUgY2hhcmFjdGVyIHNlcXVlbmNlIHJlcHJlc2VudGVkIGJ5IHRoZQogICAqICAgICAgICAgIGFyZ3VtZW50IGlzIGEgcHJlZml4IG9mIHRoZSBzdWJzdHJpbmcgb2YgdGhpcyBvYmplY3Qgc3RhcnRpbmcKICAgKiAgICAgICAgICBhdCBpbmRleCA8Y29kZT50b2Zmc2V0PC9jb2RlPjsgPGNvZGU+ZmFsc2U8L2NvZGU+IG90aGVyd2lzZS4KICAgKiAgICAgICAgICBUaGUgcmVzdWx0IGlzIDxjb2RlPmZhbHNlPC9jb2RlPiBpZiA8Y29kZT50b2Zmc2V0PC9jb2RlPiBpcwogICAqICAgICAgICAgIG5lZ2F0aXZlIG9yIGdyZWF0ZXIgdGhhbiB0aGUgbGVuZ3RoIG9mIHRoaXMKICAgKiAgICAgICAgICA8Y29kZT5TdHJpbmc8L2NvZGU+IG9iamVjdDsgb3RoZXJ3aXNlIHRoZSByZXN1bHQgaXMgdGhlIHNhbWUKICAgKiAgICAgICAgICBhcyB0aGUgcmVzdWx0IG9mIHRoZSBleHByZXNzaW9uCiAgICogICAgICAgICAgPHByZT4KICAgKiAgICAgICAgICB0aGlzLnN1YlN0cmluZyh0b2Zmc2V0KS5zdGFydHNXaXRoKHByZWZpeCkKICAgKiAgICAgICAgICA8L3ByZT4KICAgKiBAZXhjZXB0aW9uIGphdmEubGFuZy5OdWxsUG9pbnRlckV4Y2VwdGlvbiBpZiA8Y29kZT5wcmVmaXg8L2NvZGU+IGlzCiAgICogICAgICAgICAgPGNvZGU+bnVsbDwvY29kZT4uCiAgICovCiAgcHVibGljIGJvb2xlYW4gc3RhcnRzV2l0aChTdHJpbmcgcHJlZml4LCBpbnQgdG9mZnNldCkKICB7CiAgICByZXR1cm4gc3RyKCkuc3RhcnRzV2l0aChwcmVmaXgsIHRvZmZzZXQpOwogIH0KCiAgLyoqCiAgICogVGVzdHMgaWYgdGhpcyBzdHJpbmcgc3RhcnRzIHdpdGggdGhlIHNwZWNpZmllZCBwcmVmaXguCiAgICoKICAgKiBAcGFyYW0gICBwcmVmaXggICB0aGUgcHJlZml4LgogICAqIEByZXR1cm4gIDxjb2RlPnRydWU8L2NvZGU+IGlmIHRoZSBjaGFyYWN0ZXIgc2VxdWVuY2UgcmVwcmVzZW50ZWQgYnkgdGhlCiAgICogICAgICAgICAgYXJndW1lbnQgaXMgYSBwcmVmaXggb2YgdGhlIGNoYXJhY3RlciBzZXF1ZW5jZSByZXByZXNlbnRlZCBieQogICAqICAgICAgICAgIHRoaXMgc3RyaW5nOyA8Y29kZT5mYWxzZTwvY29kZT4gb3RoZXJ3aXNlLgogICAqICAgICAgICAgIE5vdGUgYWxzbyB0aGF0IDxjb2RlPnRydWU8L2NvZGU+IHdpbGwgYmUgcmV0dXJuZWQgaWYgdGhlCiAgICogICAgICAgICAgYXJndW1lbnQgaXMgYW4gZW1wdHkgc3RyaW5nIG9yIGlzIGVxdWFsIHRvIHRoaXMKICAgKiAgICAgICAgICA8Y29kZT5TdHJpbmc8L2NvZGU+IG9iamVjdCBhcyBkZXRlcm1pbmVkIGJ5IHRoZQogICAqICAgICAgICAgIHtAbGluayAjZXF1YWxzKE9iamVjdCl9IG1ldGhvZC4KICAgKiBAZXhjZXB0aW9uIGphdmEubGFuZy5OdWxsUG9pbnRlckV4Y2VwdGlvbiBpZiA8Y29kZT5wcmVmaXg8L2NvZGU+IGlzCiAgICogICAgICAgICAgPGNvZGU+bnVsbDwvY29kZT4uCiAgICovCiAgcHVibGljIGJvb2xlYW4gc3RhcnRzV2l0aChTdHJpbmcgcHJlZml4KQogIHsKICAgIHJldHVybiBzdGFydHNXaXRoKHByZWZpeCwgMCk7CiAgfQoKICAvKioKICAgKiBUZXN0cyBpZiB0aGlzIHN0cmluZyBzdGFydHMgd2l0aCB0aGUgc3BlY2lmaWVkIHByZWZpeCBiZWdpbm5pbmcKICAgKiBhIHNwZWNpZmllZCBpbmRleC4KICAgKgogICAqIEBwYXJhbSAgIHByZWZpeCAgICB0aGUgcHJlZml4LgogICAqIEBwYXJhbSAgIHRvZmZzZXQgICB3aGVyZSB0byBiZWdpbiBsb29raW5nIGluIHRoZSBzdHJpbmcuCiAgICogQHJldHVybiAgPGNvZGU+dHJ1ZTwvY29kZT4gaWYgdGhlIGNoYXJhY3RlciBzZXF1ZW5jZSByZXByZXNlbnRlZCBieSB0aGUKICAgKiAgICAgICAgICBhcmd1bWVudCBpcyBhIHByZWZpeCBvZiB0aGUgc3Vic3RyaW5nIG9mIHRoaXMgb2JqZWN0IHN0YXJ0aW5nCiAgICogICAgICAgICAgYXQgaW5kZXggPGNvZGU+dG9mZnNldDwvY29kZT47IDxjb2RlPmZhbHNlPC9jb2RlPiBvdGhlcndpc2UuCiAgICogICAgICAgICAgVGhlIHJlc3VsdCBpcyA8Y29kZT5mYWxzZTwvY29kZT4gaWYgPGNvZGU+dG9mZnNldDwvY29kZT4gaXMKICAgKiAgICAgICAgICBuZWdhdGl2ZSBvciBncmVhdGVyIHRoYW4gdGhlIGxlbmd0aCBvZiB0aGlzCiAgICogICAgICAgICAgPGNvZGU+U3RyaW5nPC9jb2RlPiBvYmplY3Q7IG90aGVyd2lzZSB0aGUgcmVzdWx0IGlzIHRoZSBzYW1lCiAgICogICAgICAgICAgYXMgdGhlIHJlc3VsdCBvZiB0aGUgZXhwcmVzc2lvbgogICAqICAgICAgICAgIDxwcmU+CiAgICogICAgICAgICAgdGhpcy5zdWJTdHJpbmcodG9mZnNldCkuc3RhcnRzV2l0aChwcmVmaXgpCiAgICogICAgICAgICAgPC9wcmU+CiAgICogQGV4Y2VwdGlvbiBqYXZhLmxhbmcuTnVsbFBvaW50ZXJFeGNlcHRpb24gaWYgPGNvZGU+cHJlZml4PC9jb2RlPiBpcwogICAqICAgICAgICAgIDxjb2RlPm51bGw8L2NvZGU+LgogICAqLwogIHB1YmxpYyBib29sZWFuIHN0YXJ0c1dpdGgoWE1MU3RyaW5nIHByZWZpeCwgaW50IHRvZmZzZXQpCiAgewoKICAgIGludCB0byA9IHRvZmZzZXQ7CiAgICBpbnQgdGxpbSA9IHRoaXMubGVuZ3RoKCk7CiAgICBpbnQgcG8gPSAwOwogICAgaW50IHBjID0gcHJlZml4Lmxlbmd0aCgpOwoKICAgIC8vIE5vdGU6IHRvZmZzZXQgbWlnaHQgYmUgbmVhciAtMT4+PjEuCiAgICBpZiAoKHRvZmZzZXQgPCAwKSB8fCAodG9mZnNldCA+IHRsaW0gLSBwYykpCiAgICB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KCiAgICB3aGlsZSAoLS1wYyA+PSAwKQogICAgewogICAgICBpZiAodGhpcy5jaGFyQXQodG8pICE9IHByZWZpeC5jaGFyQXQocG8pKQogICAgICB7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9CgogICAgICB0bysrOwogICAgICBwbysrOwogICAgfQoKICAgIHJldHVybiB0cnVlOwogIH0KCiAgLyoqCiAgICogVGVzdHMgaWYgdGhpcyBzdHJpbmcgc3RhcnRzIHdpdGggdGhlIHNwZWNpZmllZCBwcmVmaXguCiAgICoKICAgKiBAcGFyYW0gICBwcmVmaXggICB0aGUgcHJlZml4LgogICAqIEByZXR1cm4gIDxjb2RlPnRydWU8L2NvZGU+IGlmIHRoZSBjaGFyYWN0ZXIgc2VxdWVuY2UgcmVwcmVzZW50ZWQgYnkgdGhlCiAgICogICAgICAgICAgYXJndW1lbnQgaXMgYSBwcmVmaXggb2YgdGhlIGNoYXJhY3RlciBzZXF1ZW5jZSByZXByZXNlbnRlZCBieQogICAqICAgICAgICAgIHRoaXMgc3RyaW5nOyA8Y29kZT5mYWxzZTwvY29kZT4gb3RoZXJ3aXNlLgogICAqICAgICAgICAgIE5vdGUgYWxzbyB0aGF0IDxjb2RlPnRydWU8L2NvZGU+IHdpbGwgYmUgcmV0dXJuZWQgaWYgdGhlCiAgICogICAgICAgICAgYXJndW1lbnQgaXMgYW4gZW1wdHkgc3RyaW5nIG9yIGlzIGVxdWFsIHRvIHRoaXMKICAgKiAgICAgICAgICA8Y29kZT5TdHJpbmc8L2NvZGU+IG9iamVjdCBhcyBkZXRlcm1pbmVkIGJ5IHRoZQogICAqICAgICAgICAgIHtAbGluayAjZXF1YWxzKE9iamVjdCl9IG1ldGhvZC4KICAgKiBAZXhjZXB0aW9uIGphdmEubGFuZy5OdWxsUG9pbnRlckV4Y2VwdGlvbiBpZiA8Y29kZT5wcmVmaXg8L2NvZGU+IGlzCiAgICogICAgICAgICAgPGNvZGU+bnVsbDwvY29kZT4uCiAgICovCiAgcHVibGljIGJvb2xlYW4gc3RhcnRzV2l0aChYTUxTdHJpbmcgcHJlZml4KQogIHsKICAgIHJldHVybiBzdGFydHNXaXRoKHByZWZpeCwgMCk7CiAgfQoKICAvKioKICAgKiBUZXN0cyBpZiB0aGlzIHN0cmluZyBlbmRzIHdpdGggdGhlIHNwZWNpZmllZCBzdWZmaXguCiAgICoKICAgKiBAcGFyYW0gICBzdWZmaXggICB0aGUgc3VmZml4LgogICAqIEByZXR1cm4gIDxjb2RlPnRydWU8L2NvZGU+IGlmIHRoZSBjaGFyYWN0ZXIgc2VxdWVuY2UgcmVwcmVzZW50ZWQgYnkgdGhlCiAgICogICAgICAgICAgYXJndW1lbnQgaXMgYSBzdWZmaXggb2YgdGhlIGNoYXJhY3RlciBzZXF1ZW5jZSByZXByZXNlbnRlZCBieQogICAqICAgICAgICAgIHRoaXMgb2JqZWN0OyA8Y29kZT5mYWxzZTwvY29kZT4gb3RoZXJ3aXNlLiBOb3RlIHRoYXQgdGhlCiAgICogICAgICAgICAgcmVzdWx0IHdpbGwgYmUgPGNvZGU+dHJ1ZTwvY29kZT4gaWYgdGhlIGFyZ3VtZW50IGlzIHRoZQogICAqICAgICAgICAgIGVtcHR5IHN0cmluZyBvciBpcyBlcXVhbCB0byB0aGlzIDxjb2RlPlN0cmluZzwvY29kZT4gb2JqZWN0CiAgICogICAgICAgICAgYXMgZGV0ZXJtaW5lZCBieSB0aGUge0BsaW5rICNlcXVhbHMoT2JqZWN0KX0gbWV0aG9kLgogICAqIEBleGNlcHRpb24gamF2YS5sYW5nLk51bGxQb2ludGVyRXhjZXB0aW9uIGlmIDxjb2RlPnN1ZmZpeDwvY29kZT4gaXMKICAgKiAgICAgICAgICA8Y29kZT5udWxsPC9jb2RlPi4KICAgKi8KICBwdWJsaWMgYm9vbGVhbiBlbmRzV2l0aChTdHJpbmcgc3VmZml4KQogIHsKICAgIHJldHVybiBzdHIoKS5lbmRzV2l0aChzdWZmaXgpOwogIH0KCiAgLyoqCiAgICogUmV0dXJucyBhIGhhc2hjb2RlIGZvciB0aGlzIHN0cmluZy4gVGhlIGhhc2hjb2RlIGZvciBhCiAgICogPGNvZGU+U3RyaW5nPC9jb2RlPiBvYmplY3QgaXMgY29tcHV0ZWQgYXMKICAgKiA8YmxvY2txdW90ZT48cHJlPgogICAqIHNbMF0qMzFeKG4tMSkgKyBzWzFdKjMxXihuLTIpICsgLi4uICsgc1tuLTFdCiAgICogPC9wcmU+PC9ibG9ja3F1b3RlPgogICAqIHVzaW5nIDxjb2RlPmludDwvY29kZT4gYXJpdGhtZXRpYywgd2hlcmUgPGNvZGU+c1tpXTwvY29kZT4gaXMgdGhlCiAgICogPGk+aTwvaT50aCBjaGFyYWN0ZXIgb2YgdGhlIHN0cmluZywgPGNvZGU+bjwvY29kZT4gaXMgdGhlIGxlbmd0aCBvZgogICAqIHRoZSBzdHJpbmcsIGFuZCA8Y29kZT5ePC9jb2RlPiBpbmRpY2F0ZXMgZXhwb25lbnRpYXRpb24uCiAgICogKFRoZSBoYXNoIHZhbHVlIG9mIHRoZSBlbXB0eSBzdHJpbmcgaXMgemVyby4pCiAgICoKICAgKiBAcmV0dXJuICBhIGhhc2ggY29kZSB2YWx1ZSBmb3IgdGhpcyBvYmplY3QuCiAgICovCiAgcHVibGljIGludCBoYXNoQ29kZSgpCiAgewogICAgcmV0dXJuIHN0cigpLmhhc2hDb2RlKCk7CiAgfQoKICAvKioKICAgKiBSZXR1cm5zIHRoZSBpbmRleCB3aXRoaW4gdGhpcyBzdHJpbmcgb2YgdGhlIGZpcnN0IG9jY3VycmVuY2Ugb2YgdGhlCiAgICogc3BlY2lmaWVkIGNoYXJhY3Rlci4gSWYgYSBjaGFyYWN0ZXIgd2l0aCB2YWx1ZSA8Y29kZT5jaDwvY29kZT4gb2NjdXJzCiAgICogaW4gdGhlIGNoYXJhY3RlciBzZXF1ZW5jZSByZXByZXNlbnRlZCBieSB0aGlzIDxjb2RlPlN0cmluZzwvY29kZT4KICAgKiBvYmplY3QsIHRoZW4gdGhlIGluZGV4IG9mIHRoZSBmaXJzdCBzdWNoIG9jY3VycmVuY2UgaXMgcmV0dXJuZWQgLS0KICAgKiB0aGF0IGlzLCB0aGUgc21hbGxlc3QgdmFsdWUgPGk+azwvaT4gc3VjaCB0aGF0OgogICAqIDxibG9ja3F1b3RlPjxwcmU+CiAgICogdGhpcy5jaGFyQXQoPGk+azwvaT4pID09IGNoCiAgICogPC9wcmU+PC9ibG9ja3F1b3RlPgogICAqIGlzIDxjb2RlPnRydWU8L2NvZGU+LiBJZiBubyBzdWNoIGNoYXJhY3RlciBvY2N1cnMgaW4gdGhpcyBzdHJpbmcsCiAgICogdGhlbiA8Y29kZT4tMTwvY29kZT4gaXMgcmV0dXJuZWQuCiAgICoKICAgKiBAcGFyYW0gICBjaCAgIGEgY2hhcmFjdGVyLgogICAqIEByZXR1cm4gIHRoZSBpbmRleCBvZiB0aGUgZmlyc3Qgb2NjdXJyZW5jZSBvZiB0aGUgY2hhcmFjdGVyIGluIHRoZQogICAqICAgICAgICAgIGNoYXJhY3RlciBzZXF1ZW5jZSByZXByZXNlbnRlZCBieSB0aGlzIG9iamVjdCwgb3IKICAgKiAgICAgICAgICA8Y29kZT4tMTwvY29kZT4gaWYgdGhlIGNoYXJhY3RlciBkb2VzIG5vdCBvY2N1ci4KICAgKi8KICBwdWJsaWMgaW50IGluZGV4T2YoaW50IGNoKQogIHsKICAgIHJldHVybiBzdHIoKS5pbmRleE9mKGNoKTsKICB9CgogIC8qKgogICAqIFJldHVybnMgdGhlIGluZGV4IHdpdGhpbiB0aGlzIHN0cmluZyBvZiB0aGUgZmlyc3Qgb2NjdXJyZW5jZSBvZiB0aGUKICAgKiBzcGVjaWZpZWQgY2hhcmFjdGVyLCBzdGFydGluZyB0aGUgc2VhcmNoIGF0IHRoZSBzcGVjaWZpZWQgaW5kZXguCiAgICogPHA+CiAgICogSWYgYSBjaGFyYWN0ZXIgd2l0aCB2YWx1ZSA8Y29kZT5jaDwvY29kZT4gb2NjdXJzIGluIHRoZSBjaGFyYWN0ZXIKICAgKiBzZXF1ZW5jZSByZXByZXNlbnRlZCBieSB0aGlzIDxjb2RlPlN0cmluZzwvY29kZT4gb2JqZWN0IGF0IGFuIGluZGV4CiAgICogbm8gc21hbGxlciB0aGFuIDxjb2RlPmZyb21JbmRleDwvY29kZT4sIHRoZW4gdGhlIGluZGV4IG9mIHRoZSBmaXJzdAogICAqIHN1Y2ggb2NjdXJyZW5jZSBpcyByZXR1cm5lZC0tdGhhdCBpcywgdGhlIHNtYWxsZXN0IHZhbHVlIDxpPms8L2k+CiAgICogc3VjaCB0aGF0OgogICAqIDxibG9ja3F1b3RlPjxwcmU+CiAgICogKHRoaXMuY2hhckF0KDxpPms8L2k+KSA9PSBjaCkgJiYgKDxpPms8L2k+ID49IGZyb21JbmRleCkKICAgKiA8L3ByZT48L2Jsb2NrcXVvdGU+CiAgICogaXMgdHJ1ZS4gSWYgbm8gc3VjaCBjaGFyYWN0ZXIgb2NjdXJzIGluIHRoaXMgc3RyaW5nIGF0IG9yIGFmdGVyCiAgICogcG9zaXRpb24gPGNvZGU+ZnJvbUluZGV4PC9jb2RlPiwgdGhlbiA8Y29kZT4tMTwvY29kZT4gaXMgcmV0dXJuZWQuCiAgICogPHA+CiAgICogVGhlcmUgaXMgbm8gcmVzdHJpY3Rpb24gb24gdGhlIHZhbHVlIG9mIDxjb2RlPmZyb21JbmRleDwvY29kZT4uIElmIGl0CiAgICogaXMgbmVnYXRpdmUsIGl0IGhhcyB0aGUgc2FtZSBlZmZlY3QgYXMgaWYgaXQgd2VyZSB6ZXJvOiB0aGlzIGVudGlyZQogICAqIHN0cmluZyBtYXkgYmUgc2VhcmNoZWQuIElmIGl0IGlzIGdyZWF0ZXIgdGhhbiB0aGUgbGVuZ3RoIG9mIHRoaXMKICAgKiBzdHJpbmcsIGl0IGhhcyB0aGUgc2FtZSBlZmZlY3QgYXMgaWYgaXQgd2VyZSBlcXVhbCB0byB0aGUgbGVuZ3RoIG9mCiAgICogdGhpcyBzdHJpbmc6IDxjb2RlPi0xPC9jb2RlPiBpcyByZXR1cm5lZC4KICAgKgogICAqIEBwYXJhbSAgIGNoICAgICAgICAgIGEgY2hhcmFjdGVyLgogICAqIEBwYXJhbSAgIGZyb21JbmRleCAgIHRoZSBpbmRleCB0byBzdGFydCB0aGUgc2VhcmNoIGZyb20uCiAgICogQHJldHVybiAgdGhlIGluZGV4IG9mIHRoZSBmaXJzdCBvY2N1cnJlbmNlIG9mIHRoZSBjaGFyYWN0ZXIgaW4gdGhlCiAgICogICAgICAgICAgY2hhcmFjdGVyIHNlcXVlbmNlIHJlcHJlc2VudGVkIGJ5IHRoaXMgb2JqZWN0IHRoYXQgaXMgZ3JlYXRlcgogICAqICAgICAgICAgIHRoYW4gb3IgZXF1YWwgdG8gPGNvZGU+ZnJvbUluZGV4PC9jb2RlPiwgb3IgPGNvZGU+LTE8L2NvZGU+CiAgICogICAgICAgICAgaWYgdGhlIGNoYXJhY3RlciBkb2VzIG5vdCBvY2N1ci4KICAgKi8KICBwdWJsaWMgaW50IGluZGV4T2YoaW50IGNoLCBpbnQgZnJvbUluZGV4KQogIHsKICAgIHJldHVybiBzdHIoKS5pbmRleE9mKGNoLCBmcm9tSW5kZXgpOwogIH0KCiAgLyoqCiAgICogUmV0dXJucyB0aGUgaW5kZXggd2l0aGluIHRoaXMgc3RyaW5nIG9mIHRoZSBsYXN0IG9jY3VycmVuY2Ugb2YgdGhlCiAgICogc3BlY2lmaWVkIGNoYXJhY3Rlci4gVGhhdCBpcywgdGhlIGluZGV4IHJldHVybmVkIGlzIHRoZSBsYXJnZXN0CiAgICogdmFsdWUgPGk+azwvaT4gc3VjaCB0aGF0OgogICAqIDxibG9ja3F1b3RlPjxwcmU+CiAgICogdGhpcy5jaGFyQXQoPGk+azwvaT4pID09IGNoCiAgICogPC9wcmU+PC9ibG9ja3F1b3RlPgogICAqIGlzIHRydWUuCiAgICogVGhlIFN0cmluZyBpcyBzZWFyY2hlZCBiYWNrd2FyZHMgc3RhcnRpbmcgYXQgdGhlIGxhc3QgY2hhcmFjdGVyLgogICAqCiAgICogQHBhcmFtICAgY2ggICBhIGNoYXJhY3Rlci4KICAgKiBAcmV0dXJuICB0aGUgaW5kZXggb2YgdGhlIGxhc3Qgb2NjdXJyZW5jZSBvZiB0aGUgY2hhcmFjdGVyIGluIHRoZQogICAqICAgICAgICAgIGNoYXJhY3RlciBzZXF1ZW5jZSByZXByZXNlbnRlZCBieSB0aGlzIG9iamVjdCwgb3IKICAgKiAgICAgICAgICA8Y29kZT4tMTwvY29kZT4gaWYgdGhlIGNoYXJhY3RlciBkb2VzIG5vdCBvY2N1ci4KICAgKi8KICBwdWJsaWMgaW50IGxhc3RJbmRleE9mKGludCBjaCkKICB7CiAgICByZXR1cm4gc3RyKCkubGFzdEluZGV4T2YoY2gpOwogIH0KCiAgLyoqCiAgICogUmV0dXJucyB0aGUgaW5kZXggd2l0aGluIHRoaXMgc3RyaW5nIG9mIHRoZSBsYXN0IG9jY3VycmVuY2Ugb2YgdGhlCiAgICogc3BlY2lmaWVkIGNoYXJhY3Rlciwgc2VhcmNoaW5nIGJhY2t3YXJkIHN0YXJ0aW5nIGF0IHRoZSBzcGVjaWZpZWQKICAgKiBpbmRleC4gVGhhdCBpcywgdGhlIGluZGV4IHJldHVybmVkIGlzIHRoZSBsYXJnZXN0IHZhbHVlIDxpPms8L2k+CiAgICogc3VjaCB0aGF0OgogICAqIDxibG9ja3F1b3RlPjxwcmU+CiAgICogdGhpcy5jaGFyQXQoaykgPT0gY2gpICYmIChrIDw9IGZyb21JbmRleCkKICAgKiA8L3ByZT48L2Jsb2NrcXVvdGU+CiAgICogaXMgdHJ1ZS4KICAgKgogICAqIEBwYXJhbSAgIGNoICAgICAgICAgIGEgY2hhcmFjdGVyLgogICAqIEBwYXJhbSAgIGZyb21JbmRleCAgIHRoZSBpbmRleCB0byBzdGFydCB0aGUgc2VhcmNoIGZyb20uIFRoZXJlIGlzIG5vCiAgICogICAgICAgICAgcmVzdHJpY3Rpb24gb24gdGhlIHZhbHVlIG9mIDxjb2RlPmZyb21JbmRleDwvY29kZT4uIElmIGl0IGlzCiAgICogICAgICAgICAgZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRvIHRoZSBsZW5ndGggb2YgdGhpcyBzdHJpbmcsIGl0IGhhcwogICAqICAgICAgICAgIHRoZSBzYW1lIGVmZmVjdCBhcyBpZiBpdCB3ZXJlIGVxdWFsIHRvIG9uZSBsZXNzIHRoYW4gdGhlCiAgICogICAgICAgICAgbGVuZ3RoIG9mIHRoaXMgc3RyaW5nOiB0aGlzIGVudGlyZSBzdHJpbmcgbWF5IGJlIHNlYXJjaGVkLgogICAqICAgICAgICAgIElmIGl0IGlzIG5lZ2F0aXZlLCBpdCBoYXMgdGhlIHNhbWUgZWZmZWN0IGFzIGlmIGl0IHdlcmUgLTE6CiAgICogICAgICAgICAgLTEgaXMgcmV0dXJuZWQuCiAgICogQHJldHVybiAgdGhlIGluZGV4IG9mIHRoZSBsYXN0IG9jY3VycmVuY2Ugb2YgdGhlIGNoYXJhY3RlciBpbiB0aGUKICAgKiAgICAgICAgICBjaGFyYWN0ZXIgc2VxdWVuY2UgcmVwcmVzZW50ZWQgYnkgdGhpcyBvYmplY3QgdGhhdCBpcyBsZXNzCiAgICogICAgICAgICAgdGhhbiBvciBlcXVhbCB0byA8Y29kZT5mcm9tSW5kZXg8L2NvZGU+LCBvciA8Y29kZT4tMTwvY29kZT4KICAgKiAgICAgICAgICBpZiB0aGUgY2hhcmFjdGVyIGRvZXMgbm90IG9jY3VyIGJlZm9yZSB0aGF0IHBvaW50LgogICAqLwogIHB1YmxpYyBpbnQgbGFzdEluZGV4T2YoaW50IGNoLCBpbnQgZnJvbUluZGV4KQogIHsKICAgIHJldHVybiBzdHIoKS5sYXN0SW5kZXhPZihjaCwgZnJvbUluZGV4KTsKICB9CgogIC8qKgogICAqIFJldHVybnMgdGhlIGluZGV4IHdpdGhpbiB0aGlzIHN0cmluZyBvZiB0aGUgZmlyc3Qgb2NjdXJyZW5jZSBvZiB0aGUKICAgKiBzcGVjaWZpZWQgc3Vic3RyaW5nLiBUaGUgaW50ZWdlciByZXR1cm5lZCBpcyB0aGUgc21hbGxlc3QgdmFsdWUKICAgKiA8aT5rPC9pPiBzdWNoIHRoYXQ6CiAgICogPGJsb2NrcXVvdGU+PHByZT4KICAgKiB0aGlzLnN0YXJ0c1dpdGgoc3RyLCA8aT5rPC9pPikKICAgKiA8L3ByZT48L2Jsb2NrcXVvdGU+CiAgICogaXMgPGNvZGU+dHJ1ZTwvY29kZT4uCiAgICoKICAgKiBAcGFyYW0gICBzdHIgICBhbnkgc3RyaW5nLgogICAqIEByZXR1cm4gIGlmIHRoZSBzdHJpbmcgYXJndW1lbnQgb2NjdXJzIGFzIGEgc3Vic3RyaW5nIHdpdGhpbiB0aGlzCiAgICogICAgICAgICAgb2JqZWN0LCB0aGVuIHRoZSBpbmRleCBvZiB0aGUgZmlyc3QgY2hhcmFjdGVyIG9mIHRoZSBmaXJzdAogICAqICAgICAgICAgIHN1Y2ggc3Vic3RyaW5nIGlzIHJldHVybmVkOyBpZiBpdCBkb2VzIG5vdCBvY2N1ciBhcyBhCiAgICogICAgICAgICAgc3Vic3RyaW5nLCA8Y29kZT4tMTwvY29kZT4gaXMgcmV0dXJuZWQuCiAgICogQGV4Y2VwdGlvbiBqYXZhLmxhbmcuTnVsbFBvaW50ZXJFeGNlcHRpb24gaWYgPGNvZGU+c3RyPC9jb2RlPiBpcwogICAqICAgICAgICAgIDxjb2RlPm51bGw8L2NvZGU+LgogICAqLwogIHB1YmxpYyBpbnQgaW5kZXhPZihTdHJpbmcgc3RyKQogIHsKICAgIHJldHVybiBzdHIoKS5pbmRleE9mKHN0cik7CiAgfQoKICAvKioKICAgKiBSZXR1cm5zIHRoZSBpbmRleCB3aXRoaW4gdGhpcyBzdHJpbmcgb2YgdGhlIGZpcnN0IG9jY3VycmVuY2Ugb2YgdGhlCiAgICogc3BlY2lmaWVkIHN1YnN0cmluZy4gVGhlIGludGVnZXIgcmV0dXJuZWQgaXMgdGhlIHNtYWxsZXN0IHZhbHVlCiAgICogPGk+azwvaT4gc3VjaCB0aGF0OgogICAqIDxibG9ja3F1b3RlPjxwcmU+CiAgICogdGhpcy5zdGFydHNXaXRoKHN0ciwgPGk+azwvaT4pCiAgICogPC9wcmU+PC9ibG9ja3F1b3RlPgogICAqIGlzIDxjb2RlPnRydWU8L2NvZGU+LgogICAqCiAgICogQHBhcmFtICAgc3RyICAgYW55IHN0cmluZy4KICAgKiBAcmV0dXJuICBpZiB0aGUgc3RyaW5nIGFyZ3VtZW50IG9jY3VycyBhcyBhIHN1YnN0cmluZyB3aXRoaW4gdGhpcwogICAqICAgICAgICAgIG9iamVjdCwgdGhlbiB0aGUgaW5kZXggb2YgdGhlIGZpcnN0IGNoYXJhY3RlciBvZiB0aGUgZmlyc3QKICAgKiAgICAgICAgICBzdWNoIHN1YnN0cmluZyBpcyByZXR1cm5lZDsgaWYgaXQgZG9lcyBub3Qgb2NjdXIgYXMgYQogICAqICAgICAgICAgIHN1YnN0cmluZywgPGNvZGU+LTE8L2NvZGU+IGlzIHJldHVybmVkLgogICAqIEBleGNlcHRpb24gamF2YS5sYW5nLk51bGxQb2ludGVyRXhjZXB0aW9uIGlmIDxjb2RlPnN0cjwvY29kZT4gaXMKICAgKiAgICAgICAgICA8Y29kZT5udWxsPC9jb2RlPi4KICAgKi8KICBwdWJsaWMgaW50IGluZGV4T2YoWE1MU3RyaW5nIHN0cikKICB7CiAgICByZXR1cm4gc3RyKCkuaW5kZXhPZihzdHIudG9TdHJpbmcoKSk7CiAgfQoKICAvKioKICAgKiBSZXR1cm5zIHRoZSBpbmRleCB3aXRoaW4gdGhpcyBzdHJpbmcgb2YgdGhlIGZpcnN0IG9jY3VycmVuY2Ugb2YgdGhlCiAgICogc3BlY2lmaWVkIHN1YnN0cmluZywgc3RhcnRpbmcgYXQgdGhlIHNwZWNpZmllZCBpbmRleC4gVGhlIGludGVnZXIKICAgKiByZXR1cm5lZCBpcyB0aGUgc21hbGxlc3QgdmFsdWUgPGk+azwvaT4gc3VjaCB0aGF0OgogICAqIDxibG9ja3F1b3RlPjxwcmU+CiAgICogdGhpcy5zdGFydHNXaXRoKHN0ciwgPGk+azwvaT4pICYmICg8aT5rPC9pPiA+PSBmcm9tSW5kZXgpCiAgICogPC9wcmU+PC9ibG9ja3F1b3RlPgogICAqIGlzIDxjb2RlPnRydWU8L2NvZGU+LgogICAqIDxwPgogICAqIFRoZXJlIGlzIG5vIHJlc3RyaWN0aW9uIG9uIHRoZSB2YWx1ZSBvZiA8Y29kZT5mcm9tSW5kZXg8L2NvZGU+LiBJZgogICAqIGl0IGlzIG5lZ2F0aXZlLCBpdCBoYXMgdGhlIHNhbWUgZWZmZWN0IGFzIGlmIGl0IHdlcmUgemVybzogdGhpcyBlbnRpcmUKICAgKiBzdHJpbmcgbWF5IGJlIHNlYXJjaGVkLiBJZiBpdCBpcyBncmVhdGVyIHRoYW4gdGhlIGxlbmd0aCBvZiB0aGlzCiAgICogc3RyaW5nLCBpdCBoYXMgdGhlIHNhbWUgZWZmZWN0IGFzIGlmIGl0IHdlcmUgZXF1YWwgdG8gdGhlIGxlbmd0aCBvZgogICAqIHRoaXMgc3RyaW5nOiA8Y29kZT4tMTwvY29kZT4gaXMgcmV0dXJuZWQuCiAgICoKICAgKiBAcGFyYW0gICBzdHIgICAgICAgICB0aGUgc3Vic3RyaW5nIHRvIHNlYXJjaCBmb3IuCiAgICogQHBhcmFtICAgZnJvbUluZGV4ICAgdGhlIGluZGV4IHRvIHN0YXJ0IHRoZSBzZWFyY2ggZnJvbS4KICAgKiBAcmV0dXJuICBJZiB0aGUgc3RyaW5nIGFyZ3VtZW50IG9jY3VycyBhcyBhIHN1YnN0cmluZyB3aXRoaW4gdGhpcwogICAqICAgICAgICAgIG9iamVjdCBhdCBhIHN0YXJ0aW5nIGluZGV4IG5vIHNtYWxsZXIgdGhhbgogICAqICAgICAgICAgIDxjb2RlPmZyb21JbmRleDwvY29kZT4sIHRoZW4gdGhlIGluZGV4IG9mIHRoZSBmaXJzdCBjaGFyYWN0ZXIKICAgKiAgICAgICAgICBvZiB0aGUgZmlyc3Qgc3VjaCBzdWJzdHJpbmcgaXMgcmV0dXJuZWQuIElmIGl0IGRvZXMgbm90IG9jY3VyCiAgICogICAgICAgICAgYXMgYSBzdWJzdHJpbmcgc3RhcnRpbmcgYXQgPGNvZGU+ZnJvbUluZGV4PC9jb2RlPiBvciBiZXlvbmQsCiAgICogICAgICAgICAgPGNvZGU+LTE8L2NvZGU+IGlzIHJldHVybmVkLgogICAqIEBleGNlcHRpb24gamF2YS5sYW5nLk51bGxQb2ludGVyRXhjZXB0aW9uIGlmIDxjb2RlPnN0cjwvY29kZT4gaXMKICAgKiAgICAgICAgICA8Y29kZT5udWxsPC9jb2RlPgogICAqLwogIHB1YmxpYyBpbnQgaW5kZXhPZihTdHJpbmcgc3RyLCBpbnQgZnJvbUluZGV4KQogIHsKICAgIHJldHVybiBzdHIoKS5pbmRleE9mKHN0ciwgZnJvbUluZGV4KTsKICB9CgogIC8qKgogICAqIFJldHVybnMgdGhlIGluZGV4IHdpdGhpbiB0aGlzIHN0cmluZyBvZiB0aGUgcmlnaHRtb3N0IG9jY3VycmVuY2UKICAgKiBvZiB0aGUgc3BlY2lmaWVkIHN1YnN0cmluZy4gIFRoZSByaWdodG1vc3QgZW1wdHkgc3RyaW5nICIiIGlzCiAgICogY29uc2lkZXJlZCB0byBvY2N1ciBhdCB0aGUgaW5kZXggdmFsdWUgPGNvZGU+dGhpcy5sZW5ndGgoKTwvY29kZT4uCiAgICogVGhlIHJldHVybmVkIGluZGV4IGlzIHRoZSBsYXJnZXN0IHZhbHVlIDxpPms8L2k+IHN1Y2ggdGhhdAogICAqIDxibG9ja3F1b3RlPjxwcmU+CiAgICogdGhpcy5zdGFydHNXaXRoKHN0ciwgaykKICAgKiA8L3ByZT48L2Jsb2NrcXVvdGU+CiAgICogaXMgdHJ1ZS4KICAgKgogICAqIEBwYXJhbSAgIHN0ciAgIHRoZSBzdWJzdHJpbmcgdG8gc2VhcmNoIGZvci4KICAgKiBAcmV0dXJuICBpZiB0aGUgc3RyaW5nIGFyZ3VtZW50IG9jY3VycyBvbmUgb3IgbW9yZSB0aW1lcyBhcyBhIHN1YnN0cmluZwogICAqICAgICAgICAgIHdpdGhpbiB0aGlzIG9iamVjdCwgdGhlbiB0aGUgaW5kZXggb2YgdGhlIGZpcnN0IGNoYXJhY3RlciBvZgogICAqICAgICAgICAgIHRoZSBsYXN0IHN1Y2ggc3Vic3RyaW5nIGlzIHJldHVybmVkLiBJZiBpdCBkb2VzIG5vdCBvY2N1ciBhcwogICAqICAgICAgICAgIGEgc3Vic3RyaW5nLCA8Y29kZT4tMTwvY29kZT4gaXMgcmV0dXJuZWQuCiAgICogQGV4Y2VwdGlvbiBqYXZhLmxhbmcuTnVsbFBvaW50ZXJFeGNlcHRpb24gIGlmIDxjb2RlPnN0cjwvY29kZT4gaXMKICAgKiAgICAgICAgICA8Y29kZT5udWxsPC9jb2RlPi4KICAgKi8KICBwdWJsaWMgaW50IGxhc3RJbmRleE9mKFN0cmluZyBzdHIpCiAgewogICAgcmV0dXJuIHN0cigpLmxhc3RJbmRleE9mKHN0cik7CiAgfQoKICAvKioKICAgKiBSZXR1cm5zIHRoZSBpbmRleCB3aXRoaW4gdGhpcyBzdHJpbmcgb2YgdGhlIGxhc3Qgb2NjdXJyZW5jZSBvZgogICAqIHRoZSBzcGVjaWZpZWQgc3Vic3RyaW5nLgogICAqCiAgICogQHBhcmFtICAgc3RyICAgICAgICAgdGhlIHN1YnN0cmluZyB0byBzZWFyY2ggZm9yLgogICAqIEBwYXJhbSAgIGZyb21JbmRleCAgIHRoZSBpbmRleCB0byBzdGFydCB0aGUgc2VhcmNoIGZyb20uIFRoZXJlIGlzIG5vCiAgICogICAgICAgICAgcmVzdHJpY3Rpb24gb24gdGhlIHZhbHVlIG9mIGZyb21JbmRleC4gSWYgaXQgaXMgZ3JlYXRlciB0aGFuCiAgICogICAgICAgICAgdGhlIGxlbmd0aCBvZiB0aGlzIHN0cmluZywgaXQgaGFzIHRoZSBzYW1lIGVmZmVjdCBhcyBpZiBpdAogICAqICAgICAgICAgIHdlcmUgZXF1YWwgdG8gdGhlIGxlbmd0aCBvZiB0aGlzIHN0cmluZzogdGhpcyBlbnRpcmUgc3RyaW5nCiAgICogICAgICAgICAgbWF5IGJlIHNlYXJjaGVkLiBJZiBpdCBpcyBuZWdhdGl2ZSwgaXQgaGFzIHRoZSBzYW1lIGVmZmVjdAogICAqICAgICAgICAgIGFzIGlmIGl0IHdlcmUgLTE6IC0xIGlzIHJldHVybmVkLgogICAqIEByZXR1cm4gIElmIHRoZSBzdHJpbmcgYXJndW1lbnQgb2NjdXJzIG9uZSBvciBtb3JlIHRpbWVzIGFzIGEgc3Vic3RyaW5nCiAgICogICAgICAgICAgd2l0aGluIHRoaXMgb2JqZWN0IGF0IGEgc3RhcnRpbmcgaW5kZXggbm8gZ3JlYXRlciB0aGFuCiAgICogICAgICAgICAgPGNvZGU+ZnJvbUluZGV4PC9jb2RlPiwgdGhlbiB0aGUgaW5kZXggb2YgdGhlIGZpcnN0IGNoYXJhY3RlciBvZgogICAqICAgICAgICAgIHRoZSBsYXN0IHN1Y2ggc3Vic3RyaW5nIGlzIHJldHVybmVkLiBJZiBpdCBkb2VzIG5vdCBvY2N1ciBhcyBhCiAgICogICAgICAgICAgc3Vic3RyaW5nIHN0YXJ0aW5nIGF0IDxjb2RlPmZyb21JbmRleDwvY29kZT4gb3IgZWFybGllciwKICAgKiAgICAgICAgICA8Y29kZT4tMTwvY29kZT4gaXMgcmV0dXJuZWQuCiAgICogQGV4Y2VwdGlvbiBqYXZhLmxhbmcuTnVsbFBvaW50ZXJFeGNlcHRpb24gaWYgPGNvZGU+c3RyPC9jb2RlPiBpcwogICAqICAgICAgICAgIDxjb2RlPm51bGw8L2NvZGU+LgogICAqLwogIHB1YmxpYyBpbnQgbGFzdEluZGV4T2YoU3RyaW5nIHN0ciwgaW50IGZyb21JbmRleCkKICB7CiAgICByZXR1cm4gc3RyKCkubGFzdEluZGV4T2Yoc3RyLCBmcm9tSW5kZXgpOwogIH0KCiAgLyoqCiAgICogUmV0dXJucyBhIG5ldyBzdHJpbmcgdGhhdCBpcyBhIHN1YnN0cmluZyBvZiB0aGlzIHN0cmluZy4gVGhlCiAgICogc3Vic3RyaW5nIGJlZ2lucyB3aXRoIHRoZSBjaGFyYWN0ZXIgYXQgdGhlIHNwZWNpZmllZCBpbmRleCBhbmQKICAgKiBleHRlbmRzIHRvIHRoZSBlbmQgb2YgdGhpcyBzdHJpbmcuIDxwPgogICAqIEV4YW1wbGVzOgogICAqIDxibG9ja3F1b3RlPjxwcmU+CiAgICogInVuaGFwcHkiLnN1YnN0cmluZygyKSByZXR1cm5zICJoYXBweSIKICAgKiAiSGFyYmlzb24iLnN1YnN0cmluZygzKSByZXR1cm5zICJiaXNvbiIKICAgKiAiZW1wdGluZXNzIi5zdWJzdHJpbmcoOSkgcmV0dXJucyAiIiAoYW4gZW1wdHkgc3RyaW5nKQogICAqIDwvcHJlPjwvYmxvY2txdW90ZT4KICAgKgogICAqIEBwYXJhbSAgICAgIGJlZ2luSW5kZXggICB0aGUgYmVnaW5uaW5nIGluZGV4LCBpbmNsdXNpdmUuCiAgICogQHJldHVybiAgICAgdGhlIHNwZWNpZmllZCBzdWJzdHJpbmcuCiAgICogQGV4Y2VwdGlvbiAgSW5kZXhPdXRPZkJvdW5kc0V4Y2VwdGlvbiAgaWYKICAgKiAgICAgICAgICAgICA8Y29kZT5iZWdpbkluZGV4PC9jb2RlPiBpcyBuZWdhdGl2ZSBvciBsYXJnZXIgdGhhbiB0aGUKICAgKiAgICAgICAgICAgICBsZW5ndGggb2YgdGhpcyA8Y29kZT5TdHJpbmc8L2NvZGU+IG9iamVjdC4KICAgKi8KICBwdWJsaWMgWE1MU3RyaW5nIHN1YnN0cmluZyhpbnQgYmVnaW5JbmRleCkKICB7CiAgICByZXR1cm4gbmV3IFhTdHJpbmcoc3RyKCkuc3Vic3RyaW5nKGJlZ2luSW5kZXgpKTsKICB9CgogIC8qKgogICAqIFJldHVybnMgYSBuZXcgc3RyaW5nIHRoYXQgaXMgYSBzdWJzdHJpbmcgb2YgdGhpcyBzdHJpbmcuIFRoZQogICAqIHN1YnN0cmluZyBiZWdpbnMgYXQgdGhlIHNwZWNpZmllZCA8Y29kZT5iZWdpbkluZGV4PC9jb2RlPiBhbmQKICAgKiBleHRlbmRzIHRvIHRoZSBjaGFyYWN0ZXIgYXQgaW5kZXggPGNvZGU+ZW5kSW5kZXggLSAxPC9jb2RlPi4KICAgKiBUaHVzIHRoZSBsZW5ndGggb2YgdGhlIHN1YnN0cmluZyBpcyA8Y29kZT5lbmRJbmRleC1iZWdpbkluZGV4PC9jb2RlPi4KICAgKgogICAqIEBwYXJhbSAgICAgIGJlZ2luSW5kZXggICB0aGUgYmVnaW5uaW5nIGluZGV4LCBpbmNsdXNpdmUuCiAgICogQHBhcmFtICAgICAgZW5kSW5kZXggICAgIHRoZSBlbmRpbmcgaW5kZXgsIGV4Y2x1c2l2ZS4KICAgKiBAcmV0dXJuICAgICB0aGUgc3BlY2lmaWVkIHN1YnN0cmluZy4KICAgKiBAZXhjZXB0aW9uICBJbmRleE91dE9mQm91bmRzRXhjZXB0aW9uICBpZiB0aGUKICAgKiAgICAgICAgICAgICA8Y29kZT5iZWdpbkluZGV4PC9jb2RlPiBpcyBuZWdhdGl2ZSwgb3IKICAgKiAgICAgICAgICAgICA8Y29kZT5lbmRJbmRleDwvY29kZT4gaXMgbGFyZ2VyIHRoYW4gdGhlIGxlbmd0aCBvZgogICAqICAgICAgICAgICAgIHRoaXMgPGNvZGU+U3RyaW5nPC9jb2RlPiBvYmplY3QsIG9yCiAgICogICAgICAgICAgICAgPGNvZGU+YmVnaW5JbmRleDwvY29kZT4gaXMgbGFyZ2VyIHRoYW4KICAgKiAgICAgICAgICAgICA8Y29kZT5lbmRJbmRleDwvY29kZT4uCiAgICovCiAgcHVibGljIFhNTFN0cmluZyBzdWJzdHJpbmcoaW50IGJlZ2luSW5kZXgsIGludCBlbmRJbmRleCkKICB7CiAgICByZXR1cm4gbmV3IFhTdHJpbmcoc3RyKCkuc3Vic3RyaW5nKGJlZ2luSW5kZXgsIGVuZEluZGV4KSk7CiAgfQoKICAvKioKICAgKiBDb25jYXRlbmF0ZXMgdGhlIHNwZWNpZmllZCBzdHJpbmcgdG8gdGhlIGVuZCBvZiB0aGlzIHN0cmluZy4KICAgKgogICAqIEBwYXJhbSAgIHN0ciAgIHRoZSA8Y29kZT5TdHJpbmc8L2NvZGU+IHRoYXQgaXMgY29uY2F0ZW5hdGVkIHRvIHRoZSBlbmQKICAgKiAgICAgICAgICAgICAgICBvZiB0aGlzIDxjb2RlPlN0cmluZzwvY29kZT4uCiAgICogQHJldHVybiAgYSBzdHJpbmcgdGhhdCByZXByZXNlbnRzIHRoZSBjb25jYXRlbmF0aW9uIG9mIHRoaXMgb2JqZWN0J3MKICAgKiAgICAgICAgICBjaGFyYWN0ZXJzIGZvbGxvd2VkIGJ5IHRoZSBzdHJpbmcgYXJndW1lbnQncyBjaGFyYWN0ZXJzLgogICAqIEBleGNlcHRpb24gamF2YS5sYW5nLk51bGxQb2ludGVyRXhjZXB0aW9uIGlmIDxjb2RlPnN0cjwvY29kZT4gaXMKICAgKiAgICAgICAgICA8Y29kZT5udWxsPC9jb2RlPi4KICAgKi8KICBwdWJsaWMgWE1MU3RyaW5nIGNvbmNhdChTdHJpbmcgc3RyKQogIHsKCiAgICAvLyAlUkVWSUVXJSBNYWtlIGFuIEZTQiBoZXJlPwogICAgcmV0dXJuIG5ldyBYU3RyaW5nKHN0cigpLmNvbmNhdChzdHIpKTsKICB9CgogIC8qKgogICAqIENvbnZlcnRzIGFsbCBvZiB0aGUgY2hhcmFjdGVycyBpbiB0aGlzIDxjb2RlPlN0cmluZzwvY29kZT4gdG8gbG93ZXIKICAgKiBjYXNlIHVzaW5nIHRoZSBydWxlcyBvZiB0aGUgZ2l2ZW4gPGNvZGU+TG9jYWxlPC9jb2RlPi4KICAgKgogICAqIEBwYXJhbSBsb2NhbGUgdXNlIHRoZSBjYXNlIHRyYW5zZm9ybWF0aW9uIHJ1bGVzIGZvciB0aGlzIGxvY2FsZQogICAqIEByZXR1cm4gdGhlIFN0cmluZywgY29udmVydGVkIHRvIGxvd2VyY2FzZS4KICAgKiBAc2VlICAgICBqYXZhLmxhbmcuQ2hhcmFjdGVyI3RvTG93ZXJDYXNlKGNoYXIpCiAgICogQHNlZSAgICAgamF2YS5sYW5nLlN0cmluZyN0b1VwcGVyQ2FzZShMb2NhbGUpCiAgICovCiAgcHVibGljIFhNTFN0cmluZyB0b0xvd2VyQ2FzZShMb2NhbGUgbG9jYWxlKQogIHsKICAgIHJldHVybiBuZXcgWFN0cmluZyhzdHIoKS50b0xvd2VyQ2FzZShsb2NhbGUpKTsKICB9CgogIC8qKgogICAqIENvbnZlcnRzIGFsbCBvZiB0aGUgY2hhcmFjdGVycyBpbiB0aGlzIDxjb2RlPlN0cmluZzwvY29kZT4gdG8gbG93ZXIKICAgKiBjYXNlIHVzaW5nIHRoZSBydWxlcyBvZiB0aGUgZGVmYXVsdCBsb2NhbGUsIHdoaWNoIGlzIHJldHVybmVkCiAgICogYnkgPGNvZGU+TG9jYWxlLmdldERlZmF1bHQ8L2NvZGU+LgogICAqIDxwPgogICAqCiAgICogQHJldHVybiAgdGhlIHN0cmluZywgY29udmVydGVkIHRvIGxvd2VyY2FzZS4KICAgKiBAc2VlICAgICBqYXZhLmxhbmcuQ2hhcmFjdGVyI3RvTG93ZXJDYXNlKGNoYXIpCiAgICogQHNlZSAgICAgamF2YS5sYW5nLlN0cmluZyN0b0xvd2VyQ2FzZShMb2NhbGUpCiAgICovCiAgcHVibGljIFhNTFN0cmluZyB0b0xvd2VyQ2FzZSgpCiAgewogICAgcmV0dXJuIG5ldyBYU3RyaW5nKHN0cigpLnRvTG93ZXJDYXNlKCkpOwogIH0KCiAgLyoqCiAgICogQ29udmVydHMgYWxsIG9mIHRoZSBjaGFyYWN0ZXJzIGluIHRoaXMgPGNvZGU+U3RyaW5nPC9jb2RlPiB0byB1cHBlcgogICAqIGNhc2UgdXNpbmcgdGhlIHJ1bGVzIG9mIHRoZSBnaXZlbiBsb2NhbGUuCiAgICogQHBhcmFtIGxvY2FsZSB1c2UgdGhlIGNhc2UgdHJhbnNmb3JtYXRpb24gcnVsZXMgZm9yIHRoaXMgbG9jYWxlCiAgICogQHJldHVybiB0aGUgU3RyaW5nLCBjb252ZXJ0ZWQgdG8gdXBwZXJjYXNlLgogICAqIEBzZWUgICAgIGphdmEubGFuZy5DaGFyYWN0ZXIjdG9VcHBlckNhc2UoY2hhcikKICAgKiBAc2VlICAgICBqYXZhLmxhbmcuU3RyaW5nI3RvTG93ZXJDYXNlKExvY2FsZSkKICAgKi8KICBwdWJsaWMgWE1MU3RyaW5nIHRvVXBwZXJDYXNlKExvY2FsZSBsb2NhbGUpCiAgewogICAgcmV0dXJuIG5ldyBYU3RyaW5nKHN0cigpLnRvVXBwZXJDYXNlKGxvY2FsZSkpOwogIH0KCiAgLyoqCiAgICogQ29udmVydHMgYWxsIG9mIHRoZSBjaGFyYWN0ZXJzIGluIHRoaXMgPGNvZGU+U3RyaW5nPC9jb2RlPiB0byB1cHBlcgogICAqIGNhc2UgdXNpbmcgdGhlIHJ1bGVzIG9mIHRoZSBkZWZhdWx0IGxvY2FsZSwgd2hpY2ggaXMgcmV0dXJuZWQKICAgKiBieSA8Y29kZT5Mb2NhbGUuZ2V0RGVmYXVsdDwvY29kZT4uCiAgICoKICAgKiA8cD4KICAgKiBJZiBubyBjaGFyYWN0ZXIgaW4gdGhpcyBzdHJpbmcgaGFzIGEgZGlmZmVyZW50IHVwcGVyY2FzZSB2ZXJzaW9uLAogICAqIGJhc2VkIG9uIGNhbGxpbmcgdGhlIDxjb2RlPnRvVXBwZXJDYXNlPC9jb2RlPiBtZXRob2QgZGVmaW5lZCBieQogICAqIDxjb2RlPkNoYXJhY3RlcjwvY29kZT4sIHRoZW4gdGhlIG9yaWdpbmFsIHN0cmluZyBpcyByZXR1cm5lZC4KICAgKiA8cD4KICAgKiBPdGhlcndpc2UsIHRoaXMgbWV0aG9kIGNyZWF0ZXMgYSBuZXcgPGNvZGU+U3RyaW5nPC9jb2RlPiBvYmplY3QKICAgKiByZXByZXNlbnRpbmcgYSBjaGFyYWN0ZXIgc2VxdWVuY2UgaWRlbnRpY2FsIGluIGxlbmd0aCB0byB0aGUKICAgKiBjaGFyYWN0ZXIgc2VxdWVuY2UgcmVwcmVzZW50ZWQgYnkgdGhpcyA8Y29kZT5TdHJpbmc8L2NvZGU+IG9iamVjdCBhbmQKICAgKiB3aXRoIGV2ZXJ5IGNoYXJhY3RlciBlcXVhbCB0byB0aGUgcmVzdWx0IG9mIGFwcGx5aW5nIHRoZSBtZXRob2QKICAgKiA8Y29kZT5DaGFyYWN0ZXIudG9VcHBlckNhc2U8L2NvZGU+IHRvIHRoZSBjb3JyZXNwb25kaW5nIGNoYXJhY3RlciBvZgogICAqIHRoaXMgPGNvZGU+U3RyaW5nPC9jb2RlPiBvYmplY3QuIDxwPgogICAqIEV4YW1wbGVzOgogICAqIDxibG9ja3F1b3RlPjxwcmU+CiAgICogIkZhaHJ2ZXJnbvxnZW4iLnRvVXBwZXJDYXNlKCkgcmV0dXJucyAiRkFIUlZFUkdO3EdFTiIKICAgKiAiVmlzaXQgTGp1YmluamUhIi50b1VwcGVyQ2FzZSgpIHJldHVybnMgIlZJU0lUIExKVUJJTkpFISIKICAgKiA8L3ByZT48L2Jsb2NrcXVvdGU+CiAgICoKICAgKiBAcmV0dXJuICB0aGUgc3RyaW5nLCBjb252ZXJ0ZWQgdG8gdXBwZXJjYXNlLgogICAqIEBzZWUgICAgIGphdmEubGFuZy5DaGFyYWN0ZXIjdG9VcHBlckNhc2UoY2hhcikKICAgKiBAc2VlICAgICBqYXZhLmxhbmcuU3RyaW5nI3RvVXBwZXJDYXNlKExvY2FsZSkKICAgKi8KICBwdWJsaWMgWE1MU3RyaW5nIHRvVXBwZXJDYXNlKCkKICB7CiAgICByZXR1cm4gbmV3IFhTdHJpbmcoc3RyKCkudG9VcHBlckNhc2UoKSk7CiAgfQoKICAvKioKICAgKiBSZW1vdmVzIHdoaXRlIHNwYWNlIGZyb20gYm90aCBlbmRzIG9mIHRoaXMgc3RyaW5nLgogICAqCiAgICogQHJldHVybiAgdGhpcyBzdHJpbmcsIHdpdGggd2hpdGUgc3BhY2UgcmVtb3ZlZCBmcm9tIHRoZSBmcm9udCBhbmQgZW5kLgogICAqLwogIHB1YmxpYyBYTUxTdHJpbmcgdHJpbSgpCiAgewogICAgcmV0dXJuIG5ldyBYU3RyaW5nKHN0cigpLnRyaW0oKSk7CiAgfQoKICAvKioKICAgKiBSZXR1cm5zIHdoZXRoZXIgdGhlIHNwZWNpZmllZCA8dmFyPmNoPC92YXI+IGNvbmZvcm1zIHRvIHRoZSBYTUwgMS4wIGRlZmluaXRpb24KICAgKiBvZiB3aGl0ZXNwYWNlLiAgUmVmZXIgdG8gPEEgaHJlZj0iaHR0cDovL3d3dy53My5vcmcvVFIvMTk5OC9SRUMteG1sLTE5OTgwMjEwI05ULVMiPgogICAqIHRoZSBkZWZpbml0aW9uIG9mIDxDT0RFPlM8L0NPREU+PC9BPiBmb3IgZGV0YWlscy4KICAgKiBAcGFyYW0gICBjaCAgICAgIENoYXJhY3RlciB0byBjaGVjayBhcyBYTUwgd2hpdGVzcGFjZS4KICAgKiBAcmV0dXJuICAgICAgICAgID10cnVlIGlmIDx2YXI+Y2g8L3Zhcj4gaXMgWE1MIHdoaXRlc3BhY2U7IG90aGVyd2lzZSA9ZmFsc2UuCiAgICovCiAgcHJpdmF0ZSBzdGF0aWMgYm9vbGVhbiBpc1NwYWNlKGNoYXIgY2gpCiAgewogICAgcmV0dXJuIFhNTENoYXJhY3RlclJlY29nbml6ZXIuaXNXaGl0ZVNwYWNlKGNoKTsgIC8vIFRha2UgdGhlIGVhc3kgd2F5IG91dCBmb3Igbm93LgogIH0KCiAgLyoqCiAgICogQ29uZGl0aW9uYWxseSB0cmltIGFsbCBsZWFkaW5nIGFuZCB0cmFpbGluZyB3aGl0ZXNwYWNlIGluIHRoZSBzcGVjaWZpZWQgU3RyaW5nLgogICAqIEFsbCBzdHJpbmdzIG9mIHdoaXRlIHNwYWNlIGFyZQogICAqIHJlcGxhY2VkIGJ5IGEgc2luZ2xlIHNwYWNlIGNoYXJhY3RlciAoI3gyMCksIGV4Y2VwdCBzcGFjZXMgYWZ0ZXIgcHVuY3R1YXRpb24gd2hpY2gKICAgKiByZWNlaXZlIGRvdWJsZSBzcGFjZXMgaWYgZG91YmxlUHVuY3R1YXRpb25TcGFjZXMgaXMgdHJ1ZS4KICAgKiBUaGlzIGZ1bmN0aW9uIG1heSBiZSB1c2VmdWwgdG8gYSBmb3JtYXR0ZXIsIGJ1dCB0byBnZXQgZmlyc3QgY2xhc3MKICAgKiByZXN1bHRzLCB0aGUgZm9ybWF0dGVyIHNob3VsZCBwcm9iYWJseSBkbyBpdCdzIG93biB3aGl0ZSBzcGFjZSBoYW5kbGluZwogICAqIGJhc2VkIG9uIHRoZSBzZW1hbnRpY3Mgb2YgdGhlIGZvcm1hdHRpbmcgb2JqZWN0LgogICAqCiAgICogQHBhcmFtICAgdHJpbUhlYWQgICAgVHJpbSBsZWFkaW5nIHdoaXRlc3BhY2U/CiAgICogQHBhcmFtICAgdHJpbVRhaWwgICAgVHJpbSB0cmFpbGluZyB3aGl0ZXNwYWNlPwogICAqIEBwYXJhbSAgIGRvdWJsZVB1bmN0dWF0aW9uU3BhY2VzICAgIFVzZSBkb3VibGUgc3BhY2VzIGZvciBwdW5jdHVhdGlvbj8KICAgKiBAcmV0dXJuICAgICAgICAgICAgICBUaGUgdHJpbW1lZCBzdHJpbmcuCiAgICovCiAgcHVibGljIFhNTFN0cmluZyBmaXhXaGl0ZVNwYWNlKGJvb2xlYW4gdHJpbUhlYWQsIGJvb2xlYW4gdHJpbVRhaWwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJvb2xlYW4gZG91YmxlUHVuY3R1YXRpb25TcGFjZXMpCiAgewoKICAgIC8vICVPUFQlICEhISEhISEKICAgIGludCBsZW4gPSB0aGlzLmxlbmd0aCgpOwogICAgY2hhcltdIGJ1ZiA9IG5ldyBjaGFyW2xlbl07CgogICAgdGhpcy5nZXRDaGFycygwLCBsZW4sIGJ1ZiwgMCk7CgogICAgYm9vbGVhbiBlZGl0ID0gZmFsc2U7CiAgICBpbnQgczsKCiAgICBmb3IgKHMgPSAwOyBzIDwgbGVuOyBzKyspCiAgICB7CiAgICAgIGlmIChpc1NwYWNlKGJ1ZltzXSkpCiAgICAgIHsKICAgICAgICBicmVhazsKICAgICAgfQogICAgfQoKICAgIC8qIHJlcGxhY2UgUyB0byAnICcuIGFuZCAnICcrIC0+IHNpbmdsZSAnICcuICovCiAgICBpbnQgZCA9IHM7CiAgICBib29sZWFuIHByZXMgPSBmYWxzZTsKCiAgICBmb3IgKDsgcyA8IGxlbjsgcysrKQogICAgewogICAgICBjaGFyIGMgPSBidWZbc107CgogICAgICBpZiAoaXNTcGFjZShjKSkKICAgICAgewogICAgICAgIGlmICghcHJlcykKICAgICAgICB7CiAgICAgICAgICBpZiAoJyAnICE9IGMpCiAgICAgICAgICB7CiAgICAgICAgICAgIGVkaXQgPSB0cnVlOwogICAgICAgICAgfQoKICAgICAgICAgIGJ1ZltkKytdID0gJyAnOwoKICAgICAgICAgIGlmIChkb3VibGVQdW5jdHVhdGlvblNwYWNlcyAmJiAocyAhPSAwKSkKICAgICAgICAgIHsKICAgICAgICAgICAgY2hhciBwcmV2Q2hhciA9IGJ1ZltzIC0gMV07CgogICAgICAgICAgICBpZiAoISgocHJldkNoYXIgPT0gJy4nKSB8fCAocHJldkNoYXIgPT0gJyEnKQogICAgICAgICAgICAgICAgICB8fCAocHJldkNoYXIgPT0gJz8nKSkpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICBwcmVzID0gdHJ1ZTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgZWxzZQogICAgICAgICAgewogICAgICAgICAgICBwcmVzID0gdHJ1ZTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgZWxzZQogICAgICAgIHsKICAgICAgICAgIGVkaXQgPSB0cnVlOwogICAgICAgICAgcHJlcyA9IHRydWU7CiAgICAgICAgfQogICAgICB9CiAgICAgIGVsc2UKICAgICAgewogICAgICAgIGJ1ZltkKytdID0gYzsKICAgICAgICBwcmVzID0gZmFsc2U7CiAgICAgIH0KICAgIH0KCiAgICBpZiAodHJpbVRhaWwgJiYgMSA8PSBkICYmICcgJyA9PSBidWZbZCAtIDFdKQogICAgewogICAgICBlZGl0ID0gdHJ1ZTsKCiAgICAgIGQtLTsKICAgIH0KCiAgICBpbnQgc3RhcnQgPSAwOwoKICAgIGlmICh0cmltSGVhZCAmJiAwIDwgZCAmJiAnICcgPT0gYnVmWzBdKQogICAgewogICAgICBlZGl0ID0gdHJ1ZTsKCiAgICAgIHN0YXJ0Kys7CiAgICB9CgogICAgWE1MU3RyaW5nRmFjdG9yeSB4c2YgPSBYTUxTdHJpbmdGYWN0b3J5SW1wbC5nZXRGYWN0b3J5KCk7CgogICAgcmV0dXJuIGVkaXQgPyB4c2YubmV3c3RyKG5ldyBTdHJpbmcoYnVmLCBzdGFydCwgZCAtIHN0YXJ0KSkgOiB0aGlzOwogIH0KICAKICAvKioKICAgKiBAc2VlIFhQYXRoVmlzaXRhYmxlI2NhbGxWaXNpdG9ycyhFeHByZXNzaW9uT3duZXIsIFhQYXRoVmlzaXRvcikKICAgKi8KICBwdWJsaWMgdm9pZCBjYWxsVmlzaXRvcnMoRXhwcmVzc2lvbk93bmVyIG93bmVyLCBYUGF0aFZpc2l0b3IgdmlzaXRvcikKICB7CiAgCXZpc2l0b3IudmlzaXRTdHJpbmdMaXRlcmFsKG93bmVyLCB0aGlzKTsKICB9Cgp9Cg==