LyoKICogTGljZW5zZWQgdG8gdGhlIEFwYWNoZSBTb2Z0d2FyZSBGb3VuZGF0aW9uIChBU0YpIHVuZGVyIG9uZSBvciBtb3JlCiAqIGNvbnRyaWJ1dG9yIGxpY2Vuc2UgYWdyZWVtZW50cy4gIFNlZSB0aGUgTk9USUNFIGZpbGUgZGlzdHJpYnV0ZWQgd2l0aAogKiB0aGlzIHdvcmsgZm9yIGFkZGl0aW9uYWwgaW5mb3JtYXRpb24gcmVnYXJkaW5nIGNvcHlyaWdodCBvd25lcnNoaXAuCiAqIFRoZSBBU0YgbGljZW5zZXMgdGhpcyBmaWxlIHRvIFlvdSB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wCiAqICh0aGUgIkxpY2Vuc2UiKTsgeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoCiAqIHRoZSBMaWNlbnNlLiAgWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0CiAqIAogKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMAogKiAKICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZQogKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiAiQVMgSVMiIEJBU0lTLAogKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC4KICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZAogKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS4KICovCnBhY2thZ2UgY29tLnN1bi5zeW5kaWNhdGlvbi5pby5pbXBsOwoKaW1wb3J0IGphdmEudXRpbC5BcnJheUxpc3Q7CmltcG9ydCBqYXZhLnV0aWwuQ29sbGVjdGlvbnM7CmltcG9ydCBqYXZhLnV0aWwuSGFzaE1hcDsKaW1wb3J0IGphdmEudXRpbC5JdGVyYXRvcjsKaW1wb3J0IGphdmEudXRpbC5MaXN0OwppbXBvcnQgamF2YS51dGlsLk1hcDsKCmltcG9ydCBjb20uc3VuLnN5bmRpY2F0aW9uLmlvLkRlbGVnYXRpbmdNb2R1bGVHZW5lcmF0b3I7CmltcG9ydCBjb20uc3VuLnN5bmRpY2F0aW9uLmlvLkRlbGVnYXRpbmdNb2R1bGVQYXJzZXI7CmltcG9ydCBjb20uc3VuLnN5bmRpY2F0aW9uLmlvLldpcmVGZWVkR2VuZXJhdG9yOwppbXBvcnQgY29tLnN1bi5zeW5kaWNhdGlvbi5pby5XaXJlRmVlZFBhcnNlcjsKCi8qKgogKiA8cD4KICogT3ZlcnJpZGUgdGhlIGRlZmF1bHQgUm9tZSBwbHVnaW4gbWFuYWdlciB0byBiZSBPU0dpIGNvbXBsaWFudCBhcm91bmQgY2xhc3Nsb2FkZXIuCiAqIDwvcD4KICogCiAqIEBhdXRob3IgQWxlamFuZHJvIEFiZGVsbnVyCiAqIEBhdXRob3IgSmVhbi1CYXB0aXN0ZSBPbm9mcukKICogQGF1dGhvciBMdWthc3ogRHl3aWNraQogKi8KcHVibGljIGFic3RyYWN0IGNsYXNzIFBsdWdpbk1hbmFnZXIgewogICAgCiAgICBwcml2YXRlIFN0cmluZ1tdIF9wcm9wZXJ0eVZhbHVlczsKICAgIHByaXZhdGUgTWFwIF9wbHVnaW5zTWFwOwogICAgcHJpdmF0ZSBMaXN0IF9wbHVnaW5zTGlzdDsKICAgIHByaXZhdGUgTGlzdCBfa2V5czsKICAgIHByaXZhdGUgV2lyZUZlZWRQYXJzZXIgX3BhcmVudFBhcnNlcjsKICAgIHByaXZhdGUgV2lyZUZlZWRHZW5lcmF0b3IgX3BhcmVudEdlbmVyYXRvcjsKICAgIAogICAgLyoqCiAgICAgKiA8cD4KICAgICAqIENyZWF0ZXMgYSBQbHVnaW5NYW5hZ2VyLgogICAgICogPHA+CiAgICAgKiAKICAgICAqIEBwYXJhbSBwcm9wZXJ0eUtleSBwcm9wZXJ0eSBrZXkgZGVmaW5pbmcgdGhlIHBsdWdpbnMgY2xhc3Nlcy4gCiAgICAgKi8KICAgIHByb3RlY3RlZCBQbHVnaW5NYW5hZ2VyKFN0cmluZyBwcm9wZXJ0eUtleSkgewogICAgICAgIHRoaXMocHJvcGVydHlLZXksIG51bGwsIG51bGwpOwogICAgfQogICAgCiAgICBwcm90ZWN0ZWQgUGx1Z2luTWFuYWdlcihTdHJpbmcgcHJvcGVydHlLZXksIFdpcmVGZWVkUGFyc2VyIHBhcmVudFBhcnNlciwgV2lyZUZlZWRHZW5lcmF0b3IgcGFyZW50R2VuZXJhdG9yKSB7CiAgICAgICAgX3BhcmVudFBhcnNlciA9IHBhcmVudFBhcnNlcjsKICAgICAgICBfcGFyZW50R2VuZXJhdG9yID0gcGFyZW50R2VuZXJhdG9yOwogICAgICAgIF9wcm9wZXJ0eVZhbHVlcyA9IFByb3BlcnRpZXNMb2FkZXIuZ2V0UHJvcGVydGllc0xvYWRlcigpLmdldFRva2VuaXplZFByb3BlcnR5KHByb3BlcnR5S2V5LCAiLCAiKTsKICAgICAgICBsb2FkUGx1Z2lucygpOwogICAgICAgIF9wbHVnaW5zTWFwID0gQ29sbGVjdGlvbnMudW5tb2RpZmlhYmxlTWFwKF9wbHVnaW5zTWFwKTsKICAgICAgICBfcGx1Z2luc0xpc3QgPSBDb2xsZWN0aW9ucy51bm1vZGlmaWFibGVMaXN0KF9wbHVnaW5zTGlzdCk7CiAgICAgICAgX2tleXMgPSBDb2xsZWN0aW9ucy51bm1vZGlmaWFibGVMaXN0KG5ldyBBcnJheUxpc3QoX3BsdWdpbnNNYXAua2V5U2V0KCkpKTsKICAgIH0KICAgIAogICAgcHJvdGVjdGVkIGFic3RyYWN0IFN0cmluZyBnZXRLZXkoT2JqZWN0IG9iaik7CiAgICAKICAgIHByb3RlY3RlZCBMaXN0IGdldEtleXMoKSB7CiAgICAgICAgcmV0dXJuIF9rZXlzOwogICAgfQogICAgCiAgICBwcm90ZWN0ZWQgTGlzdCBnZXRQbHVnaW5zKCkgewogICAgICAgIHJldHVybiBfcGx1Z2luc0xpc3Q7CiAgICB9CiAgICAKICAgIHByb3RlY3RlZCBNYXAgZ2V0UGx1Z2luTWFwKCkgewogICAgICAgIHJldHVybiBfcGx1Z2luc01hcDsKICAgIH0KICAgIAogICAgcHJvdGVjdGVkIE9iamVjdCBnZXRQbHVnaW4oU3RyaW5nIGtleSkgewogICAgICAgIHJldHVybiBfcGx1Z2luc01hcC5nZXQoa2V5KTsKICAgIH0KICAgIAogICAgLy8gUFJJVkFURSAtIExPQURFUiBQQVJUCiAgICAKICAgIHByaXZhdGUgdm9pZCBsb2FkUGx1Z2lucygpIHsKICAgICAgICBMaXN0IGZpbmFsUGx1Z2luc0xpc3QgPSBuZXcgQXJyYXlMaXN0KCk7CiAgICAgICAgX3BsdWdpbnNMaXN0ID0gbmV3IEFycmF5TGlzdCgpOwogICAgICAgIF9wbHVnaW5zTWFwID0gbmV3IEhhc2hNYXAoKTsKICAgICAgICBTdHJpbmcgY2xhc3NOYW1lID0gbnVsbDsKICAgICAgICB0cnkgewogICAgICAgICAgICBDbGFzc1tdIGNsYXNzZXMgPSBnZXRDbGFzc2VzKCk7CiAgICAgICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgY2xhc3Nlcy5sZW5ndGg7IGkrKykgewogICAgICAgICAgICAgICAgY2xhc3NOYW1lID0gY2xhc3Nlc1tpXS5nZXROYW1lKCk7CiAgICAgICAgICAgICAgICBPYmplY3QgcGx1Z2luID0gY2xhc3Nlc1tpXS5uZXdJbnN0YW5jZSgpOwogICAgICAgICAgICAgICAgaWYgKHBsdWdpbiBpbnN0YW5jZW9mIERlbGVnYXRpbmdNb2R1bGVQYXJzZXIpIHsKICAgICAgICAgICAgICAgICAgICAoKERlbGVnYXRpbmdNb2R1bGVQYXJzZXIpIHBsdWdpbikuc2V0RmVlZFBhcnNlcihfcGFyZW50UGFyc2VyKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlmIChwbHVnaW4gaW5zdGFuY2VvZiBEZWxlZ2F0aW5nTW9kdWxlR2VuZXJhdG9yKSB7CiAgICAgICAgICAgICAgICAgICAgKChEZWxlZ2F0aW5nTW9kdWxlR2VuZXJhdG9yKSBwbHVnaW4pLnNldEZlZWRHZW5lcmF0b3IoX3BhcmVudEdlbmVyYXRvcik7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgIF9wbHVnaW5zTWFwLnB1dChnZXRLZXkocGx1Z2luKSwgcGx1Z2luKTsKICAgICAgICAgICAgICAgIF9wbHVnaW5zTGlzdC5hZGQocGx1Z2luKTsgLy8gdG8gcHJlc2VydmUgdGhlIG9yZGVyIG9mIGRlZmluaXRpb24gaW4gdGhlIHJvbWUucHJvcGVydGllcyBmaWxlcwogICAgICAgICAgICB9CiAgICAgICAgICAgIEl0ZXJhdG9yIGkgPSBfcGx1Z2luc01hcC52YWx1ZXMoKS5pdGVyYXRvcigpOwogICAgICAgICAgICB3aGlsZSAoaS5oYXNOZXh0KCkpIHsKICAgICAgICAgICAgICAgIGZpbmFsUGx1Z2luc0xpc3QuYWRkKGkubmV4dCgpKTsgLy8gdG8gcmVtb3ZlIG92ZXJyaWRkZW4gcGx1Z2luIGltcGxzCiAgICAgICAgICAgIH0KICAgICAgICAgICAgCiAgICAgICAgICAgIGkgPSBfcGx1Z2luc0xpc3QuaXRlcmF0b3IoKTsKICAgICAgICAgICAgd2hpbGUgKGkuaGFzTmV4dCgpKSB7CiAgICAgICAgICAgICAgICBPYmplY3QgcGx1Z2luID0gaS5uZXh0KCk7CiAgICAgICAgICAgICAgICBpZiAoIWZpbmFsUGx1Z2luc0xpc3QuY29udGFpbnMocGx1Z2luKSkgewogICAgICAgICAgICAgICAgICAgIGkucmVtb3ZlKCk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9IGNhdGNoIChFeGNlcHRpb24gZXgpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IFJ1bnRpbWVFeGNlcHRpb24oImNvdWxkIG5vdCBpbnN0YW50aWF0ZSBwbHVnaW4gIiArIGNsYXNzTmFtZSwgZXgpOwogICAgICAgIH0gY2F0Y2ggKEV4Y2VwdGlvbkluSW5pdGlhbGl6ZXJFcnJvciBlcikgewogICAgICAgICAgICB0aHJvdyBuZXcgUnVudGltZUV4Y2VwdGlvbigiY291bGQgbm90IGluc3RhbnRpYXRlIHBsdWdpbiAiICsgY2xhc3NOYW1lLCBlcik7CiAgICAgICAgfQogICAgfQogICAgCiAgICAvKioKICAgICAqIDxwPgogICAgICogTG9hZHMgYW5kIHJldHVybnMgdGhlIGNsYXNzZXMgZGVmaW5lZCBpbiB0aGUgcHJvcGVydGllcyBmaWxlcy4gSWYgdGhlIHN5c3RlbSBwcm9wZXJ0eSAicm9tZS5wbHVnaW5tYW5hZ2VyLnVzZWxvYWRjbGFzcyIgaXMKICAgICAqIHNldCB0byB0cnVlIHRoZW4gY2xhc3NMb2FkZXIubG9hZENsYXNzIHdpbGwgYmUgdXNlZCB0byBsb2FkIGNsYXNzZXMgKGluc3RlYWQgb2YgQ2xhc3MuZm9yTmFtZSkuIFRoaXMgaXMgZGVzaWduZWQgdG8gaW1wcm92ZQogICAgICogT1NHaSBjb21wYXRpYmlsaXR5LiBGdXJ0aGVyIGluZm9ybWF0aW9uIGNhbiBiZSBmb3VuZCBpbiBodHRwczovL3JvbWUuZGV2LmphdmEubmV0L2lzc3Vlcy9zaG93X2J1Zy5jZ2k/aWQ9MTE4CiAgICAgKiA8L3A+CiAgICAgKiAKICAgICAqIEByZXR1cm4gYXJyYXkgY29udGFpbmluZyB0aGUgY2xhc3NlcyBkZWZpbmVkIGluIHRoZSBwcm9wZXJ0aWVzIGZpbGVzLgogICAgICogQHRocm93cyBDbGFzc05vdEZvdW5kRXhjZXB0aW9uIHRocm93biBpZiBvbmUgb2YgdGhlIGNsYXNzZXMgZGVmaW5lZCBpbiB0aGUgcHJvcGVydGllcyBmaWxlIGNhbm5vdCBiZSBsb2FkZWQgYW5kIGhhcmQgZmFpbHVyZSBpcyBPTi4KICAgICAqLwogICAgcHJpdmF0ZSBDbGFzc1tdIGdldENsYXNzZXMoKSB0aHJvd3MgQ2xhc3NOb3RGb3VuZEV4Y2VwdGlvbiB7CiAgICAgICAgQ2xhc3NMb2FkZXIgY2xhc3NMb2FkZXIgPSBUaHJlYWQuY3VycmVudFRocmVhZCgpLmdldENvbnRleHRDbGFzc0xvYWRlcigpOwogICAgICAgIExpc3QgY2xhc3NlcyA9IG5ldyBBcnJheUxpc3QoKTsKICAgICAgICBib29sZWFuIHVzZUxvYWRDbGFzcyA9IEJvb2xlYW4udmFsdWVPZihTeXN0ZW0uZ2V0UHJvcGVydHkoInJvbWUucGx1Z2lubWFuYWdlci51c2Vsb2FkY2xhc3MiLCAiZmFsc2UiKSkuYm9vbGVhblZhbHVlKCk7CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBfcHJvcGVydHlWYWx1ZXMubGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgQ2xhc3MgbUNsYXNzID0gbnVsbDsKICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgIGlmICh1c2VMb2FkQ2xhc3MpIHsKICAgICAgICAgICAgICAgICAgICBtQ2xhc3MgPSBjbGFzc0xvYWRlci5sb2FkQ2xhc3MoX3Byb3BlcnR5VmFsdWVzW2ldKTsKICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgbUNsYXNzID0gQ2xhc3MuZm9yTmFtZShfcHJvcGVydHlWYWx1ZXNbaV0sIHRydWUsIGNsYXNzTG9hZGVyKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSBjYXRjaCAoQ2xhc3NOb3RGb3VuZEV4Y2VwdGlvbiBlKSB7CiAgICAgICAgICAgICAgICAvLyBpZiBleHRlcm5hbCBjbGFzcyBsb2FkZXIgZmFpbCB1c2UgbG9jYWwgY2xhc3MgbG9hZGVyCiAgICAgICAgICAgICAgICBtQ2xhc3MgPSBnZXRDbGFzcygpLmdldENsYXNzTG9hZGVyKCkubG9hZENsYXNzKF9wcm9wZXJ0eVZhbHVlc1tpXSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY2xhc3Nlcy5hZGQobUNsYXNzKTsKICAgICAgICB9CiAgICAgICAgQ2xhc3NbXSBhcnJheSA9IG5ldyBDbGFzc1tjbGFzc2VzLnNpemUoKV07CiAgICAgICAgY2xhc3Nlcy50b0FycmF5KGFycmF5KTsKICAgICAgICByZXR1cm4gYXJyYXk7CiAgICB9Cgp9Cg==