LyoKICogQ29weXJpZ2h0IChDKSAyMDA5IEdvb2dsZSBJbmMuCiAqCiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSAiTGljZW5zZSIpOwogKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuCiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdAogKgogKiBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjAKICoKICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZQogKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiAiQVMgSVMiIEJBU0lTLAogKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC4KICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZAogKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS4KICovCgpwYWNrYWdlIGNvbS5nb29nbGUuaTE4bi5waG9uZW51bWJlcnM7CgppbXBvcnQgY29tLmdvb2dsZS5pMThuLnBob25lbnVtYmVycy5QaG9uZW1ldGFkYXRhLk51bWJlckZvcm1hdDsKaW1wb3J0IGNvbS5nb29nbGUuaTE4bi5waG9uZW51bWJlcnMuUGhvbmVtZXRhZGF0YS5QaG9uZU1ldGFkYXRhOwppbXBvcnQgY29tLmdvb2dsZS5pMThuLnBob25lbnVtYmVycy5QaG9uZW1ldGFkYXRhLlBob25lTWV0YWRhdGFDb2xsZWN0aW9uOwppbXBvcnQgY29tLmdvb2dsZS5pMThuLnBob25lbnVtYmVycy5QaG9uZW1ldGFkYXRhLlBob25lTnVtYmVyRGVzYzsKaW1wb3J0IGNvbS5nb29nbGUuaTE4bi5waG9uZW51bWJlcnMuUGhvbmVudW1iZXIuUGhvbmVOdW1iZXI7CmltcG9ydCBjb20uZ29vZ2xlLmkxOG4ucGhvbmVudW1iZXJzLlBob25lbnVtYmVyLlBob25lTnVtYmVyLkNvdW50cnlDb2RlU291cmNlOwoKaW1wb3J0IGphdmEuaW8uSW5wdXRTdHJlYW07CmltcG9ydCBqYXZhLmlvLklPRXhjZXB0aW9uOwppbXBvcnQgamF2YS5pby5PYmplY3RJbnB1dFN0cmVhbTsKaW1wb3J0IGphdmEudXRpbC5BcnJheUxpc3Q7CmltcG9ydCBqYXZhLnV0aWwuQXJyYXlzOwppbXBvcnQgamF2YS51dGlsLkNvbGxlY3Rpb25zOwppbXBvcnQgamF2YS51dGlsLkhhc2hNYXA7CmltcG9ydCBqYXZhLnV0aWwuSGFzaFNldDsKaW1wb3J0IGphdmEudXRpbC5MaXN0OwppbXBvcnQgamF2YS51dGlsLk1hcDsKaW1wb3J0IGphdmEudXRpbC5TZXQ7CmltcG9ydCBqYXZhLnV0aWwubG9nZ2luZy5MZXZlbDsKaW1wb3J0IGphdmEudXRpbC5sb2dnaW5nLkxvZ2dlcjsKaW1wb3J0IGphdmEudXRpbC5yZWdleC5NYXRjaGVyOwppbXBvcnQgamF2YS51dGlsLnJlZ2V4LlBhdHRlcm47CgovKioKICogVXRpbGl0eSBmb3IgaW50ZXJuYXRpb25hbCBwaG9uZSBudW1iZXJzLiBGdW5jdGlvbmFsaXR5IGluY2x1ZGVzIGZvcm1hdHRpbmcsIHBhcnNpbmcgYW5kCiAqIHZhbGlkYXRpb24uCiAqCiAqIEBhdXRob3IgU2hhb3BlbmcgSmlhCiAqIEBhdXRob3IgTGFyYSBSZW5uaWUKICovCnB1YmxpYyBjbGFzcyBQaG9uZU51bWJlclV0aWwgewogIC8vIFRoZSBtaW5pbXVtIGFuZCBtYXhpbXVtIGxlbmd0aCBvZiB0aGUgbmF0aW9uYWwgc2lnbmlmaWNhbnQgbnVtYmVyLgogIHByaXZhdGUgc3RhdGljIGZpbmFsIGludCBNSU5fTEVOR1RIX0ZPUl9OU04gPSAzOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIGludCBNQVhfTEVOR1RIX0ZPUl9OU04gPSAxNTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBTdHJpbmcgTUVUQV9EQVRBX0ZJTEUgPQogICAgICAiL2NvbS9nb29nbGUvaTE4bi9waG9uZW51bWJlcnMvUGhvbmVOdW1iZXJNZXRhZGF0YVByb3RvIjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBMb2dnZXIgTE9HR0VSID0gTG9nZ2VyLmdldExvZ2dlcihQaG9uZU51bWJlclV0aWwuY2xhc3MuZ2V0TmFtZSgpKTsKCiAgLy8gQSBtYXBwaW5nIGZyb20gYSBjb3VudHJ5IGNvZGUgdG8gdGhlIHJlZ2lvbiBjb2RlcyB3aGljaCBkZW5vdGUgdGhlIGNvdW50cnkvcmVnaW9uCiAgLy8gcmVwcmVzZW50ZWQgYnkgdGhhdCBjb3VudHJ5IGNvZGUuIEluIHRoZSBjYXNlIG9mIG11bHRpcGxlIGNvdW50cmllcyBzaGFyaW5nIGEgY2FsbGluZyBjb2RlLAogIC8vIHN1Y2ggYXMgdGhlIE5BTlBBIGNvdW50cmllcywgdGhlIG9uZSBpbmRpY2F0ZWQgd2l0aCAiaXNNYWluQ291bnRyeUZvckNvZGUiIGluIHRoZSBtZXRhZGF0YQogIC8vIHNob3VsZCBiZSBmaXJzdC4gVGhlIGluaXRpYWwgY2FwYWNpdHkgaXMgc2V0IHRvIDMwMCBhcyB0aGVyZSBhcmUgcm91Z2hseSAyMDAgZGlmZmVyZW50CiAgLy8gY291bnRyeSBjb2RlcywgYW5kIHRoaXMgb2ZmZXJzIGEgbG9hZCBmYWN0b3Igb2Ygcm91Z2hseSAwLjc1LgogIHByaXZhdGUgZmluYWwgTWFwPEludGVnZXIsIExpc3Q8U3RyaW5nPiA+IGNvdW50cnlDb2RlVG9SZWdpb25Db2RlTWFwID0KICAgICAgbmV3IEhhc2hNYXA8SW50ZWdlciwgTGlzdDxTdHJpbmc+ID4oMzEwKTsKCiAgLy8gVGhlIHNldCBvZiBjb3VudHJpZXMgdGhhdCBzaGFyZSBjb3VudHJ5IGNvZGUgMS4gVGhlcmUgYXJlIHJvdWdobHkgMjYgY291bnRyaWVzIG9mIHRoZW0gYW5kIHdlCiAgLy8gc2V0IHRoZSBpbml0aWFsIGNhcGFjaXR5IG9mIHRoZSBIYXNoU2V0IHRvIDM1IHRvIG9mZmVyIGEgbG9hZCBmYWN0b3Igb2Ygcm91Z2hseSAwLjc1LgogIHByaXZhdGUgZmluYWwgSGFzaFNldDxTdHJpbmc+IG5hbnBhQ291bnRyaWVzID0gbmV3IEhhc2hTZXQ8U3RyaW5nPigzNSk7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgaW50IE5BTlBBX0NPVU5UUllfQ09ERSA9IDE7CgogIC8vIFRoZSBQTFVTX1NJR04gc2lnbmlmaWVzIHRoZSBpbnRlcm5hdGlvbmFsIHByZWZpeC4KICBzdGF0aWMgZmluYWwgY2hhciBQTFVTX1NJR04gPSAnKyc7CgogIC8vIFRoZXNlIG1hcHBpbmdzIG1hcCBhIGNoYXJhY3RlciAoa2V5KSB0byBhIHNwZWNpZmljIGRpZ2l0IHRoYXQgc2hvdWxkIHJlcGxhY2UgaXQgZm9yCiAgLy8gbm9ybWFsaXphdGlvbiBwdXJwb3Nlcy4gTm9uLUV1cm9wZWFuIGRpZ2l0cyB0aGF0IG1heSBiZSB1c2VkIGluIHBob25lIG51bWJlcnMgYXJlIG1hcHBlZCB0byBhCiAgLy8gRXVyb3BlYW4gZXF1aXZhbGVudC4KICBzdGF0aWMgZmluYWwgTWFwPENoYXJhY3RlciwgQ2hhcmFjdGVyPiBESUdJVF9NQVBQSU5HUzsKCiAgLy8gT25seSB1cHBlci1jYXNlIHZhcmlhbnRzIG9mIGFscGhhIGNoYXJhY3RlcnMgYXJlIHN0b3JlZC4KICBwcml2YXRlIHN0YXRpYyBmaW5hbCBNYXA8Q2hhcmFjdGVyLCBDaGFyYWN0ZXI+IEFMUEhBX01BUFBJTkdTOwoKICAvLyBGb3IgcGVyZm9ybWFuY2UgcmVhc29ucywgYW1hbGdhbWF0ZSBib3RoIGludG8gb25lIG1hcC4KICBwcml2YXRlIHN0YXRpYyBmaW5hbCBNYXA8Q2hhcmFjdGVyLCBDaGFyYWN0ZXI+IEFMTF9OT1JNQUxJWkFUSU9OX01BUFBJTkdTOwoKICBzdGF0aWMgewogICAgSGFzaE1hcDxDaGFyYWN0ZXIsIENoYXJhY3Rlcj4gZGlnaXRNYXAgPSBuZXcgSGFzaE1hcDxDaGFyYWN0ZXIsIENoYXJhY3Rlcj4oNTApOwogICAgZGlnaXRNYXAucHV0KCcwJywgJzAnKTsKICAgIGRpZ2l0TWFwLnB1dCgnXHVGRjEwJywgJzAnKTsgIC8vIEZ1bGx3aWR0aCBkaWdpdCAwCiAgICBkaWdpdE1hcC5wdXQoJ1x1MDY2MCcsICcwJyk7ICAvLyBBcmFiaWMtaW5kaWMgZGlnaXQgMAogICAgZGlnaXRNYXAucHV0KCcxJywgJzEnKTsKICAgIGRpZ2l0TWFwLnB1dCgnXHVGRjExJywgJzEnKTsgIC8vIEZ1bGx3aWR0aCBkaWdpdCAxCiAgICBkaWdpdE1hcC5wdXQoJ1x1MDY2MScsICcxJyk7ICAvLyBBcmFiaWMtaW5kaWMgZGlnaXQgMQogICAgZGlnaXRNYXAucHV0KCcyJywgJzInKTsKICAgIGRpZ2l0TWFwLnB1dCgnXHVGRjEyJywgJzInKTsgIC8vIEZ1bGx3aWR0aCBkaWdpdCAyCiAgICBkaWdpdE1hcC5wdXQoJ1x1MDY2MicsICcyJyk7ICAvLyBBcmFiaWMtaW5kaWMgZGlnaXQgMgogICAgZGlnaXRNYXAucHV0KCczJywgJzMnKTsKICAgIGRpZ2l0TWFwLnB1dCgnXHVGRjEzJywgJzMnKTsgIC8vIEZ1bGx3aWR0aCBkaWdpdCAzCiAgICBkaWdpdE1hcC5wdXQoJ1x1MDY2MycsICczJyk7ICAvLyBBcmFiaWMtaW5kaWMgZGlnaXQgMwogICAgZGlnaXRNYXAucHV0KCc0JywgJzQnKTsKICAgIGRpZ2l0TWFwLnB1dCgnXHVGRjE0JywgJzQnKTsgIC8vIEZ1bGx3aWR0aCBkaWdpdCA0CiAgICBkaWdpdE1hcC5wdXQoJ1x1MDY2NCcsICc0Jyk7ICAvLyBBcmFiaWMtaW5kaWMgZGlnaXQgNAogICAgZGlnaXRNYXAucHV0KCc1JywgJzUnKTsKICAgIGRpZ2l0TWFwLnB1dCgnXHVGRjE1JywgJzUnKTsgIC8vIEZ1bGx3aWR0aCBkaWdpdCA1CiAgICBkaWdpdE1hcC5wdXQoJ1x1MDY2NScsICc1Jyk7ICAvLyBBcmFiaWMtaW5kaWMgZGlnaXQgNQogICAgZGlnaXRNYXAucHV0KCc2JywgJzYnKTsKICAgIGRpZ2l0TWFwLnB1dCgnXHVGRjE2JywgJzYnKTsgIC8vIEZ1bGx3aWR0aCBkaWdpdCA2CiAgICBkaWdpdE1hcC5wdXQoJ1x1MDY2NicsICc2Jyk7ICAvLyBBcmFiaWMtaW5kaWMgZGlnaXQgNgogICAgZGlnaXRNYXAucHV0KCc3JywgJzcnKTsKICAgIGRpZ2l0TWFwLnB1dCgnXHVGRjE3JywgJzcnKTsgIC8vIEZ1bGx3aWR0aCBkaWdpdCA3CiAgICBkaWdpdE1hcC5wdXQoJ1x1MDY2NycsICc3Jyk7ICAvLyBBcmFiaWMtaW5kaWMgZGlnaXQgNwogICAgZGlnaXRNYXAucHV0KCc4JywgJzgnKTsKICAgIGRpZ2l0TWFwLnB1dCgnXHVGRjE4JywgJzgnKTsgIC8vIEZ1bGx3aWR0aCBkaWdpdCA4CiAgICBkaWdpdE1hcC5wdXQoJ1x1MDY2OCcsICc4Jyk7ICAvLyBBcmFiaWMtaW5kaWMgZGlnaXQgOAogICAgZGlnaXRNYXAucHV0KCc5JywgJzknKTsKICAgIGRpZ2l0TWFwLnB1dCgnXHVGRjE5JywgJzknKTsgIC8vIEZ1bGx3aWR0aCBkaWdpdCA5CiAgICBkaWdpdE1hcC5wdXQoJ1x1MDY2OScsICc5Jyk7ICAvLyBBcmFiaWMtaW5kaWMgZGlnaXQgOQogICAgRElHSVRfTUFQUElOR1MgPSBDb2xsZWN0aW9ucy51bm1vZGlmaWFibGVNYXAoZGlnaXRNYXApOwoKICAgIEhhc2hNYXA8Q2hhcmFjdGVyLCBDaGFyYWN0ZXI+IGFscGhhTWFwID0gbmV3IEhhc2hNYXA8Q2hhcmFjdGVyLCBDaGFyYWN0ZXI+KDQwKTsKICAgIGFscGhhTWFwLnB1dCgnQScsICcyJyk7CiAgICBhbHBoYU1hcC5wdXQoJ0InLCAnMicpOwogICAgYWxwaGFNYXAucHV0KCdDJywgJzInKTsKICAgIGFscGhhTWFwLnB1dCgnRCcsICczJyk7CiAgICBhbHBoYU1hcC5wdXQoJ0UnLCAnMycpOwogICAgYWxwaGFNYXAucHV0KCdGJywgJzMnKTsKICAgIGFscGhhTWFwLnB1dCgnRycsICc0Jyk7CiAgICBhbHBoYU1hcC5wdXQoJ0gnLCAnNCcpOwogICAgYWxwaGFNYXAucHV0KCdJJywgJzQnKTsKICAgIGFscGhhTWFwLnB1dCgnSicsICc1Jyk7CiAgICBhbHBoYU1hcC5wdXQoJ0snLCAnNScpOwogICAgYWxwaGFNYXAucHV0KCdMJywgJzUnKTsKICAgIGFscGhhTWFwLnB1dCgnTScsICc2Jyk7CiAgICBhbHBoYU1hcC5wdXQoJ04nLCAnNicpOwogICAgYWxwaGFNYXAucHV0KCdPJywgJzYnKTsKICAgIGFscGhhTWFwLnB1dCgnUCcsICc3Jyk7CiAgICBhbHBoYU1hcC5wdXQoJ1EnLCAnNycpOwogICAgYWxwaGFNYXAucHV0KCdSJywgJzcnKTsKICAgIGFscGhhTWFwLnB1dCgnUycsICc3Jyk7CiAgICBhbHBoYU1hcC5wdXQoJ1QnLCAnOCcpOwogICAgYWxwaGFNYXAucHV0KCdVJywgJzgnKTsKICAgIGFscGhhTWFwLnB1dCgnVicsICc4Jyk7CiAgICBhbHBoYU1hcC5wdXQoJ1cnLCAnOScpOwogICAgYWxwaGFNYXAucHV0KCdYJywgJzknKTsKICAgIGFscGhhTWFwLnB1dCgnWScsICc5Jyk7CiAgICBhbHBoYU1hcC5wdXQoJ1onLCAnOScpOwogICAgQUxQSEFfTUFQUElOR1MgPSBDb2xsZWN0aW9ucy51bm1vZGlmaWFibGVNYXAoYWxwaGFNYXApOwoKICAgIEhhc2hNYXA8Q2hhcmFjdGVyLCBDaGFyYWN0ZXI+IGNvbWJpbmVkTWFwID0gbmV3IEhhc2hNYXA8Q2hhcmFjdGVyLCBDaGFyYWN0ZXI+KDEwMCk7CiAgICBjb21iaW5lZE1hcC5wdXRBbGwoYWxwaGFNYXApOwogICAgY29tYmluZWRNYXAucHV0QWxsKGRpZ2l0TWFwKTsKICAgIEFMTF9OT1JNQUxJWkFUSU9OX01BUFBJTkdTID0gQ29sbGVjdGlvbnMudW5tb2RpZmlhYmxlTWFwKGNvbWJpbmVkTWFwKTsKICB9CgogIC8vIEEgbGlzdCBvZiBhbGwgY291bnRyeSBjb2RlcyB3aGVyZSBuYXRpb25hbCBzaWduaWZpY2FudCBudW1iZXJzIChleGNsdWRpbmcgYW55IG5hdGlvbmFsIHByZWZpeCkKICAvLyBleGlzdCB0aGF0IHN0YXJ0IHdpdGggYSBsZWFkaW5nIHplcm8uCiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgU2V0PEludGVnZXI+IExFQURJTkdfWkVST19DT1VOVFJJRVM7CiAgc3RhdGljIHsKICAgIEhhc2hTZXQ8SW50ZWdlcj4gYVNldCA9IG5ldyBIYXNoU2V0PEludGVnZXI+KDEwKTsKICAgIGFTZXQuYWRkKDM5KTsgIC8vIEl0YWx5CiAgICBhU2V0LmFkZCg0Nyk7ICAvLyBOb3J3YXkKICAgIGFTZXQuYWRkKDIyNSk7ICAvLyBDb3RlIGQnSXZvaXJlCiAgICBhU2V0LmFkZCgyMjcpOyAgLy8gTmlnZXIKICAgIGFTZXQuYWRkKDIyOCk7ICAvLyBUb2dvCiAgICBhU2V0LmFkZCgyNDEpOyAgLy8gR2Fib24KICAgIGFTZXQuYWRkKDM3OSk7ICAvLyBWYXRpY2FuIENpdHkKICAgIExFQURJTkdfWkVST19DT1VOVFJJRVMgPSBDb2xsZWN0aW9ucy51bm1vZGlmaWFibGVTZXQoYVNldCk7CiAgfQoKICAvLyBQYXR0ZXJuIHRoYXQgbWFrZXMgaXQgZWFzeSB0byBkaXN0aW5ndWlzaCB3aGV0aGVyIGEgY291bnRyeSBoYXMgYSB1bmlxdWUgaW50ZXJuYXRpb25hbCBkaWFsaW5nCiAgLy8gcHJlZml4IG9yIG5vdC4gSWYgYSBjb3VudHJ5IGhhcyBhIHVuaXF1ZSBpbnRlcm5hdGlvbmFsIHByZWZpeCAoZS5nLiAwMTEgaW4gVVNBKSwgaXQgd2lsbCBiZQogIC8vIHJlcHJlc2VudGVkIGFzIGEgc3RyaW5nIHRoYXQgY29udGFpbnMgYSBzZXF1ZW5jZSBvZiBBU0NJSSBkaWdpdHMuIElmIHRoZXJlIGFyZSBtdWx0aXBsZQogIC8vIGF2YWlsYWJsZSBpbnRlcm5hdGlvbmFsIHByZWZpeGVzIGluIGEgY291bnRyeSwgdGhleSB3aWxsIGJlIHJlcHJlc2VudGVkIGFzIGEgcmVnZXggc3RyaW5nIHRoYXQKICAvLyBhbHdheXMgY29udGFpbnMgY2hhcmFjdGVyKHMpIG90aGVyIHRoYW4gQVNDSUkgZGlnaXRzLgogIC8vIE5vdGUgdGhpcyByZWdleCBhbHNvIGluY2x1ZGVzIHRpbGRlLCB3aGljaCBzaWduYWxzIHdhaXRpbmcgZm9yIHRoZSB0b25lLgogIHByaXZhdGUgc3RhdGljIGZpbmFsIFBhdHRlcm4gVU5JUVVFX0lOVEVSTkFUSU9OQUxfUFJFRklYID0KICAgICAgUGF0dGVybi5jb21waWxlKCJbXFxkXSsoPzpbflx1MjA1M1x1MjIzQ1x1RkY1RV1bXFxkXSspPyIpOwoKICAvLyBSZWd1bGFyIGV4cHJlc3Npb24gb2YgYWNjZXB0YWJsZSBwdW5jdHVhdGlvbiBmb3VuZCBpbiBwaG9uZSBudW1iZXJzLiBUaGlzIGV4Y2x1ZGVzIHB1bmN0dWF0aW9uCiAgLy8gZm91bmQgYXMgYSBsZWFkaW5nIGNoYXJhY3RlciBvbmx5LgogIC8vIFRoaXMgY29uc2lzdHMgb2YgZGFzaCBjaGFyYWN0ZXJzLCB3aGl0ZSBzcGFjZSBjaGFyYWN0ZXJzLCBmdWxsIHN0b3BzLCBzbGFzaGVzLAogIC8vIHNxdWFyZSBicmFja2V0cywgcGFyZW50aGVzZXMgYW5kIHRpbGRlcy4gSXQgYWxzbyBpbmNsdWRlcyB0aGUgbGV0dGVyICd4JyBhcyB0aGF0IGlzIGZvdW5kIGFzIGEKICAvLyBwbGFjZWhvbGRlciBmb3IgY2FycmllciBpbmZvcm1hdGlvbiBpbiBzb21lIHBob25lIG51bWJlcnMuCiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgU3RyaW5nIFZBTElEX1BVTkNUVUFUSU9OID0gIi14XHUyMDEwLVx1MjAxNVx1MjIxMlx1RkYwRC1cdUZGMEYgIiArCiAgICAgICJcdTAwQTBcdTIwMEJcdTIwNjBcdTMwMDAoKVx1RkYwOFx1RkYwOVx1RkYzQlx1RkYzRC5cXFtcXF0vflx1MjA1M1x1MjIzQ1x1RkY1RSI7CgogIC8vIERpZ2l0cyBhY2NlcHRlZCBpbiBwaG9uZSBudW1iZXJzCiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgU3RyaW5nIFZBTElEX0RJR0lUUyA9CiAgICAgIEFycmF5cy50b1N0cmluZyhESUdJVF9NQVBQSU5HUy5rZXlTZXQoKS50b0FycmF5KCkpLnJlcGxhY2VBbGwoIiwgIiwgIiIpOwogIC8vIFdlIGFjY2VwdCBhbHBoYSBjaGFyYWN0ZXJzIGluIHBob25lIG51bWJlcnMsIEFTQ0lJIG9ubHksIHVwcGVyIGFuZCBsb3dlciBjYXNlLgogIHByaXZhdGUgc3RhdGljIGZpbmFsIFN0cmluZyBWQUxJRF9BTFBIQSA9CiAgICAgIEFycmF5cy50b1N0cmluZyhBTFBIQV9NQVBQSU5HUy5rZXlTZXQoKS50b0FycmF5KCkpLnJlcGxhY2VBbGwoIiwgIiwgIiIpICsKICAgICAgQXJyYXlzLnRvU3RyaW5nKEFMUEhBX01BUFBJTkdTLmtleVNldCgpLnRvQXJyYXkoKSkudG9Mb3dlckNhc2UoKS5yZXBsYWNlQWxsKCIsICIsICIiKTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBTdHJpbmcgUExVU19DSEFSUyA9ICIrXHVGRjBCIjsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBQYXR0ZXJuIENBUFRVUklOR19ESUdJVF9QQVRURVJOID0KICAgICAgUGF0dGVybi5jb21waWxlKCIoWyIgKyBWQUxJRF9ESUdJVFMgKyAiXSkiKTsKCiAgLy8gUmVndWxhciBleHByZXNzaW9uIG9mIGFjY2VwdGFibGUgY2hhcmFjdGVycyB0aGF0IG1heSBzdGFydCBhIHBob25lIG51bWJlciBmb3IgdGhlIHB1cnBvc2VzIG9mCiAgLy8gcGFyc2luZy4gVGhpcyBhbGxvd3MgdXMgdG8gc3RyaXAgYXdheSBtZWFuaW5nbGVzcyBwcmVmaXhlcyB0byBwaG9uZSBudW1iZXJzIHRoYXQgbWF5IGJlCiAgLy8gbWlzdGFrZW5seSBnaXZlbiB0byB1cy4gVGhpcyBjb25zaXN0cyBvZiBkaWdpdHMsIHRoZSBwbHVzIHN5bWJvbCBhbmQgYXJhYmljLWluZGljIGRpZ2l0cy4gVGhpcwogIC8vIGRvZXMgbm90IGNvbnRhaW4gYWxwaGEgY2hhcmFjdGVycywgYWx0aG91Z2ggdGhleSBtYXkgYmUgdXNlZCBsYXRlciBpbiB0aGUgbnVtYmVyLiBJdCBhbHNvIGRvZXMKICAvLyBub3QgaW5jbHVkZSBvdGhlciBwdW5jdHVhdGlvbiwgYXMgdGhpcyB3aWxsIGJlIHN0cmlwcGVkIGxhdGVyIGR1cmluZyBwYXJzaW5nIGFuZCBpcyBvZiBubwogIC8vIGluZm9ybWF0aW9uIHZhbHVlIHdoZW4gcGFyc2luZyBhIG51bWJlci4KICBwcml2YXRlIHN0YXRpYyBmaW5hbCBTdHJpbmcgVkFMSURfU1RBUlRfQ0hBUiA9ICJbIiArIFBMVVNfQ0hBUlMgKyBWQUxJRF9ESUdJVFMgKyAiXSI7CiAgc3RhdGljIGZpbmFsIFBhdHRlcm4gVkFMSURfU1RBUlRfQ0hBUl9QQVRURVJOID0gUGF0dGVybi5jb21waWxlKFZBTElEX1NUQVJUX0NIQVIpOwoKICAvLyBSZWd1bGFyIGV4cHJlc3Npb24gb2YgY2hhcmFjdGVycyB0eXBpY2FsbHkgdXNlZCB0byBzdGFydCBhIHNlY29uZCBwaG9uZSBudW1iZXIgZm9yIHRoZSBwdXJwb3NlcwogIC8vIG9mIHBhcnNpbmcuIFRoaXMgYWxsb3dzIHVzIHRvIHN0cmlwIG9mZiBwYXJ0cyBvZiB0aGUgbnVtYmVyIHRoYXQgYXJlIGFjdHVhbGx5IHRoZSBzdGFydCBvZgogIC8vIGFub3RoZXIgbnVtYmVyLCBzdWNoIGFzIGZvcjogKDUzMCkgNTgzLTY5ODUgeDMwMi94MjMwMyAtPiB0aGUgc2Vjb25kIGV4dGVuc2lvbiBoZXJlIG1ha2VzIHRoaXMKICAvLyBhY3R1YWxseSB0d28gcGhvbmUgbnVtYmVycywgKDUzMCkgNTgzLTY5ODUgeDMwMiBhbmQgKDUzMCkgNTgzLTY5ODUgeDIzMDMuIFdlIHJlbW92ZSB0aGUgc2Vjb25kCiAgLy8gZXh0ZW5zaW9uIHNvIHRoYXQgdGhlIGZpcnN0IG51bWJlciBpcyBwYXJzZWQgY29ycmVjdGx5LgogIHByaXZhdGUgc3RhdGljIGZpbmFsIFN0cmluZyBTRUNPTkRfTlVNQkVSX1NUQVJUID0gIltcXFxcL10gKngiOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIFBhdHRlcm4gU0VDT05EX05VTUJFUl9TVEFSVF9QQVRURVJOID0gUGF0dGVybi5jb21waWxlKFNFQ09ORF9OVU1CRVJfU1RBUlQpOwoKICAvLyBSZWd1bGFyIGV4cHJlc3Npb24gb2YgdHJhaWxpbmcgY2hhcmFjdGVycyB0aGF0IHdlIHdhbnQgdG8gcmVtb3ZlLiBXZSByZW1vdmUgYWxsIGNoYXJhY3RlcnMgdGhhdAogIC8vIGFyZSBub3QgYWxwaGEgb3IgbnVtZXJpY2FsIGNoYXJhY3RlcnMuIFRoZSBoYXNoIGNoYXJhY3RlciBpcyByZXRhaW5lZCBoZXJlLCBhcyBpdCBtYXkgc2lnbmlmeQogIC8vIHRoZSBwcmV2aW91cyBibG9jayB3YXMgYW4gZXh0ZW5zaW9uLgogIHByaXZhdGUgc3RhdGljIGZpbmFsIFN0cmluZyBVTldBTlRFRF9FTkRfQ0hBUlMgPSAiW1tcXFB7Tn0mJlxcUHtMfV0mJlteI11dKyQiOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIFBhdHRlcm4gVU5XQU5URURfRU5EX0NIQVJfUEFUVEVSTiA9IFBhdHRlcm4uY29tcGlsZShVTldBTlRFRF9FTkRfQ0hBUlMpOwoKICAvLyBXZSB1c2UgdGhpcyBwYXR0ZXJuIHRvIGNoZWNrIGlmIHRoZSBwaG9uZSBudW1iZXIgaGFzIGF0IGxlYXN0IHRocmVlIGxldHRlcnMgaW4gaXQgLSBpZiBzbywgdGhlbgogIC8vIHdlIHRyZWF0IGl0IGFzIGEgbnVtYmVyIHdoZXJlIHNvbWUgcGhvbmUtbnVtYmVyIGRpZ2l0cyBhcmUgcmVwcmVzZW50ZWQgYnkgbGV0dGVycy4KICBwcml2YXRlIHN0YXRpYyBmaW5hbCBQYXR0ZXJuIFZBTElEX0FMUEhBX1BIT05FX1BBVFRFUk4gPSBQYXR0ZXJuLmNvbXBpbGUoIig/Oi4qP1tBLVphLXpdKXszfS4qIik7CgogIC8vIFJlZ3VsYXIgZXhwcmVzc2lvbiBvZiB2aWFibGUgcGhvbmUgbnVtYmVycy4gVGhpcyBpcyBsb2NhdGlvbiBpbmRlcGVuZGVudC4gQ2hlY2tzIHdlIGhhdmUgYXQKICAvLyBsZWFzdCB0aHJlZSBsZWFkaW5nIGRpZ2l0cywgYW5kIG9ubHkgdmFsaWQgcHVuY3R1YXRpb24sIGFscGhhIGNoYXJhY3RlcnMgYW5kCiAgLy8gZGlnaXRzIGluIHRoZSBwaG9uZSBudW1iZXIuIERvZXMgbm90IGluY2x1ZGUgZXh0ZW5zaW9uIGRhdGEuCiAgLy8gVGhlIHN5bWJvbCAneCcgaXMgYWxsb3dlZCBoZXJlIGFzIHZhbGlkIHB1bmN0dWF0aW9uIHNpbmNlIGl0IGlzIG9mdGVuIHVzZWQgYXMgYSBwbGFjZWhvbGRlciBmb3IKICAvLyBjYXJyaWVyIGNvZGVzLCBmb3IgZXhhbXBsZSBpbiBCcmF6aWxpYW4gcGhvbmUgbnVtYmVycy4KICAvLyBDb3JyZXNwb25kcyB0byB0aGUgZm9sbG93aW5nOgogIC8vIHBsdXNfc2lnbj8oW3B1bmN0dWF0aW9uXSpbZGlnaXRzXSl7Myx9KFtwdW5jdHVhdGlvbl18W2RpZ2l0c118W2FscGhhXSkqCiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgU3RyaW5nIFZBTElEX1BIT05FX05VTUJFUiA9CiAgICAgICJbIiArIFBMVVNfQ0hBUlMgKyAiXT8oPzpbIiArIFZBTElEX1BVTkNUVUFUSU9OICsgIl0qWyIgKyBWQUxJRF9ESUdJVFMgKyAiXSl7Myx9WyIgKwogICAgICBWQUxJRF9BTFBIQSArIFZBTElEX1BVTkNUVUFUSU9OICsgVkFMSURfRElHSVRTICsgIl0qIjsKCiAgLy8gRGVmYXVsdCBleHRlbnNpb24gcHJlZml4IHRvIHVzZSB3aGVuIGZvcm1hdHRpbmcuIFRoaXMgd2lsbCBiZSBwdXQgaW4gZnJvbnQgb2YgYW55IGV4dGVuc2lvbgogIC8vIGNvbXBvbmVudCBvZiB0aGUgbnVtYmVyLCBhZnRlciB0aGUgbWFpbiBuYXRpb25hbCBudW1iZXIgaXMgZm9ybWF0dGVkLiBGb3IgZXhhbXBsZSwgaWYgeW91IHdpc2gKICAvLyB0aGUgZGVmYXVsdCBleHRlbnNpb24gZm9ybWF0dGluZyB0byBiZSAiIGV4dG46IDM0NTYiLCB0aGVuIHlvdSBzaG91bGQgc3BlY2lmeSAiIGV4dG46ICIgaGVyZQogIC8vIGFzIHRoZSBkZWZhdWx0IGV4dGVuc2lvbiBwcmVmaXguIFRoaXMgY2FuIGJlIG92ZXJyaWRkZW4gYnkgY291bnRyeS1zcGVjaWZpYyBwcmVmZXJlbmNlcy4KICBwcml2YXRlIHN0YXRpYyBmaW5hbCBTdHJpbmcgREVGQVVMVF9FWFROX1BSRUZJWCA9ICIgZXh0LiAiOwoKICAvLyBSZWdleHAgb2YgYWxsIHBvc3NpYmxlIHdheXMgdG8gd3JpdGUgZXh0ZW5zaW9ucywgZm9yIHVzZSB3aGVuIHBhcnNpbmcuIFRoaXMgd2lsbCBiZSBydW4gYXMgYQogIC8vIGNhc2UtaW5zZW5zaXRpdmUgcmVnZXhwIG1hdGNoLiBXaWRlIGNoYXJhY3RlciB2ZXJzaW9ucyBhcmUgYWxzbyBwcm92aWRlZCBhZnRlciBlYWNoIGFzY2lpCiAgLy8gdmVyc2lvbi4gVGhlcmUgYXJlIHR3byByZWd1bGFyIGV4cHJlc3Npb25zIGhlcmU6IHRoZSBtb3JlIGdlbmVyaWMgb25lIHN0YXJ0cyB3aXRoIG9wdGlvbmFsCiAgLy8gd2hpdGUgc3BhY2UgYW5kIGVuZHMgd2l0aCBhbiBvcHRpb25hbCBmdWxsIHN0b3AgKC4pLCBmb2xsb3dlZCBieSB6ZXJvIG9yIG1vcmUgc3BhY2VzL3RhYnMgYW5kCiAgLy8gdGhlbiB0aGUgbnVtYmVycyB0aGVtc2VsdmVzLiBUaGUgb3RoZXIgb25lIGNvdmVycyB0aGUgc3BlY2lhbCBjYXNlIG9mIEFtZXJpY2FuIG51bWJlcnMgd2hlcmUKICAvLyB0aGUgZXh0ZW5zaW9uIGlzIHdyaXR0ZW4gd2l0aCBhIGhhc2ggYXQgdGhlIGVuZCwgc3VjaCBhcyAiLSA1MDMjIi4KICAvLyBOb3RlIHRoYXQgdGhlIG9ubHkgY2FwdHVyaW5nIGdyb3VwcyBzaG91bGQgYmUgYXJvdW5kIHRoZSBkaWdpdHMgdGhhdCB5b3Ugd2FudCB0byBjYXB0dXJlIGFzCiAgLy8gcGFydCBvZiB0aGUgZXh0ZW5zaW9uLCBvciBlbHNlIHBhcnNpbmcgd2lsbCBmYWlsIQogIHByaXZhdGUgc3RhdGljIGZpbmFsIFN0cmluZyBLTk9XTl9FWFROX1BBVFRFUk5TID0gIlsgXHUwMEEwXFx0LF0qKD86ZXh0KD86ZW5zaW8pP24/fCIgKwogICAgICAiXHVGRjQ1XHVGRjU4XHVGRjU0XHVGRjRFP3xbLHhcdUZGNTgjXHVGRjAzflx1RkY1RV18aW50fGFuZXhvfFx1RkY0OVx1RkY0RVx1RkY1NCkiICsKICAgICAgIls6XFwuXHVGRjBFXT9bIFx1MDBBMFxcdCwtXSooWyIgKyBWQUxJRF9ESUdJVFMgKyAiXXsxLDd9KXxbLSBdKyhbIiArIFZBTElEX0RJR0lUUyArCiAgICAgICJdezEsNX0pIyI7CgogIC8vIFJlZ2V4cCBvZiBhbGwga25vd24gZXh0ZW5zaW9uIHByZWZpeGVzIHVzZWQgYnkgZGlmZmVyZW50IGNvdW50cmllcyBmb2xsb3dlZCBieSAxIG9yIG1vcmUgdmFsaWQKICAvLyBkaWdpdHMsIGZvciB1c2Ugd2hlbiBwYXJzaW5nLgogIHByaXZhdGUgc3RhdGljIGZpbmFsIFBhdHRlcm4gRVhUTl9QQVRURVJOID0KICAgICAgUGF0dGVybi5jb21waWxlKCIoPzoiICsgS05PV05fRVhUTl9QQVRURVJOUyArICIpJCIsCiAgICAgICAgICAgICAgICAgICAgICBQYXR0ZXJuLlVOSUNPREVfQ0FTRSB8IFBhdHRlcm4uQ0FTRV9JTlNFTlNJVElWRSk7CgogIC8vIFdlIGFwcGVuZCBvcHRpb25hbGx5IHRoZSBleHRlbnNpb24gcGF0dGVybiB0byB0aGUgZW5kIGhlcmUsIGFzIGEgdmFsaWQgcGhvbmUgbnVtYmVyIG1heQogIC8vIGhhdmUgYW4gZXh0ZW5zaW9uIHByZWZpeCBhcHBlbmRlZCwgZm9sbG93ZWQgYnkgMSBvciBtb3JlIGRpZ2l0cy4KICBwcml2YXRlIHN0YXRpYyBmaW5hbCBQYXR0ZXJuIFZBTElEX1BIT05FX05VTUJFUl9QQVRURVJOID0KICAgICAgUGF0dGVybi5jb21waWxlKFZBTElEX1BIT05FX05VTUJFUiArICIoPzoiICsgS05PV05fRVhUTl9QQVRURVJOUyArICIpPyIsCiAgICAgICAgICAgICAgICAgICAgICBQYXR0ZXJuLlVOSUNPREVfQ0FTRSB8IFBhdHRlcm4uQ0FTRV9JTlNFTlNJVElWRSk7CgogIHByaXZhdGUgc3RhdGljIGZpbmFsIFBhdHRlcm4gTk9OX0RJR0lUU19QQVRURVJOID0gUGF0dGVybi5jb21waWxlKCIoXFxEKykiKTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBQYXR0ZXJuIEZJUlNUX0dST1VQX1BBVFRFUk4gPSBQYXR0ZXJuLmNvbXBpbGUoIihcXCQxKSIpOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIFBhdHRlcm4gTlBfUEFUVEVSTiA9IFBhdHRlcm4uY29tcGlsZSgiXFwkTlAiKTsKICBwcml2YXRlIHN0YXRpYyBmaW5hbCBQYXR0ZXJuIEZHX1BBVFRFUk4gPSBQYXR0ZXJuLmNvbXBpbGUoIlxcJEZHIik7CiAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgUGF0dGVybiBDQ19QQVRURVJOID0gUGF0dGVybi5jb21waWxlKCJcXCRDQyIpOwogIHByaXZhdGUgc3RhdGljIGZpbmFsIFBhdHRlcm4gTk9OX0RJR0lUX1BBVFRFUk4gPSBQYXR0ZXJuLmNvbXBpbGUoIlxcRCIpOwoKICBwcml2YXRlIHN0YXRpYyBQaG9uZU51bWJlclV0aWwgaW5zdGFuY2UgPSBudWxsOwoKICAvLyBBIG1hcHBpbmcgZnJvbSBhIHJlZ2lvbiBjb2RlIHRvIHRoZSBQaG9uZU1ldGFkYXRhIGZvciB0aGF0IHJlZ2lvbi4KICBwcml2YXRlIEhhc2hNYXA8U3RyaW5nLCBQaG9uZU1ldGFkYXRhPiBjb3VudHJ5VG9NZXRhZGF0YU1hcCA9CiAgICAgIG5ldyBIYXNoTWFwPFN0cmluZywgUGhvbmVNZXRhZGF0YT4oKTsKCiAgLy8gQSBjYWNoZSBmb3IgZnJlcXVlbnRseSB1c2VkIGNvdW50cnktc3BlY2lmaWMgcmVndWxhciBleHByZXNzaW9ucy4gQXMgbW9zdCBwZW9wbGUgdXNlIHBob25lCiAgLy8gbnVtYmVycyBwcmltYXJpbHkgZnJvbSBvbmUgdG8gdHdvIGNvdW50cmllcywgYW5kIHRoZXJlIGFyZSByb3VnaGx5IDYwIHJlZ3VsYXIgZXhwcmVzc2lvbnMKICAvLyBuZWVkZWQsIHRoZSBpbml0aWFsIGNhcGFjaXR5IG9mIDEwMCBvZmZlcnMgYSByb3VnaCBsb2FkIGZhY3RvciBvZiAwLjc1LgogIHByaXZhdGUgUmVnZXhDYWNoZSByZWdleENhY2hlID0gbmV3IFJlZ2V4Q2FjaGUoMTAwKTsKCiAgLyoqCiAgICogSU5URVJOQVRJT05BTCBhbmQgTkFUSU9OQUwgZm9ybWF0cyBhcmUgY29uc2lzdGVudCB3aXRoIHRoZSBkZWZpbml0aW9uIGluIElUVS1UIFJlY29tbWVuZGF0aW9uCiAgICogRS4gMTIzLiBGb3IgZXhhbXBsZSwgdGhlIG51bWJlciBvZiB0aGUgR29vZ2xlIFp1cmljaCBvZmZpY2Ugd2lsbCBiZSB3cml0dGVuIGFzCiAgICogIis0MSA0NCA2NjggMTgwMCIgaW4gSU5URVJOQVRJT05BTCBmb3JtYXQsIGFuZCBhcyAiMDQ0IDY2OCAxODAwIiBpbiBOQVRJT05BTCBmb3JtYXQuCiAgICogRTE2NCBmb3JtYXQgaXMgYXMgcGVyIElOVEVSTkFUSU9OQUwgZm9ybWF0IGJ1dCB3aXRoIG5vIGZvcm1hdHRpbmcgYXBwbGllZCwgZS5nLiArNDE0NDY2ODE4MDAuCiAgICoKICAgKiBOb3RlOiBJZiB5b3UgYXJlIGNvbnNpZGVyaW5nIHN0b3JpbmcgdGhlIG51bWJlciBpbiBhIG5ldXRyYWwgZm9ybWF0LCB5b3UgYXJlIGhpZ2hseSBhZHZpc2VkIHRvCiAgICogdXNlIHRoZSBwaG9uZW51bWJlci5wcm90by4KICAgKi8KICBwdWJsaWMgZW51bSBQaG9uZU51bWJlckZvcm1hdCB7CiAgICBFMTY0LAogICAgSU5URVJOQVRJT05BTCwKICAgIE5BVElPTkFMCiAgfQoKICAvKioKICAgKiBUeXBlIG9mIHBob25lIG51bWJlcnMuCiAgICovCiAgcHVibGljIGVudW0gUGhvbmVOdW1iZXJUeXBlIHsKICAgIEZJWEVEX0xJTkUsCiAgICBNT0JJTEUsCiAgICAvLyBJbiBzb21lIGNvdW50cmllcyAoZS5nLiB0aGUgVVNBKSwgaXQgaXMgaW1wb3NzaWJsZSB0byBkaXN0aW5ndWlzaCBiZXR3ZWVuIGZpeGVkLWxpbmUgYW5kCiAgICAvLyBtb2JpbGUgbnVtYmVycyBieSBsb29raW5nIGF0IHRoZSBwaG9uZSBudW1iZXIgaXRzZWxmLgogICAgRklYRURfTElORV9PUl9NT0JJTEUsCiAgICAvLyBGcmVlcGhvbmUgbGluZXMKICAgIFRPTExfRlJFRSwKICAgIFBSRU1JVU1fUkFURSwKICAgIC8vIFRoZSBjb3N0IG9mIHRoaXMgY2FsbCBpcyBzaGFyZWQgYmV0d2VlbiB0aGUgY2FsbGVyIGFuZCB0aGUgcmVjaXBpZW50LCBhbmQgaXMgaGVuY2UgdHlwaWNhbGx5CiAgICAvLyBsZXNzIHRoYW4gUFJFTUlVTV9SQVRFIGNhbGxzLiBTZWUgLy8gaHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9TaGFyZWRfQ29zdF9TZXJ2aWNlIGZvcgogICAgLy8gbW9yZSBpbmZvcm1hdGlvbi4KICAgIFNIQVJFRF9DT1NULAogICAgLy8gVm9pY2Ugb3ZlciBJUCBudW1iZXJzLiBUaGlzIGluY2x1ZGVzIFRTb0lQIChUZWxlcGhvbnkgU2VydmljZSBvdmVyIElQKS4KICAgIFZPSVAsCiAgICAvLyBBIHBlcnNvbmFsIG51bWJlciBpcyBhc3NvY2lhdGVkIHdpdGggYSBwYXJ0aWN1bGFyIHBlcnNvbiwgYW5kIG1heSBiZSByb3V0ZWQgdG8gZWl0aGVyIGEKICAgIC8vIE1PQklMRSBvciBGSVhFRF9MSU5FIG51bWJlci4gU29tZSBtb3JlIGluZm9ybWF0aW9uIGNhbiBiZSBmb3VuZCBoZXJlOgogICAgLy8gaHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9QZXJzb25hbF9OdW1iZXJzCiAgICBQRVJTT05BTF9OVU1CRVIsCiAgICAvLyBBIHBob25lIG51bWJlciBpcyBvZiB0eXBlIFVOS05PV04gd2hlbiBpdCBkb2VzIG5vdCBmaXQgYW55IG9mIHRoZSBrbm93biBwYXR0ZXJucyBmb3IgYQogICAgLy8gc3BlY2lmaWMgY291bnRyeS4KICAgIFVOS05PV04KICB9CgogIC8qKgogICAqIFR5cGVzIG9mIHBob25lIG51bWJlciBtYXRjaGVzLiBTZWUgZGV0YWlsZWQgZGVzY3JpcHRpb24gYmVzaWRlIHRoZSBpc051bWJlck1hdGNoKCkgbWV0aG9kLgogICAqLwogIHB1YmxpYyBlbnVtIE1hdGNoVHlwZSB7CiAgICBOT19NQVRDSCwKICAgIFNIT1JUX05TTl9NQVRDSCwKICAgIE5TTl9NQVRDSCwKICAgIEVYQUNUX01BVENILAogIH0KCiAgLyoqCiAgICogUG9zc2libGUgb3V0Y29tZXMgd2hlbiB0ZXN0aW5nIGlmIGEgUGhvbmVOdW1iZXIgaXMgcG9zc2libGUuCiAgICovCiAgcHVibGljIGVudW0gVmFsaWRhdGlvblJlc3VsdCB7CiAgICBJU19QT1NTSUJMRSwKICAgIElOVkFMSURfQ09VTlRSWV9DT0RFLAogICAgVE9PX1NIT1JULAogICAgVE9PX0xPTkcsCiAgfQoKICAvKioKICAgKiBUaGlzIGNsYXNzIGltcGxlbWVudHMgYSBzaW5nbGV0b24sIHNvIHRoZSBvbmx5IGNvbnN0cnVjdG9yIGlzIHByaXZhdGUuCiAgICovCiAgcHJpdmF0ZSBQaG9uZU51bWJlclV0aWwoKSB7CiAgfQoKICBwcml2YXRlIHZvaWQgaW5pdChJbnB1dFN0cmVhbSBzb3VyY2UpIHsKICAgIC8vIFJlYWQgaW4gbWV0YWRhdGEgZm9yIGVhY2ggY291bnRyeS4KICAgIHRyeSB7CiAgICAgIE9iamVjdElucHV0U3RyZWFtIGluID0gbmV3IE9iamVjdElucHV0U3RyZWFtKHNvdXJjZSk7CiAgICAgIFBob25lTWV0YWRhdGFDb2xsZWN0aW9uIG1ldGFkYXRhQ29sbGVjdGlvbiA9IG5ldyBQaG9uZU1ldGFkYXRhQ29sbGVjdGlvbigpOwogICAgICBtZXRhZGF0YUNvbGxlY3Rpb24ucmVhZEV4dGVybmFsKGluKTsKICAgICAgZm9yIChQaG9uZU1ldGFkYXRhIG1ldGFkYXRhIDogbWV0YWRhdGFDb2xsZWN0aW9uLmdldE1ldGFkYXRhTGlzdCgpKSB7CiAgICAgICAgU3RyaW5nIHJlZ2lvbkNvZGUgPSBtZXRhZGF0YS5nZXRJZCgpOwogICAgICAgIGNvdW50cnlUb01ldGFkYXRhTWFwLnB1dChyZWdpb25Db2RlLCBtZXRhZGF0YSk7CiAgICAgICAgY291bnRyeVRvTWV0YWRhdGFNYXAucHV0KHJlZ2lvbkNvZGUudG9Mb3dlckNhc2UoKSwgbWV0YWRhdGEpOwogICAgICAgIGludCBjb3VudHJ5Q29kZSA9IG1ldGFkYXRhLmdldENvdW50cnlDb2RlKCk7CiAgICAgICAgaWYgKGNvdW50cnlDb2RlVG9SZWdpb25Db2RlTWFwLmNvbnRhaW5zS2V5KGNvdW50cnlDb2RlKSkgewogICAgICAgICAgaWYgKG1ldGFkYXRhLmdldE1haW5Db3VudHJ5Rm9yQ29kZSgpKSB7CiAgICAgICAgICAgIGNvdW50cnlDb2RlVG9SZWdpb25Db2RlTWFwLmdldChjb3VudHJ5Q29kZSkuYWRkKDAsIHJlZ2lvbkNvZGUpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgY291bnRyeUNvZGVUb1JlZ2lvbkNvZGVNYXAuZ2V0KGNvdW50cnlDb2RlKS5hZGQocmVnaW9uQ29kZSk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIC8vIEZvciBtb3N0IGNvdW50cmllcywgdGhlcmUgd2lsbCBiZSBvbmx5IG9uZSByZWdpb24gY29kZSBmb3IgdGhlIGNvdW50cnkgZGlhbGluZyBjb2RlLgogICAgICAgICAgTGlzdDxTdHJpbmc+IGxpc3RXaXRoUmVnaW9uQ29kZSA9IG5ldyBBcnJheUxpc3Q8U3RyaW5nPigxKTsKICAgICAgICAgIGxpc3RXaXRoUmVnaW9uQ29kZS5hZGQocmVnaW9uQ29kZSk7CiAgICAgICAgICBjb3VudHJ5Q29kZVRvUmVnaW9uQ29kZU1hcC5wdXQoY291bnRyeUNvZGUsIGxpc3RXaXRoUmVnaW9uQ29kZSk7CiAgICAgICAgfQogICAgICAgIGlmIChjb3VudHJ5Q29kZSA9PSBOQU5QQV9DT1VOVFJZX0NPREUpIHsKICAgICAgICAgIG5hbnBhQ291bnRyaWVzLmFkZChyZWdpb25Db2RlKTsKICAgICAgICAgIG5hbnBhQ291bnRyaWVzLmFkZChyZWdpb25Db2RlLnRvTG93ZXJDYXNlKCkpOwogICAgICAgIH0KICAgICAgfQogICAgfSBjYXRjaCAoSU9FeGNlcHRpb24gZSkgewogICAgICBMT0dHRVIubG9nKExldmVsLldBUk5JTkcsIGUudG9TdHJpbmcoKSk7CiAgICB9IGNhdGNoIChDbGFzc05vdEZvdW5kRXhjZXB0aW9uIGUpIHsKICAgICAgTE9HR0VSLmxvZyhMZXZlbC5XQVJOSU5HLCBlLnRvU3RyaW5nKCkpOwogICAgfQogIH0KCiAgLyoqCiAgICogQXR0ZW1wdHMgdG8gZXh0cmFjdCBhIHBvc3NpYmxlIG51bWJlciBmcm9tIHRoZSBzdHJpbmcgcGFzc2VkIGluLiBUaGlzIGN1cnJlbnRseSBzdHJpcHMgYWxsCiAgICogbGVhZGluZyBjaGFyYWN0ZXJzIHRoYXQgY291bGQgbm90IGJlIHVzZWQgdG8gc3RhcnQgYSBwaG9uZSBudW1iZXIuIENoYXJhY3RlcnMgdGhhdCBjYW4gYmUgdXNlZAogICAqIHRvIHN0YXJ0IGEgcGhvbmUgbnVtYmVyIGFyZSBkZWZpbmVkIGluIHRoZSBWQUxJRF9TVEFSVF9DSEFSX1BBVFRFUk4uIElmIG5vbmUgb2YgdGhlc2UKICAgKiBjaGFyYWN0ZXJzIGFyZSBmb3VuZCBpbiB0aGUgbnVtYmVyIHBhc3NlZCBpbiwgYW4gZW1wdHkgc3RyaW5nIGlzIHJldHVybmVkLiBUaGlzIGZ1bmN0aW9uIGFsc28KICAgKiBhdHRlbXB0cyB0byBzdHJpcCBvZmYgYW55IGFsdGVybmF0aXZlIGV4dGVuc2lvbnMgb3IgZW5kaW5ncyBpZiB0d28gb3IgbW9yZSBhcmUgcHJlc2VudCwgc3VjaCBhcwogICAqIGluIHRoZSBjYXNlIG9mOiAoNTMwKSA1ODMtNjk4NSB4MzAyL3gyMzAzLiBUaGUgc2Vjb25kIGV4dGVuc2lvbiBoZXJlIG1ha2VzIHRoaXMgYWN0dWFsbHkgdHdvCiAgICogcGhvbmUgbnVtYmVycywgKDUzMCkgNTgzLTY5ODUgeDMwMiBhbmQgKDUzMCkgNTgzLTY5ODUgeDIzMDMuIFdlIHJlbW92ZSB0aGUgc2Vjb25kIGV4dGVuc2lvbiBzbwogICAqIHRoYXQgdGhlIGZpcnN0IG51bWJlciBpcyBwYXJzZWQgY29ycmVjdGx5LgogICAqCiAgICogQHBhcmFtIG51bWJlciAgdGhlIHN0cmluZyB0aGF0IG1pZ2h0IGNvbnRhaW4gYSBwaG9uZSBudW1iZXIKICAgKiBAcmV0dXJuICAgICAgICB0aGUgbnVtYmVyLCBzdHJpcHBlZCBvZiBhbnkgbm9uLXBob25lLW51bWJlciBwcmVmaXggKHN1Y2ggYXMgIlRlbDoiKSBvciBhbiBlbXB0eQogICAqICAgICAgICAgICAgICAgIHN0cmluZyBpZiBubyBjaGFyYWN0ZXIgdXNlZCB0byBzdGFydCBwaG9uZSBudW1iZXJzIChzdWNoIGFzICsgb3IgYW55IGRpZ2l0KSBpcwogICAqICAgICAgICAgICAgICAgIGZvdW5kIGluIHRoZSBudW1iZXIKICAgKi8KICBzdGF0aWMgU3RyaW5nIGV4dHJhY3RQb3NzaWJsZU51bWJlcihTdHJpbmcgbnVtYmVyKSB7CiAgICBNYXRjaGVyIG0gPSBWQUxJRF9TVEFSVF9DSEFSX1BBVFRFUk4ubWF0Y2hlcihudW1iZXIpOwogICAgaWYgKG0uZmluZCgpKSB7CiAgICAgIG51bWJlciA9IG51bWJlci5zdWJzdHJpbmcobS5zdGFydCgpKTsKICAgICAgLy8gUmVtb3ZlIHRyYWlsaW5nIG5vbi1hbHBoYSBub24tbnVtZXJpY2FsIGNoYXJhY3RlcnMuCiAgICAgIE1hdGNoZXIgdHJhaWxpbmdDaGFyc01hdGNoZXIgPSBVTldBTlRFRF9FTkRfQ0hBUl9QQVRURVJOLm1hdGNoZXIobnVtYmVyKTsKICAgICAgaWYgKHRyYWlsaW5nQ2hhcnNNYXRjaGVyLmZpbmQoKSkgewogICAgICAgIG51bWJlciA9IG51bWJlci5zdWJzdHJpbmcoMCwgdHJhaWxpbmdDaGFyc01hdGNoZXIuc3RhcnQoKSk7CiAgICAgIH0KICAgICAgLy8gQ2hlY2sgZm9yIGV4dHJhIG51bWJlcnMgYXQgdGhlIGVuZC4KICAgICAgTWF0Y2hlciBzZWNvbmROdW1iZXIgPSBTRUNPTkRfTlVNQkVSX1NUQVJUX1BBVFRFUk4ubWF0Y2hlcihudW1iZXIpOwogICAgICBpZiAoc2Vjb25kTnVtYmVyLmZpbmQoKSkgewogICAgICAgIG51bWJlciA9IG51bWJlci5zdWJzdHJpbmcoMCwgc2Vjb25kTnVtYmVyLnN0YXJ0KCkpOwogICAgICB9CiAgICAgIHJldHVybiBudW1iZXI7CiAgICB9IGVsc2UgewogICAgICByZXR1cm4gIiI7CiAgICB9CiAgfQoKICAvKioKICAgKiBDaGVja3MgdG8gc2VlIGlmIHRoZSBzdHJpbmcgb2YgY2hhcmFjdGVycyBjb3VsZCBwb3NzaWJseSBiZSBhIHBob25lIG51bWJlciBhdCBhbGwuIEF0IHRoZQogICAqIG1vbWVudCwgY2hlY2tzIHRvIHNlZSB0aGF0IHRoZSBzdHJpbmcgYmVnaW5zIHdpdGggYXQgbGVhc3QgMyBkaWdpdHMsIGlnbm9yaW5nIGFueSBwdW5jdHVhdGlvbgogICAqIGNvbW1vbmx5IGZvdW5kIGluIHBob25lIG51bWJlcnMuCiAgICogVGhpcyBtZXRob2QgZG9lcyBub3QgcmVxdWlyZSB0aGUgbnVtYmVyIHRvIGJlIG5vcm1hbGl6ZWQgaW4gYWR2YW5jZSAtIGJ1dCBkb2VzIGFzc3VtZSB0aGF0CiAgICogbGVhZGluZyBub24tbnVtYmVyIHN5bWJvbHMgaGF2ZSBiZWVuIHJlbW92ZWQsIHN1Y2ggYXMgYnkgdGhlIG1ldGhvZCBleHRyYWN0UG9zc2libGVOdW1iZXIuCiAgICoKICAgKiBAcGFyYW0gbnVtYmVyICBzdHJpbmcgdG8gYmUgY2hlY2tlZCBmb3IgdmlhYmlsaXR5IGFzIGEgcGhvbmUgbnVtYmVyCiAgICogQHJldHVybiAgICAgICAgdHJ1ZSBpZiB0aGUgbnVtYmVyIGNvdWxkIGJlIGEgcGhvbmUgbnVtYmVyIG9mIHNvbWUgc29ydCwgb3RoZXJ3aXNlIGZhbHNlCiAgICovCiAgc3RhdGljIGJvb2xlYW4gaXNWaWFibGVQaG9uZU51bWJlcihTdHJpbmcgbnVtYmVyKSB7CiAgICBpZiAobnVtYmVyLmxlbmd0aCgpIDwgTUlOX0xFTkdUSF9GT1JfTlNOKSB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICAgIE1hdGNoZXIgbSA9IFZBTElEX1BIT05FX05VTUJFUl9QQVRURVJOLm1hdGNoZXIobnVtYmVyKTsKICAgIHJldHVybiBtLm1hdGNoZXMoKTsKICB9CgogIC8qKgogICAqIE5vcm1hbGl6ZXMgYSBzdHJpbmcgb2YgY2hhcmFjdGVycyByZXByZXNlbnRpbmcgYSBwaG9uZSBudW1iZXIuIFRoaXMgcGVyZm9ybXMgdGhlIGZvbGxvd2luZwogICAqIGNvbnZlcnNpb25zOgogICAqICAgV2lkZS1hc2NpaSBkaWdpdHMgYXJlIGNvbnZlcnRlZCB0byBub3JtYWwgQVNDSUkgKEV1cm9wZWFuKSBkaWdpdHMuCiAgICogICBMZXR0ZXJzIGFyZSBjb252ZXJ0ZWQgdG8gdGhlaXIgbnVtZXJpYyByZXByZXNlbnRhdGlvbiBvbiBhIHRlbGVwaG9uZSBrZXlwYWQuIFRoZSBrZXlwYWQKICAgKiAgICAgICB1c2VkIGhlcmUgaXMgdGhlIG9uZSBkZWZpbmVkIGluIElUVSBSZWNvbW1lbmRhdGlvbiBFLjE2MS4gVGhpcyBpcyBvbmx5IGRvbmUgaWYgdGhlcmUgYXJlCiAgICogICAgICAgMyBvciBtb3JlIGxldHRlcnMgaW4gdGhlIG51bWJlciwgdG8gbGVzc2VuIHRoZSByaXNrIHRoYXQgc3VjaCBsZXR0ZXJzIGFyZSB0eXBvcyAtCiAgICogICAgICAgb3RoZXJ3aXNlIGFscGhhIGNoYXJhY3RlcnMgYXJlIHN0cmlwcGVkLgogICAqICAgUHVuY3R1YXRpb24gaXMgc3RyaXBwZWQuCiAgICogICBBcmFiaWMtSW5kaWMgbnVtZXJhbHMgYXJlIGNvbnZlcnRlZCB0byBFdXJvcGVhbiBudW1lcmFscy4KICAgKgogICAqIEBwYXJhbSBudW1iZXIgIGEgc3RyaW5nIG9mIGNoYXJhY3RlcnMgcmVwcmVzZW50aW5nIGEgcGhvbmUgbnVtYmVyCiAgICogQHJldHVybiAgICAgICAgdGhlIG5vcm1hbGl6ZWQgc3RyaW5nIHZlcnNpb24gb2YgdGhlIHBob25lIG51bWJlcgogICAqLwogIHN0YXRpYyBTdHJpbmcgbm9ybWFsaXplKFN0cmluZyBudW1iZXIpIHsKICAgIE1hdGNoZXIgbSA9IFZBTElEX0FMUEhBX1BIT05FX1BBVFRFUk4ubWF0Y2hlcihudW1iZXIpOwogICAgaWYgKG0ubWF0Y2hlcygpKSB7CiAgICAgIHJldHVybiBub3JtYWxpemVIZWxwZXIobnVtYmVyLCBBTExfTk9STUFMSVpBVElPTl9NQVBQSU5HUywgdHJ1ZSk7CiAgICB9IGVsc2UgewogICAgICByZXR1cm4gbm9ybWFsaXplSGVscGVyKG51bWJlciwgRElHSVRfTUFQUElOR1MsIHRydWUpOwogICAgfQogIH0KCiAgLyoqCiAgICogTm9ybWFsaXplcyBhIHN0cmluZyBvZiBjaGFyYWN0ZXJzIHJlcHJlc2VudGluZyBhIHBob25lIG51bWJlci4gVGhpcyBpcyBhIHdyYXBwZXIgZm9yCiAgICogbm9ybWFsaXplKFN0cmluZyBudW1iZXIpIGJ1dCBkb2VzIGluLXBsYWNlIG5vcm1hbGl6YXRpb24gb2YgdGhlIFN0cmluZ0J1ZmZlciBwcm92aWRlZC4KICAgKgogICAqIEBwYXJhbSBudW1iZXIgIGEgU3RyaW5nQnVmZmVyIG9mIGNoYXJhY3RlcnMgcmVwcmVzZW50aW5nIGEgcGhvbmUgbnVtYmVyIHRoYXQgd2lsbCBiZSBub3JtYWxpemVkCiAgICogICAgIGluIHBsYWNlCiAgICovCiAgc3RhdGljIHZvaWQgbm9ybWFsaXplKFN0cmluZ0J1ZmZlciBudW1iZXIpIHsKICAgIFN0cmluZyBub3JtYWxpemVkTnVtYmVyID0gbm9ybWFsaXplKG51bWJlci50b1N0cmluZygpKTsKICAgIG51bWJlci5yZXBsYWNlKDAsIG51bWJlci5sZW5ndGgoKSwgbm9ybWFsaXplZE51bWJlcik7CiAgfQoKICAvKioKICAgKiBOb3JtYWxpemVzIGEgc3RyaW5nIG9mIGNoYXJhY3RlcnMgcmVwcmVzZW50aW5nIGEgcGhvbmUgbnVtYmVyLiBUaGlzIGNvbnZlcnRzIHdpZGUtYXNjaWkgYW5kCiAgICogYXJhYmljLWluZGljIG51bWVyYWxzIHRvIEV1cm9wZWFuIG51bWVyYWxzLCBhbmQgc3RyaXBzIHB1bmN0dWF0aW9uIGFuZCBhbHBoYSBjaGFyYWN0ZXJzLgogICAqCiAgICogQHBhcmFtIG51bWJlciAgYSBzdHJpbmcgb2YgY2hhcmFjdGVycyByZXByZXNlbnRpbmcgYSBwaG9uZSBudW1iZXIKICAgKiBAcmV0dXJuICAgICAgICB0aGUgbm9ybWFsaXplZCBzdHJpbmcgdmVyc2lvbiBvZiB0aGUgcGhvbmUgbnVtYmVyCiAgICovCiAgcHVibGljIHN0YXRpYyBTdHJpbmcgbm9ybWFsaXplRGlnaXRzT25seShTdHJpbmcgbnVtYmVyKSB7CiAgICByZXR1cm4gbm9ybWFsaXplSGVscGVyKG51bWJlciwgRElHSVRfTUFQUElOR1MsIHRydWUpOwogIH0KCiAgLyoqCiAgICogQ29udmVydHMgYWxsIGFscGhhIGNoYXJhY3RlcnMgaW4gYSBudW1iZXIgdG8gdGhlaXIgcmVzcGVjdGl2ZSBkaWdpdHMgb24gYSBrZXlwYWQsIGJ1dCByZXRhaW5zCiAgICogZXhpc3RpbmcgZm9ybWF0dGluZy4gQWxzbyBjb252ZXJ0cyB3aWRlLWFzY2lpIGRpZ2l0cyB0byBub3JtYWwgYXNjaWkgZGlnaXRzLCBhbmQgY29udmVydHMKICAgKiBBcmFiaWMtSW5kaWMgbnVtZXJhbHMgdG8gRXVyb3BlYW4gbnVtZXJhbHMuCiAgICovCiAgcHVibGljIHN0YXRpYyBTdHJpbmcgY29udmVydEFscGhhQ2hhcmFjdGVyc0luTnVtYmVyKFN0cmluZyBudW1iZXIpIHsKICAgIHJldHVybiBub3JtYWxpemVIZWxwZXIobnVtYmVyLCBBTExfTk9STUFMSVpBVElPTl9NQVBQSU5HUywgZmFsc2UpOwogIH0KCiAgLyoqCiAgICogR2V0cyB0aGUgbGVuZ3RoIG9mIHRoZSBnZW9ncmFwaGljYWwgYXJlYSBjb2RlIGZyb20gdGhlIG5hdGlvbmFsX251bWJlciBmaWVsZCBvZiB0aGUgUGhvbmVOdW1iZXIKICAgKiBvYmplY3QgcGFzc2VkIGluLCBzbyB0aGF0IGNsaWVudHMgY291bGQgdXNlIGl0IHRvIHNwbGl0IGEgbmF0aW9uYWwgc2lnbmlmaWNhbnQgbnVtYmVyIGludG8KICAgKiBnZW9ncmFwaGljYWwgYXJlYSBjb2RlIGFuZCBzdWJzY3JpYmVyIG51bWJlci4gSXQgd29ya3MgaW4gc3VjaCBhIHdheSB0aGF0IHRoZSByZXN1bHRhbnQKICAgKiBzdWJzY3JpYmVyIG51bWJlciBzaG91bGQgYmUgZGlhbGxhYmxlLCBhdCBsZWFzdCBvbiBzb21lIGRldmljZXMuIEFuIGV4YW1wbGUgb2YgaG93IHRoaXMgY291bGQKICAgKiBiZSB1c2VkOgogICAqCiAgICogUGhvbmVOdW1iZXJVdGlsIHBob25lVXRpbC5QaG9uZU51bWJlclV0aWwuZ2V0SW5zdGFuY2UoKTsKICAgKiBQaG9uZU51bWJlciBudW1iZXIgPSBwaG9uZVV0aWwucGFyc2UoIjE2NTAyNTMwMDAwIiwgUmVnaW9uQ29kZS5VUyk7CiAgICogU3RyaW5nIG5hdGlvbmFsU2lnbmlmaWNhbnROdW1iZXIgPSBQaG9uZU51bWJlclV0aWwuZ2V0TmF0aW9uYWxTaWduaWZpY2FudE51bWJlcihudW1iZXIpOwogICAqIFN0cmluZyBhcmVhQ29kZTsKICAgKiBTdHJpbmcgc3Vic2NyaWJlck51bWJlcjsKICAgKgogICAqIGludCBhcmVhQ29kZUxlbmd0aCA9IHBob25lVXRpbC5nZXRMZW5ndGhPZkdlb2dyYXBoaWNhbEFyZWFDb2RlKG51bWJlcik7CiAgICogaWYgKGFyZWFDb2RlTGVuZ3RoID4gMCkgewogICAqICAgYXJlYUNvZGUgPSBuYXRpb25hbFNpZ25pZmljYW50TnVtYmVyLnN1YnN0cmluZygwLCBhcmVhQ29kZUxlbmd0aCk7CiAgICogICBzdWJzY3JpYmVyTnVtYmVyID0gbmF0aW9uYWxTaWduaWZpY2FudE51bWJlci5zdWJzdHJpbmcoYXJlYUNvZGVMZW5ndGgpOwogICAqIH0gZWxzZSB7CiAgICogICBhcmVhQ29kZSA9ICIiOwogICAqICAgc3Vic2NyaWJlck51bWJlciA9IG5hdGlvbmFsU2lnbmlmaWNhbnROdW1iZXI7CiAgICogfQogICAqCiAgICogTi5CLjogYXJlYSBjb2RlIGlzIGEgdmVyeSBhbWJpZ3VvdXMgY29uY2VwdCwgc28gdGhlIEkxOE4gdGVhbSBnZW5lcmFsbHkgcmVjb21tZW5kcyBhZ2FpbnN0CiAgICogdXNpbmcgaXQgZm9yIG1vc3QgcHVycG9zZXMsIGJ1dCByZWNvbW1lbmRzIHVzaW5nIHRoZSBtb3JlIGdlbmVyYWwgbmF0aW9uYWxfbnVtYmVyIGluc3RlYWQuIFJlYWQKICAgKiB0aGUgZm9sbG93aW5nIGNhcmVmdWxseSBiZWZvcmUgZGVjaWRpbmcgdG8gdXNlIHRoaXMgbWV0aG9kOgogICAqCiAgICogIC0gZ2VvZ3JhcGhpY2FsIGFyZWEgY29kZXMgY2hhbmdlIG92ZXIgdGltZSwgYW5kIHRoaXMgbWV0aG9kIGhvbm9ycyB0aG9zZSBjaGFuZ2VzOyB0aGVyZWZvcmUsCiAgICogICAgaXQgZG9lc24ndCBndWFyYW50ZWUgdGhlIHN0YWJpbGl0eSBvZiB0aGUgcmVzdWx0IGl0IHByb2R1Y2VzLgogICAqICAtIHN1YnNjcmliZXIgbnVtYmVycyBtYXkgbm90IGJlIGRpYWxsYWJsZSBmcm9tIGFsbCBkZXZpY2VzIChub3RhYmx5IG1vYmlsZSBkZXZpY2VzLCB3aGljaAogICAqICAgIHR5cGljYWxseSByZXF1aXJlcyB0aGUgZnVsbCBuYXRpb25hbF9udW1iZXIgdG8gYmUgZGlhbGxlZCBpbiBtb3N0IGNvdW50cmllcykuCiAgICogIC0gbW9zdCBub24tZ2VvZ3JhcGhpY2FsIG51bWJlcnMgaGF2ZSBubyBhcmVhIGNvZGVzLgogICAqICAtIHNvbWUgZ2VvZ3JhcGhpY2FsIG51bWJlcnMgaGF2ZSBubyBhcmVhIGNvZGVzLgogICAqCiAgICogQHBhcmFtIG51bWJlciAgdGhlIFBob25lTnVtYmVyIG9iamVjdCBmb3Igd2hpY2ggY2xpZW50cyB3YW50IHRvIGtub3cgdGhlIGxlbmd0aCBvZiB0aGUgYXJlYQogICAqICAgICBjb2RlIGluIHRoZSBuYXRpb25hbF9udW1iZXIgZmllbGQuCiAgICogQHJldHVybiAgdGhlIGxlbmd0aCBvZiBhcmVhIGNvZGUgb2YgdGhlIFBob25lTnVtYmVyIG9iamVjdCBwYXNzZWQgaW4uCiAgICovCiAgcHVibGljIGludCBnZXRMZW5ndGhPZkdlb2dyYXBoaWNhbEFyZWFDb2RlKFBob25lTnVtYmVyIG51bWJlcikgewogICAgU3RyaW5nIHJlZ2lvbkNvZGUgPSBnZXRSZWdpb25Db2RlRm9yTnVtYmVyKG51bWJlcik7CiAgICBpZiAoIWlzVmFsaWRSZWdpb25Db2RlKHJlZ2lvbkNvZGUpKSB7CiAgICAgIHJldHVybiAwOwogICAgfQogICAgUGhvbmVNZXRhZGF0YSBtZXRhZGF0YSA9IGdldE1ldGFkYXRhRm9yUmVnaW9uKHJlZ2lvbkNvZGUpOwogICAgLy8gRm9yIE5BTlBBIGNvdW50cmllcywgbmF0aW9uYWwgcHJlZml4IGlzIHRoZSBzYW1lIGFzIGNvdW50cnkgY29kZSwgYnV0IGl0IGlzIG5vdCBzdG9yZWQgaW4KICAgIC8vIHRoZSBtZXRhZGF0YS4KICAgIGlmICghbWV0YWRhdGEuaGFzTmF0aW9uYWxQcmVmaXgoKSAmJiAhaXNOQU5QQUNvdW50cnkocmVnaW9uQ29kZSkpIHsKICAgICAgcmV0dXJuIDA7CiAgICB9CgogICAgUGhvbmVOdW1iZXJUeXBlIHR5cGUgPSBnZXROdW1iZXJUeXBlSGVscGVyKFN0cmluZy52YWx1ZU9mKG51bWJlci5nZXROYXRpb25hbE51bWJlcigpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YSk7CiAgICAvLyBNb3N0IG51bWJlcnMgb3RoZXIgdGhhbiB0aGUgdHdvIHR5cGVzIGJlbG93IGhhdmUgdG8gYmUgZGlhbGxlZCBpbiBmdWxsLgogICAgaWYgKHR5cGUgIT0gUGhvbmVOdW1iZXJUeXBlLkZJWEVEX0xJTkUgJiYgdHlwZSAhPSBQaG9uZU51bWJlclR5cGUuRklYRURfTElORV9PUl9NT0JJTEUpIHsKICAgICAgcmV0dXJuIDA7CiAgICB9CgogICAgUGhvbmVOdW1iZXIgY29waWVkUHJvdG87CiAgICBpZiAobnVtYmVyLmhhc0V4dGVuc2lvbigpKSB7CiAgICAgIC8vIFdlIGRvbid0IHdhbnQgdG8gYWx0ZXIgdGhlIHByb3RvIGdpdmVuIHRvIHVzLCBidXQgd2UgZG9uJ3Qgd2FudCB0byBpbmNsdWRlIHRoZSBleHRlbnNpb24KICAgICAgLy8gd2hlbiB3ZSBmb3JtYXQgaXQsIHNvIHdlIGNvcHkgaXQgYW5kIGNsZWFyIHRoZSBleHRlbnNpb24gaGVyZS4KICAgICAgY29waWVkUHJvdG8gPSBuZXcgUGhvbmVOdW1iZXIoKTsKICAgICAgY29waWVkUHJvdG8ubWVyZ2VGcm9tKG51bWJlcik7CiAgICAgIGNvcGllZFByb3RvLmNsZWFyRXh0ZW5zaW9uKCk7CiAgICB9IGVsc2UgewogICAgICBjb3BpZWRQcm90byA9IG51bWJlcjsKICAgIH0KCiAgICBTdHJpbmcgbmF0aW9uYWxTaWduaWZpY2FudE51bWJlciA9IGZvcm1hdChjb3BpZWRQcm90bywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFBob25lTnVtYmVyVXRpbC5QaG9uZU51bWJlckZvcm1hdC5JTlRFUk5BVElPTkFMKTsKICAgIFN0cmluZ1tdIG51bWJlckdyb3VwcyA9IE5PTl9ESUdJVF9QQVRURVJOLnNwbGl0KG5hdGlvbmFsU2lnbmlmaWNhbnROdW1iZXIpOwogICAgLy8gVGhlIHBhdHRlcm4gd2lsbCBzdGFydCB3aXRoICIrQ09VTlRSWV9DT0RFICIgc28gdGhlIGZpcnN0IGdyb3VwIHdpbGwgYWx3YXlzIGJlIHRoZSBlbXB0eQogICAgLy8gc3RyaW5nIChiZWZvcmUgdGhlICsgc3ltYm9sKSBhbmQgdGhlIHNlY29uZCBncm91cCB3aWxsIGJlIHRoZSBjb3VudHJ5IGNvZGUuIFRoZSB0aGlyZCBncm91cAogICAgLy8gd2lsbCBiZSBhcmVhIGNvZGUgaWYgaXQgaXMgbm90IHRoZSBsYXN0IGdyb3VwLgogICAgaWYgKG51bWJlckdyb3Vwcy5sZW5ndGggPD0gMykgewogICAgICByZXR1cm4gMDsKICAgIH0KICAgIC8vIE5vdGUgYWxsIGNvdW50cmllcyB0aGF0IHVzZSBsZWFkaW5nIHplcm8gaW4gbmF0aW9uYWwgbnVtYmVyIGRvbid0IHVzZSBuYXRpb25hbCBwcmVmaXgsIHNvCiAgICAvLyB0aGV5IHdvbid0IGhhdmUgYW4gYXJlYSBjb2RlLCB3aGljaCBtZWFucyBjbGllbnRzIGRvbid0IG5lZWQgdG8gd29ycnkgYWJvdXQgYXBwZW5kaW5nIHRoZQogICAgLy8gbGVhZGluZyB6ZXJvIHRvIHRoZSBnZW9ncmFwaGljYWwgYXJlYSBjb2RlIHRoZXkgZGVyaXZlIGZyb20gdGhlIGxlbmd0aCB3ZSByZXR1cm4gaGVyZS4KICAgIHJldHVybiBudW1iZXJHcm91cHNbMl0ubGVuZ3RoKCk7CiAgfSAgCgogIC8qKgogICAqIE5vcm1hbGl6ZXMgYSBzdHJpbmcgb2YgY2hhcmFjdGVycyByZXByZXNlbnRpbmcgYSBwaG9uZSBudW1iZXIgYnkgcmVwbGFjaW5nIGFsbCBjaGFyYWN0ZXJzIGZvdW5kCiAgICogaW4gdGhlIGFjY29tcGFueWluZyBtYXAgd2l0aCB0aGUgdmFsdWVzIHRoZXJlaW4sIGFuZCBzdHJpcHBpbmcgYWxsIG90aGVyIGNoYXJhY3RlcnMgaWYKICAgKiByZW1vdmVOb25NYXRjaGVzIGlzIHRydWUuCiAgICoKICAgKiBAcGFyYW0gbnVtYmVyICAgICAgICAgICAgICAgICAgICAgYSBzdHJpbmcgb2YgY2hhcmFjdGVycyByZXByZXNlbnRpbmcgYSBwaG9uZSBudW1iZXIKICAgKiBAcGFyYW0gbm9ybWFsaXphdGlvblJlcGxhY2VtZW50cyAgYSBtYXBwaW5nIG9mIGNoYXJhY3RlcnMgdG8gd2hhdCB0aGV5IHNob3VsZCBiZSByZXBsYWNlZCBieSBpbgogICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGUgbm9ybWFsaXplZCB2ZXJzaW9uIG9mIHRoZSBwaG9uZSBudW1iZXIKICAgKiBAcGFyYW0gcmVtb3ZlTm9uTWF0Y2hlcyAgICAgICAgICAgaW5kaWNhdGVzIHdoZXRoZXIgY2hhcmFjdGVycyB0aGF0IGFyZSBub3QgYWJsZSB0byBiZSByZXBsYWNlZAogICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaG91bGQgYmUgc3RyaXBwZWQgZnJvbSB0aGUgbnVtYmVyLiBJZiB0aGlzIGlzIGZhbHNlLCB0aGV5CiAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpbGwgYmUgbGVmdCB1bmNoYW5nZWQgaW4gdGhlIG51bWJlci4KICAgKiBAcmV0dXJuICB0aGUgbm9ybWFsaXplZCBzdHJpbmcgdmVyc2lvbiBvZiB0aGUgcGhvbmUgbnVtYmVyCiAgICovCiAgcHJpdmF0ZSBzdGF0aWMgU3RyaW5nIG5vcm1hbGl6ZUhlbHBlcigKICAgICAgU3RyaW5nIG51bWJlciwKICAgICAgTWFwPENoYXJhY3RlciwgQ2hhcmFjdGVyPiBub3JtYWxpemF0aW9uUmVwbGFjZW1lbnRzLAogICAgICBib29sZWFuIHJlbW92ZU5vbk1hdGNoZXMpIHsKICAgIFN0cmluZ0J1ZmZlciBub3JtYWxpemVkTnVtYmVyID0gbmV3IFN0cmluZ0J1ZmZlcihudW1iZXIubGVuZ3RoKCkpOwogICAgY2hhcltdIG51bWJlckFzQ2hhckFycmF5ID0gbnVtYmVyLnRvQ2hhckFycmF5KCk7CiAgICBmb3IgKGNoYXIgY2hhcmFjdGVyIDogbnVtYmVyQXNDaGFyQXJyYXkpIHsKICAgICAgQ2hhcmFjdGVyIG5ld0RpZ2l0ID0gbm9ybWFsaXphdGlvblJlcGxhY2VtZW50cy5nZXQoQ2hhcmFjdGVyLnRvVXBwZXJDYXNlKGNoYXJhY3RlcikpOwogICAgICBpZiAobmV3RGlnaXQgIT0gbnVsbCkgewogICAgICAgIG5vcm1hbGl6ZWROdW1iZXIuYXBwZW5kKG5ld0RpZ2l0KTsKICAgICAgfSBlbHNlIGlmICghcmVtb3ZlTm9uTWF0Y2hlcykgewogICAgICAgIG5vcm1hbGl6ZWROdW1iZXIuYXBwZW5kKGNoYXJhY3Rlcik7CiAgICAgIH0KICAgICAgLy8gSWYgbmVpdGhlciBvZiB0aGUgYWJvdmUgYXJlIHRydWUsIHdlIHJlbW92ZSB0aGlzIGNoYXJhY3Rlci4KICAgIH0KICAgIHJldHVybiBub3JtYWxpemVkTnVtYmVyLnRvU3RyaW5nKCk7CiAgfQoKICBzdGF0aWMgc3luY2hyb25pemVkIFBob25lTnVtYmVyVXRpbCBnZXRJbnN0YW5jZShJbnB1dFN0cmVhbSBzb3VyY2UpIHsKICAgIGlmIChpbnN0YW5jZSA9PSBudWxsKSB7CiAgICAgIGluc3RhbmNlID0gbmV3IFBob25lTnVtYmVyVXRpbCgpOwogICAgICBpbnN0YW5jZS5pbml0KHNvdXJjZSk7CiAgICB9CiAgICByZXR1cm4gaW5zdGFuY2U7CiAgfQoKICAvKioKICAgKiBVc2VkIGZvciB0ZXN0aW5nIHB1cnBvc2VzIG9ubHkgdG8gcmVzZXQgdGhlIFBob25lTnVtYmVyVXRpbCBzaW5nbGV0b24gdG8gbnVsbC4KICAgKi8KICBzdGF0aWMgc3luY2hyb25pemVkIHZvaWQgcmVzZXRJbnN0YW5jZSgpIHsKICAgIGluc3RhbmNlID0gbnVsbDsKICB9CgogIC8qKgogICAqIENvbnZlbmllbmNlIG1ldGhvZCB0byBlbmFibGUgdGVzdHMgdG8gZ2V0IGEgbGlzdCBvZiB3aGF0IGNvdW50cmllcyB0aGUgbGlicmFyeSBoYXMgbWV0YWRhdGEKICAgKiBmb3IuCiAgICovCnB1YmxpYyBTZXQ8U3RyaW5nPiBnZXRTdXBwb3J0ZWRDb3VudHJpZXMoKSB7CiAgICByZXR1cm4gY291bnRyeVRvTWV0YWRhdGFNYXAua2V5U2V0KCk7CiAgfQoKICAvKioKICAgKiBHZXRzIGEgUGhvbmVOdW1iZXJVdGlsIGluc3RhbmNlIHRvIGNhcnJ5IG91dCBpbnRlcm5hdGlvbmFsIHBob25lIG51bWJlciBmb3JtYXR0aW5nLCBwYXJzaW5nLAogICAqIG9yIHZhbGlkYXRpb24uIFRoZSBpbnN0YW5jZSBpcyBsb2FkZWQgd2l0aCBwaG9uZSBudW1iZXIgbWV0YWRhdGEgZm9yIGEgbnVtYmVyIG9mIG1vc3QgY29tbW9ubHkKICAgKiB1c2VkIGNvdW50cmllcy9yZWdpb25zLgogICAqCiAgICogVGhlIFBob25lTnVtYmVyVXRpbCBpcyBpbXBsZW1lbnRlZCBhcyBhIHNpbmdsZXRvbi4gVGhlcmVmb3JlLCBjYWxsaW5nIGdldEluc3RhbmNlIG11bHRpcGxlCiAgICogdGltZXMgd2lsbCBvbmx5IHJlc3VsdCBpbiBvbmUgaW5zdGFuY2UgYmVpbmcgY3JlYXRlZC4KICAgKgogICAqIEByZXR1cm4gYSBQaG9uZU51bWJlclV0aWwgaW5zdGFuY2UKICAgKi8KICBwdWJsaWMgc3RhdGljIHN5bmNocm9uaXplZCBQaG9uZU51bWJlclV0aWwgZ2V0SW5zdGFuY2UoKSB7CiAgICBpZiAoaW5zdGFuY2UgPT0gbnVsbCkgewogICAgICBpbnN0YW5jZSA9IG5ldyBQaG9uZU51bWJlclV0aWwoKTsKICAgICAgSW5wdXRTdHJlYW0gaW4gPSBQaG9uZU51bWJlclV0aWwuY2xhc3MuZ2V0UmVzb3VyY2VBc1N0cmVhbShNRVRBX0RBVEFfRklMRSk7CiAgICAgIGluc3RhbmNlLmluaXQoaW4pOwogICAgfQogICAgcmV0dXJuIGluc3RhbmNlOwogIH0KCiAgLyoqCiAgICogSGVscGVyIGZ1bmN0aW9uIHRvIGNoZWNrIHJlZ2lvbiBjb2RlIGlzIG5vdCB1bmtub3duIG9yIG51bGwuCiAgICovCiAgcHJpdmF0ZSBib29sZWFuIGlzVmFsaWRSZWdpb25Db2RlKFN0cmluZyByZWdpb25Db2RlKSB7CiAgICByZXR1cm4gY291bnRyeVRvTWV0YWRhdGFNYXAuY29udGFpbnNLZXkocmVnaW9uQ29kZSk7CiAgfQoKICAvKioKICAgKiBGb3JtYXRzIGEgcGhvbmUgbnVtYmVyIGluIHRoZSBzcGVjaWZpZWQgZm9ybWF0IHVzaW5nIGRlZmF1bHQgcnVsZXMuIE5vdGUgdGhhdCB0aGlzIGRvZXMgbm90CiAgICogcHJvbWlzZSB0byBwcm9kdWNlIGEgcGhvbmUgbnVtYmVyIHRoYXQgdGhlIHVzZXIgY2FuIGRpYWwgZnJvbSB3aGVyZSB0aGV5IGFyZSAtIGFsdGhvdWdoIHdlIGRvCiAgICogZm9ybWF0IGluIGVpdGhlciAnbmF0aW9uYWwnIG9yICdpbnRlcm5hdGlvbmFsJyBmb3JtYXQgZGVwZW5kaW5nIG9uIHdoYXQgdGhlIGNsaWVudCBhc2tzIGZvciwgd2UKICAgKiBkbyBub3QgY3VycmVudGx5IHN1cHBvcnQgYSBtb3JlIGFiYnJldmlhdGVkIGZvcm1hdCwgc3VjaCBhcyBmb3IgdXNlcnMgaW4gdGhlIHNhbWUgImFyZWEiIHdobwogICAqIGNvdWxkIHBvdGVudGlhbGx5IGRpYWwgdGhlIG51bWJlciB3aXRob3V0IGFyZWEgY29kZS4gTm90ZSB0aGF0IGlmIHRoZSBwaG9uZSBudW1iZXIgaGFzIGEKICAgKiBjb3VudHJ5IGNvZGUgb2YgMCBvciBhbiBvdGhlcndpc2UgaW52YWxpZCBjb3VudHJ5IGNvZGUsIHdlIGNhbm5vdCB3b3JrIG91dCB3aGljaCBmb3JtYXR0aW5nCiAgICogcnVsZXMgdG8gYXBwbHkgc28gd2UgcmV0dXJuIHRoZSBuYXRpb25hbCBzaWduaWZpY2FudCBudW1iZXIgd2l0aCBubyBmb3JtYXR0aW5nIGFwcGxpZWQuCiAgICoKICAgKiBAcGFyYW0gbnVtYmVyICAgICAgICAgdGhlIHBob25lIG51bWJlciB0byBiZSBmb3JtYXR0ZWQKICAgKiBAcGFyYW0gbnVtYmVyRm9ybWF0ICAgdGhlIGZvcm1hdCB0aGUgcGhvbmUgbnVtYmVyIHNob3VsZCBiZSBmb3JtYXR0ZWQgaW50bwogICAqIEByZXR1cm4gIHRoZSBmb3JtYXR0ZWQgcGhvbmUgbnVtYmVyCiAgICovCiAgcHVibGljIFN0cmluZyBmb3JtYXQoUGhvbmVOdW1iZXIgbnVtYmVyLCBQaG9uZU51bWJlckZvcm1hdCBudW1iZXJGb3JtYXQpIHsKICAgIFN0cmluZ0J1ZmZlciBmb3JtYXR0ZWROdW1iZXIgPSBuZXcgU3RyaW5nQnVmZmVyKDIwKTsKICAgIGZvcm1hdChudW1iZXIsIG51bWJlckZvcm1hdCwgZm9ybWF0dGVkTnVtYmVyKTsKICAgIHJldHVybiBmb3JtYXR0ZWROdW1iZXIudG9TdHJpbmcoKTsKICB9CgogIC8vIFNhbWUgYXMgZm9ybWF0KFBob25lTnVtYmVyLCBQaG9uZU51bWJlckZvcm1hdCksIGJ1dCBhY2NlcHRzIG11dGFibGUgU3RyaW5nQnVmZmVyIGFzIHBhcmFtZXRlcnMKICAvLyB0byBkZWNyZWFzZSBvYmplY3QgY3JlYXRpb24gd2hlbiBpbnZva2VkIG1hbnkgdGltZXMuCiAgcHVibGljIHZvaWQgZm9ybWF0KFBob25lTnVtYmVyIG51bWJlciwgUGhvbmVOdW1iZXJGb3JtYXQgbnVtYmVyRm9ybWF0LAogICAgICAgICAgICAgICAgICAgICBTdHJpbmdCdWZmZXIgZm9ybWF0dGVkTnVtYmVyKSB7CiAgICAvLyBDbGVhciB0aGUgU3RyaW5nQnVmZmVyIGZpcnN0LgogICAgZm9ybWF0dGVkTnVtYmVyLnNldExlbmd0aCgwKTsKICAgIGludCBjb3VudHJ5Q29kZSA9IG51bWJlci5nZXRDb3VudHJ5Q29kZSgpOwogICAgU3RyaW5nIG5hdGlvbmFsU2lnbmlmaWNhbnROdW1iZXIgPSBnZXROYXRpb25hbFNpZ25pZmljYW50TnVtYmVyKG51bWJlcik7CiAgICBpZiAobnVtYmVyRm9ybWF0ID09IFBob25lTnVtYmVyRm9ybWF0LkUxNjQpIHsKICAgICAgLy8gRWFybHkgZXhpdCBmb3IgRTE2NCBjYXNlIHNpbmNlIG5vIGZvcm1hdHRpbmcgb2YgdGhlIG5hdGlvbmFsIG51bWJlciBuZWVkcyB0byBiZSBhcHBsaWVkLgogICAgICAvLyBFeHRlbnNpb25zIGFyZSBub3QgZm9ybWF0dGVkLgogICAgICBmb3JtYXR0ZWROdW1iZXIuYXBwZW5kKG5hdGlvbmFsU2lnbmlmaWNhbnROdW1iZXIpOwogICAgICBmb3JtYXROdW1iZXJCeUZvcm1hdChjb3VudHJ5Q29kZSwgUGhvbmVOdW1iZXJGb3JtYXQuRTE2NCwgZm9ybWF0dGVkTnVtYmVyKTsKICAgICAgcmV0dXJuOwogICAgfQogICAgLy8gTm90ZSBnZXRSZWdpb25Db2RlRm9yQ291bnRyeUNvZGUoKSBpcyB1c2VkIGJlY2F1c2UgZm9ybWF0dGluZyBpbmZvcm1hdGlvbiBmb3IgY291bnRyaWVzIHdoaWNoCiAgICAvLyBzaGFyZSBhIGNvdW50cnkgY29kZSBpcyBjb250YWluZWQgYnkgb25seSBvbmUgY291bnRyeSBmb3IgcGVyZm9ybWFuY2UgcmVhc29ucy4gRm9yIGV4YW1wbGUsCiAgICAvLyBmb3IgTkFOUEEgY291bnRyaWVzIGl0IHdpbGwgYmUgY29udGFpbmVkIGluIHRoZSBtZXRhZGF0YSBmb3IgVVMuCiAgICBTdHJpbmcgcmVnaW9uQ29kZSA9IGdldFJlZ2lvbkNvZGVGb3JDb3VudHJ5Q29kZShjb3VudHJ5Q29kZSk7CiAgICBpZiAoIWlzVmFsaWRSZWdpb25Db2RlKHJlZ2lvbkNvZGUpKSB7CiAgICAgIGZvcm1hdHRlZE51bWJlci5hcHBlbmQobmF0aW9uYWxTaWduaWZpY2FudE51bWJlcik7CiAgICAgIHJldHVybjsKICAgIH0KCiAgICBmb3JtYXR0ZWROdW1iZXIuYXBwZW5kKGZvcm1hdE5hdGlvbmFsTnVtYmVyKG5hdGlvbmFsU2lnbmlmaWNhbnROdW1iZXIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlZ2lvbkNvZGUsIG51bWJlckZvcm1hdCkpOwogICAgbWF5YmVHZXRGb3JtYXR0ZWRFeHRlbnNpb24obnVtYmVyLCByZWdpb25Db2RlLCBmb3JtYXR0ZWROdW1iZXIpOwogICAgZm9ybWF0TnVtYmVyQnlGb3JtYXQoY291bnRyeUNvZGUsIG51bWJlckZvcm1hdCwgZm9ybWF0dGVkTnVtYmVyKTsKICB9CgogIC8qKgogICAqIEZvcm1hdHMgYSBwaG9uZSBudW1iZXIgaW4gdGhlIHNwZWNpZmllZCBmb3JtYXQgdXNpbmcgY2xpZW50LWRlZmluZWQgZm9ybWF0dGluZyBydWxlcy4gTm90ZSB0aGF0CiAgICogaWYgdGhlIHBob25lIG51bWJlciBoYXMgYSBjb3VudHJ5IGNvZGUgb2YgemVybyBvciBhbiBvdGhlcndpc2UgaW52YWxpZCBjb3VudHJ5IGNvZGUsIHdlIGNhbm5vdAogICAqIHdvcmsgb3V0IHRoaW5ncyBsaWtlIHdoZXRoZXIgdGhlcmUgc2hvdWxkIGJlIGEgbmF0aW9uYWwgcHJlZml4IGFwcGxpZWQsIG9yIGhvdyB0byBmb3JtYXQKICAgKiBleHRlbnNpb25zLCBzbyB3ZSByZXR1cm4gdGhlIG5hdGlvbmFsIHNpZ25pZmljYW50IG51bWJlciB3aXRoIG5vIGZvcm1hdHRpbmcgYXBwbGllZC4KICAgKgogICAqIEBwYXJhbSBudW1iZXIgICAgICAgICAgICAgICAgICAgICAgICB0aGUgcGhvbmUgbnVtYmVyIHRvIGJlIGZvcm1hdHRlZAogICAqIEBwYXJhbSBudW1iZXJGb3JtYXQgICAgICAgICAgICAgICAgICB0aGUgZm9ybWF0IHRoZSBwaG9uZSBudW1iZXIgc2hvdWxkIGJlIGZvcm1hdHRlZCBpbnRvCiAgICogQHBhcmFtIHVzZXJEZWZpbmVkRm9ybWF0cyAgICAgICAgICAgIGZvcm1hdHRpbmcgcnVsZXMgc3BlY2lmaWVkIGJ5IGNsaWVudHMKICAgKiBAcmV0dXJuICB0aGUgZm9ybWF0dGVkIHBob25lIG51bWJlcgogICAqLwogIHB1YmxpYyBTdHJpbmcgZm9ybWF0QnlQYXR0ZXJuKFBob25lTnVtYmVyIG51bWJlciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBQaG9uZU51bWJlckZvcm1hdCBudW1iZXJGb3JtYXQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTGlzdDxOdW1iZXJGb3JtYXQ+IHVzZXJEZWZpbmVkRm9ybWF0cykgewogICAgaW50IGNvdW50cnlDb2RlID0gbnVtYmVyLmdldENvdW50cnlDb2RlKCk7CiAgICBTdHJpbmcgbmF0aW9uYWxTaWduaWZpY2FudE51bWJlciA9IGdldE5hdGlvbmFsU2lnbmlmaWNhbnROdW1iZXIobnVtYmVyKTsKICAgIC8vIE5vdGUgZ2V0UmVnaW9uQ29kZUZvckNvdW50cnlDb2RlKCkgaXMgdXNlZCBiZWNhdXNlIGZvcm1hdHRpbmcgaW5mb3JtYXRpb24gZm9yIGNvdW50cmllcyB3aGljaAogICAgLy8gc2hhcmUgYSBjb3VudHJ5IGNvZGUgaXMgY29udGFpbmVkIGJ5IG9ubHkgb25lIGNvdW50cnkgZm9yIHBlcmZvcm1hbmNlIHJlYXNvbnMuIEZvciBleGFtcGxlLAogICAgLy8gZm9yIE5BTlBBIGNvdW50cmllcyBpdCB3aWxsIGJlIGNvbnRhaW5lZCBpbiB0aGUgbWV0YWRhdGEgZm9yIFVTLgogICAgU3RyaW5nIHJlZ2lvbkNvZGUgPSBnZXRSZWdpb25Db2RlRm9yQ291bnRyeUNvZGUoY291bnRyeUNvZGUpOwogICAgaWYgKCFpc1ZhbGlkUmVnaW9uQ29kZShyZWdpb25Db2RlKSkgewogICAgICByZXR1cm4gbmF0aW9uYWxTaWduaWZpY2FudE51bWJlcjsKICAgIH0KICAgIGludCBzaXplID0gdXNlckRlZmluZWRGb3JtYXRzLnNpemUoKTsKICAgIGZvciAoaW50IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKSB7CiAgICAgIE51bWJlckZvcm1hdCBudW1Gb3JtYXQgPSB1c2VyRGVmaW5lZEZvcm1hdHMuZ2V0KGkpOwogICAgICBTdHJpbmcgbmF0aW9uYWxQcmVmaXhGb3JtYXR0aW5nUnVsZSA9IG51bUZvcm1hdC5nZXROYXRpb25hbFByZWZpeEZvcm1hdHRpbmdSdWxlKCk7CiAgICAgIGlmIChuYXRpb25hbFByZWZpeEZvcm1hdHRpbmdSdWxlLmxlbmd0aCgpID4gMCkgewogICAgICAgIFN0cmluZyBuYXRpb25hbFByZWZpeCA9IGdldE1ldGFkYXRhRm9yUmVnaW9uKHJlZ2lvbkNvZGUpLmdldE5hdGlvbmFsUHJlZml4KCk7CiAgICAgICAgLy8gUmVwbGFjZSAkTlAgd2l0aCBuYXRpb25hbCBwcmVmaXggYW5kICRGRyB3aXRoIHRoZSBmaXJzdCBncm91cCAoJDEpLgogICAgICAgIG5hdGlvbmFsUHJlZml4Rm9ybWF0dGluZ1J1bGUgPQogICAgICAgICAgICBOUF9QQVRURVJOLm1hdGNoZXIobmF0aW9uYWxQcmVmaXhGb3JtYXR0aW5nUnVsZSkucmVwbGFjZUZpcnN0KG5hdGlvbmFsUHJlZml4KTsKICAgICAgICBuYXRpb25hbFByZWZpeEZvcm1hdHRpbmdSdWxlID0KICAgICAgICAgICAgRkdfUEFUVEVSTi5tYXRjaGVyKG5hdGlvbmFsUHJlZml4Rm9ybWF0dGluZ1J1bGUpLnJlcGxhY2VGaXJzdCgiXFwkMSIpOwogICAgICAgIG51bUZvcm1hdC5zZXROYXRpb25hbFByZWZpeEZvcm1hdHRpbmdSdWxlKG5hdGlvbmFsUHJlZml4Rm9ybWF0dGluZ1J1bGUpOwogICAgICB9CiAgICB9CgogICAgU3RyaW5nQnVmZmVyIGZvcm1hdHRlZE51bWJlciA9CiAgICAgICAgbmV3IFN0cmluZ0J1ZmZlcihmb3JtYXRBY2NvcmRpbmdUb0Zvcm1hdHMobmF0aW9uYWxTaWduaWZpY2FudE51bWJlciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1c2VyRGVmaW5lZEZvcm1hdHMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbnVtYmVyRm9ybWF0KSk7CiAgICBtYXliZUdldEZvcm1hdHRlZEV4dGVuc2lvbihudW1iZXIsIHJlZ2lvbkNvZGUsIGZvcm1hdHRlZE51bWJlcik7CiAgICBmb3JtYXROdW1iZXJCeUZvcm1hdChjb3VudHJ5Q29kZSwgbnVtYmVyRm9ybWF0LCBmb3JtYXR0ZWROdW1iZXIpOwogICAgcmV0dXJuIGZvcm1hdHRlZE51bWJlci50b1N0cmluZygpOwogIH0KCiAgcHVibGljIFN0cmluZyBmb3JtYXROYXRpb25hbE51bWJlcldpdGhDYXJyaWVyQ29kZShQaG9uZU51bWJlciBudW1iZXIsIFN0cmluZyBjYXJyaWVyQ29kZSkgewogICAgaW50IGNvdW50cnlDb2RlID0gbnVtYmVyLmdldENvdW50cnlDb2RlKCk7CiAgICBTdHJpbmcgbmF0aW9uYWxTaWduaWZpY2FudE51bWJlciA9IGdldE5hdGlvbmFsU2lnbmlmaWNhbnROdW1iZXIobnVtYmVyKTsKICAgIC8vIE5vdGUgZ2V0UmVnaW9uQ29kZUZvckNvdW50cnlDb2RlKCkgaXMgdXNlZCBiZWNhdXNlIGZvcm1hdHRpbmcgaW5mb3JtYXRpb24gZm9yIGNvdW50cmllcyB3aGljaAogICAgLy8gc2hhcmUgYSBjb3VudHJ5IGNvZGUgaXMgY29udGFpbmVkIGJ5IG9ubHkgb25lIGNvdW50cnkgZm9yIHBlcmZvcm1hbmNlIHJlYXNvbnMuIEZvciBleGFtcGxlLAogICAgLy8gZm9yIE5BTlBBIGNvdW50cmllcyBpdCB3aWxsIGJlIGNvbnRhaW5lZCBpbiB0aGUgbWV0YWRhdGEgZm9yIFVTLgogICAgU3RyaW5nIHJlZ2lvbkNvZGUgPSBnZXRSZWdpb25Db2RlRm9yQ291bnRyeUNvZGUoY291bnRyeUNvZGUpOwogICAgaWYgKCFpc1ZhbGlkUmVnaW9uQ29kZShyZWdpb25Db2RlKSkgewogICAgICByZXR1cm4gbmF0aW9uYWxTaWduaWZpY2FudE51bWJlcjsKICAgIH0KCiAgICBTdHJpbmdCdWZmZXIgZm9ybWF0dGVkTnVtYmVyID0gbmV3IFN0cmluZ0J1ZmZlcigyMCk7CiAgICBmb3JtYXR0ZWROdW1iZXIuYXBwZW5kKGZvcm1hdE5hdGlvbmFsTnVtYmVyKG5hdGlvbmFsU2lnbmlmaWNhbnROdW1iZXIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlZ2lvbkNvZGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFBob25lTnVtYmVyRm9ybWF0Lk5BVElPTkFMLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXJyaWVyQ29kZSkpOwogICAgbWF5YmVHZXRGb3JtYXR0ZWRFeHRlbnNpb24obnVtYmVyLCByZWdpb25Db2RlLCBmb3JtYXR0ZWROdW1iZXIpOwogICAgZm9ybWF0TnVtYmVyQnlGb3JtYXQoY291bnRyeUNvZGUsIFBob25lTnVtYmVyRm9ybWF0Lk5BVElPTkFMLCBmb3JtYXR0ZWROdW1iZXIpOwogICAgcmV0dXJuIGZvcm1hdHRlZE51bWJlci50b1N0cmluZygpOwogIH0KCiAgLyoqCiAgICogRm9ybWF0cyBhIHBob25lIG51bWJlciBmb3Igb3V0LW9mLWNvdW50cnkgZGlhbGluZyBwdXJwb3NlLiBJZiBubyBjb3VudHJ5Q2FsbGluZ0Zyb20KICAgKiBpcyBzdXBwbGllZCwgd2UgZm9ybWF0IHRoZSBudW1iZXIgaW4gaXRzIElOVEVSTkFUSU9OQUwgZm9ybWF0LiBJZiB0aGUgY291bnRyeUNhbGxpbmdGcm9tIGlzCiAgICogdGhlIHNhbWUgYXMgdGhlIGNvdW50cnkgd2hlcmUgdGhlIG51bWJlciBpcyBmcm9tLCB0aGVuIE5BVElPTkFMIGZvcm1hdHRpbmcgd2lsbCBiZSBhcHBsaWVkLgogICAqCiAgICogSWYgdGhlIG51bWJlciBpdHNlbGYgaGFzIGEgY291bnRyeSBjb2RlIG9mIHplcm8gb3IgYW4gb3RoZXJ3aXNlIGludmFsaWQgY291bnRyeSBjb2RlLCB0aGVuIHdlCiAgICogcmV0dXJuIHRoZSBudW1iZXIgd2l0aCBubyBmb3JtYXR0aW5nIGFwcGxpZWQuCiAgICoKICAgKiBOb3RlIHRoaXMgZnVuY3Rpb24gdGFrZXMgY2FyZSBvZiB0aGUgY2FzZSBmb3IgY2FsbGluZyBpbnNpZGUgb2YgTkFOUEEgYW5kIGJldHdlZW4gUnVzc2lhIGFuZAogICAqIEthemFraHN0YW4gKHdobyBzaGFyZSB0aGUgc2FtZSBjb3VudHJ5IGNvZGUpLiBJbiB0aG9zZSBjYXNlcywgbm8gaW50ZXJuYXRpb25hbCBwcmVmaXggaXMgdXNlZC4KICAgKiBGb3IgY291bnRyaWVzIHdoaWNoIGhhdmUgbXVsdGlwbGUgaW50ZXJuYXRpb25hbCBwcmVmaXhlcywgdGhlIG51bWJlciBpbiBpdHMgSU5URVJOQVRJT05BTAogICAqIGZvcm1hdCB3aWxsIGJlIHJldHVybmVkIGluc3RlYWQuCiAgICoKICAgKiBAcGFyYW0gbnVtYmVyICAgICAgICAgICAgICAgdGhlIHBob25lIG51bWJlciB0byBiZSBmb3JtYXR0ZWQKICAgKiBAcGFyYW0gY291bnRyeUNhbGxpbmdGcm9tICAgdGhlIElTTyAzMTY2LTEgdHdvLWxldHRlciBjb3VudHJ5IGNvZGUgdGhhdCBkZW5vdGVzIHRoZSBmb3JlaWduCiAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50cnkgd2hlcmUgdGhlIGNhbGwgaXMgYmVpbmcgcGxhY2VkCiAgICogQHJldHVybiAgdGhlIGZvcm1hdHRlZCBwaG9uZSBudW1iZXIKICAgKi8KICBwdWJsaWMgU3RyaW5nIGZvcm1hdE91dE9mQ291bnRyeUNhbGxpbmdOdW1iZXIoUGhvbmVOdW1iZXIgbnVtYmVyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTdHJpbmcgY291bnRyeUNhbGxpbmdGcm9tKSB7CiAgICBpZiAoIWlzVmFsaWRSZWdpb25Db2RlKGNvdW50cnlDYWxsaW5nRnJvbSkpIHsKICAgICAgcmV0dXJuIGZvcm1hdChudW1iZXIsIFBob25lTnVtYmVyRm9ybWF0LklOVEVSTkFUSU9OQUwpOwogICAgfQogICAgaW50IGNvdW50cnlDb2RlID0gbnVtYmVyLmdldENvdW50cnlDb2RlKCk7CiAgICBTdHJpbmcgcmVnaW9uQ29kZSA9IGdldFJlZ2lvbkNvZGVGb3JDb3VudHJ5Q29kZShjb3VudHJ5Q29kZSk7CiAgICBTdHJpbmcgbmF0aW9uYWxTaWduaWZpY2FudE51bWJlciA9IGdldE5hdGlvbmFsU2lnbmlmaWNhbnROdW1iZXIobnVtYmVyKTsKICAgIGlmICghaXNWYWxpZFJlZ2lvbkNvZGUocmVnaW9uQ29kZSkpIHsKICAgICAgcmV0dXJuIG5hdGlvbmFsU2lnbmlmaWNhbnROdW1iZXI7CiAgICB9CiAgICBpZiAoY291bnRyeUNvZGUgPT0gTkFOUEFfQ09VTlRSWV9DT0RFKSB7CiAgICAgIGlmIChpc05BTlBBQ291bnRyeShjb3VudHJ5Q2FsbGluZ0Zyb20pKSB7CiAgICAgICAgLy8gRm9yIE5BTlBBIGNvdW50cmllcywgcmV0dXJuIHRoZSBuYXRpb25hbCBmb3JtYXQgZm9yIHRoZXNlIGNvdW50cmllcyBidXQgcHJlZml4IGl0IHdpdGgKICAgICAgICAvLyB0aGUgY291bnRyeSBjb2RlLgogICAgICAgIHJldHVybiBjb3VudHJ5Q29kZSArICIgIiArIGZvcm1hdChudW1iZXIsIFBob25lTnVtYmVyRm9ybWF0Lk5BVElPTkFMKTsKICAgICAgfQogICAgfSBlbHNlIGlmIChjb3VudHJ5Q29kZSA9PSBnZXRDb3VudHJ5Q29kZUZvclJlZ2lvbihjb3VudHJ5Q2FsbGluZ0Zyb20pKSB7CiAgICAvLyBGb3IgY291bnRyaWVzIHRoYXQgc2hhcmUgYSBjb3VudHJ5IGNhbGxpbmcgY29kZSwgdGhlIGNvdW50cnkgY29kZSBuZWVkIG5vdCBiZSBkaWFsbGVkLiBUaGlzCiAgICAvLyBhbHNvIGFwcGxpZXMgd2hlbiBkaWFsbGluZyB3aXRoaW4gYSBjb3VudHJ5LCBzbyB0aGlzIGlmIGNsYXVzZSBjb3ZlcnMgYm90aCB0aGVzZSBjYXNlcy4KICAgIC8vIFRlY2huaWNhbGx5IHRoaXMgaXMgdGhlIGNhc2UgZm9yIGRpYWxsaW5nIGZyb20gbGEgUo51bmlvbiB0byBvdGhlciBvdmVyc2VhcyBkZXBhcnRtZW50cyBvZgogICAgLy8gRnJhbmNlIChGcmVuY2ggR3VpYW5hLCBNYXJ0aW5pcXVlLCBHdWFkZWxvdXBlKSwgYnV0IG5vdCB2aWNlIHZlcnNhIC0gc28gd2UgZG9uJ3QgY292ZXIgdGhpcwogICAgLy8gZWRnZSBjYXNlIGZvciBub3cgYW5kIGZvciB0aG9zZSBjYXNlcyByZXR1cm4gdGhlIHZlcnNpb24gaW5jbHVkaW5nIGNvdW50cnkgY29kZS4KICAgIC8vIERldGFpbHMgaGVyZTogaHR0cDovL3d3dy5wZXRpdGZ1dGUuY29tL3ZveWFnZS8yMjUtaW5mby1wcmF0aXF1ZXMtcmV1bmlvbgogICAgICByZXR1cm4gZm9ybWF0KG51bWJlciwgUGhvbmVOdW1iZXJGb3JtYXQuTkFUSU9OQUwpOwogICAgfQogICAgU3RyaW5nIGZvcm1hdHRlZE5hdGlvbmFsTnVtYmVyID0KICAgICAgICBmb3JtYXROYXRpb25hbE51bWJlcihuYXRpb25hbFNpZ25pZmljYW50TnVtYmVyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlZ2lvbkNvZGUsIFBob25lTnVtYmVyRm9ybWF0LklOVEVSTkFUSU9OQUwpOwogICAgUGhvbmVNZXRhZGF0YSBtZXRhZGF0YSA9IGdldE1ldGFkYXRhRm9yUmVnaW9uKGNvdW50cnlDYWxsaW5nRnJvbSk7CiAgICBTdHJpbmcgaW50ZXJuYXRpb25hbFByZWZpeCA9IG1ldGFkYXRhLmdldEludGVybmF0aW9uYWxQcmVmaXgoKTsKCiAgICAvLyBGb3IgY291bnRyaWVzIHRoYXQgaGF2ZSBtdWx0aXBsZSBpbnRlcm5hdGlvbmFsIHByZWZpeGVzLCB0aGUgaW50ZXJuYXRpb25hbCBmb3JtYXQgb2YgdGhlCiAgICAvLyBudW1iZXIgaXMgcmV0dXJuZWQsIHVubGVzcyB0aGVyZSBpcyBhIHByZWZlcnJlZCBpbnRlcm5hdGlvbmFsIHByZWZpeC4KICAgIFN0cmluZyBpbnRlcm5hdGlvbmFsUHJlZml4Rm9yRm9ybWF0dGluZyA9ICIiOwogICAgaWYgKFVOSVFVRV9JTlRFUk5BVElPTkFMX1BSRUZJWC5tYXRjaGVyKGludGVybmF0aW9uYWxQcmVmaXgpLm1hdGNoZXMoKSkgewogICAgICBpbnRlcm5hdGlvbmFsUHJlZml4Rm9yRm9ybWF0dGluZyA9IGludGVybmF0aW9uYWxQcmVmaXg7CiAgICB9IGVsc2UgaWYgKG1ldGFkYXRhLmhhc1ByZWZlcnJlZEludGVybmF0aW9uYWxQcmVmaXgoKSkgewogICAgICBpbnRlcm5hdGlvbmFsUHJlZml4Rm9yRm9ybWF0dGluZyA9IG1ldGFkYXRhLmdldFByZWZlcnJlZEludGVybmF0aW9uYWxQcmVmaXgoKTsKICAgIH0KCiAgICBTdHJpbmdCdWZmZXIgZm9ybWF0dGVkTnVtYmVyID0gbmV3IFN0cmluZ0J1ZmZlcihmb3JtYXR0ZWROYXRpb25hbE51bWJlcik7CiAgICBtYXliZUdldEZvcm1hdHRlZEV4dGVuc2lvbihudW1iZXIsIHJlZ2lvbkNvZGUsIGZvcm1hdHRlZE51bWJlcik7CiAgICBpZiAoaW50ZXJuYXRpb25hbFByZWZpeEZvckZvcm1hdHRpbmcubGVuZ3RoKCkgPiAwKSB7CiAgICAgIGZvcm1hdHRlZE51bWJlci5pbnNlcnQoMCwgIiAiKS5pbnNlcnQoMCwgY291bnRyeUNvZGUpLmluc2VydCgwLCAiICIpCiAgICAgICAgICAuaW5zZXJ0KDAsIGludGVybmF0aW9uYWxQcmVmaXhGb3JGb3JtYXR0aW5nKTsKICAgIH0gZWxzZSB7CiAgICAgIGZvcm1hdE51bWJlckJ5Rm9ybWF0KGNvdW50cnlDb2RlLAogICAgICAgICAgICAgICAgICAgICAgICAgICBQaG9uZU51bWJlckZvcm1hdC5JTlRFUk5BVElPTkFMLAogICAgICAgICAgICAgICAgICAgICAgICAgICBmb3JtYXR0ZWROdW1iZXIpOwogICAgfQogICAgcmV0dXJuIGZvcm1hdHRlZE51bWJlci50b1N0cmluZygpOwogIH0KCiAgLyoqCiAgICogRm9ybWF0cyBhIHBob25lIG51bWJlciB1c2luZyB0aGUgb3JpZ2luYWwgcGhvbmUgbnVtYmVyIGZvcm1hdCB0aGF0IHRoZSBudW1iZXIgaXMgcGFyc2VkIGZyb20uCiAgICogVGhlIG9yaWdpbmFsIGZvcm1hdCBpcyBlbWJlZGRlZCBpbiB0aGUgY291bnRyeV9jb2RlX3NvdXJjZSBmaWVsZCBvZiB0aGUgUGhvbmVOdW1iZXIgb2JqZWN0CiAgICogcGFzc2VkIGluLiBJZiBzdWNoIGluZm9ybWF0aW9uIGlzIG1pc3NpbmcsIHRoZSBudW1iZXIgd2lsbCBiZSBmb3JtYXR0ZWQgaW50byB0aGUgTkFUSU9OQUwKICAgKiBmb3JtYXQgYnkgZGVmYXVsdC4KICAgKgogICAqIEBwYXJhbSBudW1iZXIgIHRoZSBQaG9uZU51bWJlciB0aGF0IG5lZWRzIHRvIGJlIGZvcm1hdHRlZCBpbiBpdHMgb3JpZ2luYWwgbnVtYmVyIGZvcm1hdAogICAqIEBwYXJhbSBjb3VudHJ5Q2FsbGluZ0Zyb20gIHRoZSBjb3VudHJ5IHdob3NlIElERCBuZWVkcyB0byBiZSBwcmVmaXhlZCBpZiB0aGUgb3JpZ2luYWwgbnVtYmVyCiAgICogICAgIGhhcyBvbmUKICAgKiBAcmV0dXJuICB0aGUgZm9ybWF0dGVkIHBob25lIG51bWJlciBpbiBpdHMgb3JpZ2luYWwgbnVtYmVyIGZvcm1hdAogICAqLwogIHB1YmxpYyBTdHJpbmcgZm9ybWF0SW5PcmlnaW5hbEZvcm1hdChQaG9uZU51bWJlciBudW1iZXIsIFN0cmluZyBjb3VudHJ5Q2FsbGluZ0Zyb20pIHsKICAgIGlmICghbnVtYmVyLmhhc0NvdW50cnlDb2RlU291cmNlKCkpIHsKICAgICAgcmV0dXJuIGZvcm1hdChudW1iZXIsIFBob25lTnVtYmVyRm9ybWF0Lk5BVElPTkFMKTsKICAgIH0KICAgIHN3aXRjaCAobnVtYmVyLmdldENvdW50cnlDb2RlU291cmNlKCkpIHsKICAgICAgY2FzZSBGUk9NX05VTUJFUl9XSVRIX1BMVVNfU0lHTjoKICAgICAgICByZXR1cm4gZm9ybWF0KG51bWJlciwgUGhvbmVOdW1iZXJGb3JtYXQuSU5URVJOQVRJT05BTCk7CiAgICAgIGNhc2UgRlJPTV9OVU1CRVJfV0lUSF9JREQ6CiAgICAgICAgcmV0dXJuIGZvcm1hdE91dE9mQ291bnRyeUNhbGxpbmdOdW1iZXIobnVtYmVyLCBjb3VudHJ5Q2FsbGluZ0Zyb20pOwogICAgICBjYXNlIEZST01fTlVNQkVSX1dJVEhPVVRfUExVU19TSUdOOgogICAgICAgIHJldHVybiBmb3JtYXQobnVtYmVyLCBQaG9uZU51bWJlckZvcm1hdC5JTlRFUk5BVElPTkFMKS5zdWJzdHJpbmcoMSk7CiAgICAgIGNhc2UgRlJPTV9ERUZBVUxUX0NPVU5UUlk6CiAgICAgIGRlZmF1bHQ6CiAgICAgICAgcmV0dXJuIGZvcm1hdChudW1iZXIsIFBob25lTnVtYmVyRm9ybWF0Lk5BVElPTkFMKTsgICAgICAKICAgIH0KICB9CgogIAogIC8qKgogICAqIEdldHMgdGhlIG5hdGlvbmFsIHNpZ25pZmljYW50IG51bWJlciBvZiB0aGUgYSBwaG9uZSBudW1iZXIuIE5vdGUgYSBuYXRpb25hbCBzaWduaWZpY2FudCBudW1iZXIKICAgKiBkb2Vzbid0IGNvbnRhaW4gYSBuYXRpb25hbCBwcmVmaXggb3IgYW55IGZvcm1hdHRpbmcuCiAgICoKICAgKiBAcGFyYW0gbnVtYmVyICB0aGUgUGhvbmVOdW1iZXIgb2JqZWN0IGZvciB3aGljaCB0aGUgbmF0aW9uYWwgc2lnbmlmaWNhbnQgbnVtYmVyIGlzIG5lZWRlZAogICAqIEByZXR1cm4gIHRoZSBuYXRpb25hbCBzaWduaWZpY2FudCBudW1iZXIgb2YgdGhlIFBob25lTnVtYmVyIG9iamVjdCBwYXNzZWQgaW4KICAgKi8KICBwdWJsaWMgc3RhdGljIFN0cmluZyBnZXROYXRpb25hbFNpZ25pZmljYW50TnVtYmVyKFBob25lTnVtYmVyIG51bWJlcikgewogICAgLy8gVGhlIGxlYWRpbmcgemVybyBpbiB0aGUgbmF0aW9uYWwgKHNpZ25pZmljYW50KSBudW1iZXIgb2YgYW4gSXRhbGlhbiBwaG9uZSBudW1iZXIgaGFzIGEKICAgIC8vIHNwZWNpYWwgbWVhbmluZy4gVW5saWtlIHRoZSByZXN0IG9mIHRoZSB3b3JsZCwgaXQgaW5kaWNhdGVzIHRoZSBudW1iZXIgaXMgYSBsYW5kbGluZQogICAgLy8gbnVtYmVyLiBUaGVyZSBoYXZlIGJlZW4gcGxhbnMgdG8gbWlncmF0ZSBsYW5kbGluZSBudW1iZXJzIHRvIHN0YXJ0IHdpdGggdGhlIGRpZ2l0IHR3byBzaW5jZQogICAgLy8gRGVjZW1iZXIgMjAwMCwgYnV0IGl0IGhhcyBub3QgeWV0IGhhcHBlbmVkLgogICAgLy8gU2VlIGh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvJTJCMzkgZm9yIG1vcmUgZGV0YWlscy4KICAgIC8vIE90aGVyIGNvdW50cmllcyBzdWNoIGFzIENvdGUgZCdJdm9pcmUgYW5kIEdhYm9uIHVzZSB0aGlzIGZvciB0aGVpciBtb2JpbGUgbnVtYmVycy4KICAgIFN0cmluZ0J1ZmZlciBuYXRpb25hbE51bWJlciA9IG5ldyBTdHJpbmdCdWZmZXIoCiAgICAgICAgKG51bWJlci5oYXNJdGFsaWFuTGVhZGluZ1plcm8oKSAmJiBudW1iZXIuZ2V0SXRhbGlhbkxlYWRpbmdaZXJvKCkgJiYKICAgICAgICAgaXNMZWFkaW5nWmVyb0NvdW50cnkobnVtYmVyLmdldENvdW50cnlDb2RlKCkpKQogICAgICAgID8gIjAiIDogIiIKICAgICk7CiAgICBuYXRpb25hbE51bWJlci5hcHBlbmQobnVtYmVyLmdldE5hdGlvbmFsTnVtYmVyKCkpOwogICAgcmV0dXJuIG5hdGlvbmFsTnVtYmVyLnRvU3RyaW5nKCk7CiAgfQoKICAvKioKICAgKiBBIGhlbHBlciBmdW5jdGlvbiB0aGF0IGlzIHVzZWQgYnkgZm9ybWF0IGFuZCBmb3JtYXRCeVBhdHRlcm4uCiAgICovCiAgcHJpdmF0ZSB2b2lkIGZvcm1hdE51bWJlckJ5Rm9ybWF0KGludCBjb3VudHJ5Q29kZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUGhvbmVOdW1iZXJGb3JtYXQgbnVtYmVyRm9ybWF0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTdHJpbmdCdWZmZXIgZm9ybWF0dGVkTnVtYmVyKSB7CiAgICBzd2l0Y2ggKG51bWJlckZvcm1hdCkgewogICAgICBjYXNlIEUxNjQ6CiAgICAgICAgZm9ybWF0dGVkTnVtYmVyLmluc2VydCgwLCBjb3VudHJ5Q29kZSkuaW5zZXJ0KDAsIFBMVVNfU0lHTik7CiAgICAgICAgcmV0dXJuOwogICAgICBjYXNlIElOVEVSTkFUSU9OQUw6CiAgICAgICAgZm9ybWF0dGVkTnVtYmVyLmluc2VydCgwLCAiICIpLmluc2VydCgwLCBjb3VudHJ5Q29kZSkuaW5zZXJ0KDAsIFBMVVNfU0lHTik7CiAgICAgICAgcmV0dXJuOwogICAgICBjYXNlIE5BVElPTkFMOgogICAgICBkZWZhdWx0OgogICAgICAgIHJldHVybjsKICAgIH0KICB9CgogIC8vIFNpbXBsZSB3cmFwcGVyIG9mIGZvcm1hdE5hdGlvbmFsTnVtYmVyIGZvciB0aGUgY29tbW9uIGNhc2Ugb2Ygbm8gY2FycmllciBjb2RlLgogIHByaXZhdGUgU3RyaW5nIGZvcm1hdE5hdGlvbmFsTnVtYmVyKFN0cmluZyBudW1iZXIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgU3RyaW5nIHJlZ2lvbkNvZGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUGhvbmVOdW1iZXJGb3JtYXQgbnVtYmVyRm9ybWF0KSB7CiAgICByZXR1cm4gZm9ybWF0TmF0aW9uYWxOdW1iZXIobnVtYmVyLCByZWdpb25Db2RlLCBudW1iZXJGb3JtYXQsIG51bGwpOwogIH0gIAoKICAvLyBOb3RlIGluIHNvbWUgY291bnRyaWVzLCB0aGUgbmF0aW9uYWwgbnVtYmVyIGNhbiBiZSB3cml0dGVuIGluIHR3byBjb21wbGV0ZWx5IGRpZmZlcmVudCB3YXlzCiAgLy8gZGVwZW5kaW5nIG9uIHdoZXRoZXIgaXQgZm9ybXMgcGFydCBvZiB0aGUgTkFUSU9OQUwgZm9ybWF0IG9yIElOVEVSTkFUSU9OQUwgZm9ybWF0LiBUaGUKICAvLyBudW1iZXJGb3JtYXQgcGFyYW1ldGVyIGhlcmUgaXMgdXNlZCB0byBzcGVjaWZ5IHdoaWNoIGZvcm1hdCB0byB1c2UgZm9yIHRob3NlIGNhc2VzLiBJZiBhCiAgLy8gY2FycmllckNvZGUgaXMgc3BlY2lmaWVkLCB0aGlzIHdpbGwgYmUgaW5zZXJ0ZWQgaW50byB0aGUgZm9ybWF0dGVkIHN0cmluZyB0byByZXBsYWNlICRDQy4KICBwcml2YXRlIFN0cmluZyBmb3JtYXROYXRpb25hbE51bWJlcihTdHJpbmcgbnVtYmVyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFN0cmluZyByZWdpb25Db2RlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFBob25lTnVtYmVyRm9ybWF0IG51bWJlckZvcm1hdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTdHJpbmcgY2FycmllckNvZGUpIHsKICAgIFBob25lTWV0YWRhdGEgbWV0YWRhdGEgPSBnZXRNZXRhZGF0YUZvclJlZ2lvbihyZWdpb25Db2RlKTsKICAgIExpc3Q8TnVtYmVyRm9ybWF0PiBpbnRsTnVtYmVyRm9ybWF0cyA9IG1ldGFkYXRhLmdldEludGxOdW1iZXJGb3JtYXRMaXN0KCk7CiAgICAvLyBXaGVuIHRoZSBpbnRsTnVtYmVyRm9ybWF0cyBleGlzdHMsIHdlIHVzZSB0aGF0IHRvIGZvcm1hdCBuYXRpb25hbCBudW1iZXIgZm9yIHRoZQogICAgLy8gSU5URVJOQVRJT05BTCBmb3JtYXQgaW5zdGVhZCBvZiB1c2luZyB0aGUgbnVtYmVyRGVzYy5udW1iZXJGb3JtYXRzLgogICAgTGlzdDxOdW1iZXJGb3JtYXQ+IGF2YWlsYWJsZUZvcm1hdHMgPQogICAgICAgIChpbnRsTnVtYmVyRm9ybWF0cy5zaXplKCkgPT0gMCB8fCBudW1iZXJGb3JtYXQgPT0gUGhvbmVOdW1iZXJGb3JtYXQuTkFUSU9OQUwpCiAgICAgICAgPyBtZXRhZGF0YS5nZXROdW1iZXJGb3JtYXRMaXN0KCkKICAgICAgICA6IG1ldGFkYXRhLmdldEludGxOdW1iZXJGb3JtYXRMaXN0KCk7CiAgICByZXR1cm4gZm9ybWF0QWNjb3JkaW5nVG9Gb3JtYXRzKG51bWJlciwgYXZhaWxhYmxlRm9ybWF0cywgbnVtYmVyRm9ybWF0LCBjYXJyaWVyQ29kZSk7CiAgfQoKICAvLyBTaW1wbGUgd3JhcHBlciBvZiBmb3JtYXRBY2NvcmRpbmdUb0Zvcm1hdHMgZm9yIHRoZSBjb21tb24gY2FzZSBvZiBubyBjYXJyaWVyIGNvZGUuCiAgcHJpdmF0ZSBTdHJpbmcgZm9ybWF0QWNjb3JkaW5nVG9Gb3JtYXRzKFN0cmluZyBuYXRpb25hbE51bWJlciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTGlzdDxOdW1iZXJGb3JtYXQ+IGF2YWlsYWJsZUZvcm1hdHMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFBob25lTnVtYmVyRm9ybWF0IG51bWJlckZvcm1hdCkgewogICAgcmV0dXJuIGZvcm1hdEFjY29yZGluZ1RvRm9ybWF0cyhuYXRpb25hbE51bWJlciwgYXZhaWxhYmxlRm9ybWF0cywgbnVtYmVyRm9ybWF0LCBudWxsKTsKICB9CgogIC8vIE5vdGUgdGhhdCBjYXJyaWVyQ29kZSBpcyBvcHRpb25hbCAtIGlmIE5VTEwgb3IgYW4gZW1wdHkgc3RyaW5nLCBubyBjYXJyaWVyIGNvZGUgcmVwbGFjZW1lbnQKICAvLyB3aWxsIHRha2UgcGxhY2UuIENhcnJpZXIgY29kZSByZXBsYWNlbWVudCBvY2N1cnMgYmVmb3JlIG5hdGlvbmFsIHByZWZpeCByZXBsYWNlbWVudC4KICBwcml2YXRlIFN0cmluZyBmb3JtYXRBY2NvcmRpbmdUb0Zvcm1hdHMoU3RyaW5nIG5hdGlvbmFsTnVtYmVyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBMaXN0PE51bWJlckZvcm1hdD4gYXZhaWxhYmxlRm9ybWF0cywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUGhvbmVOdW1iZXJGb3JtYXQgbnVtYmVyRm9ybWF0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTdHJpbmcgY2FycmllckNvZGUpIHsKICAgIGZvciAoTnVtYmVyRm9ybWF0IG51bUZvcm1hdCA6IGF2YWlsYWJsZUZvcm1hdHMpIHsKICAgICAgaWYgKCFudW1Gb3JtYXQuaGFzTGVhZGluZ0RpZ2l0cygpIHx8CiAgICAgICAgICByZWdleENhY2hlLmdldFBhdHRlcm5Gb3JSZWdleChudW1Gb3JtYXQuZ2V0TGVhZGluZ0RpZ2l0cygpKS5tYXRjaGVyKG5hdGlvbmFsTnVtYmVyKQogICAgICAgICAgICAgIC5sb29raW5nQXQoKSkgewogICAgICAgIE1hdGNoZXIgbSA9IHJlZ2V4Q2FjaGUuZ2V0UGF0dGVybkZvclJlZ2V4KG51bUZvcm1hdC5nZXRQYXR0ZXJuKCkpLm1hdGNoZXIobmF0aW9uYWxOdW1iZXIpOwogICAgICAgIFN0cmluZyBudW1iZXJGb3JtYXRSdWxlID0gbnVtRm9ybWF0LmdldEZvcm1hdCgpOwogICAgICAgIGlmIChtLm1hdGNoZXMoKSkgewogICAgICAgICAgaWYgKGNhcnJpZXJDb2RlICE9IG51bGwgJiYgY2FycmllckNvZGUubGVuZ3RoKCkgPiAwICYmCiAgICAgICAgICAgICAgbnVtRm9ybWF0LmdldERvbWVzdGljQ2FycmllckNvZGVGb3JtYXR0aW5nUnVsZSgpLmxlbmd0aCgpID4gMCkgewogICAgICAgICAgICAvLyBSZXBsYWNlIHRoZSAkQ0MgaW4gdGhlIGZvcm1hdHRpbmcgcnVsZSB3aXRoIHRoZSBkZXNpcmVkIGNhcnJpZXIgY29kZS4KICAgICAgICAgICAgU3RyaW5nIGNhcnJpZXJDb2RlRm9ybWF0dGluZ1J1bGUgPSBudW1Gb3JtYXQuZ2V0RG9tZXN0aWNDYXJyaWVyQ29kZUZvcm1hdHRpbmdSdWxlKCk7CiAgICAgICAgICAgIGNhcnJpZXJDb2RlRm9ybWF0dGluZ1J1bGUgPQogICAgICAgICAgICAgICAgQ0NfUEFUVEVSTi5tYXRjaGVyKGNhcnJpZXJDb2RlRm9ybWF0dGluZ1J1bGUpLnJlcGxhY2VGaXJzdChjYXJyaWVyQ29kZSk7CiAgICAgICAgICAgIC8vIE5vdyByZXBsYWNlIHRoZSAkRkcgaW4gdGhlIGZvcm1hdHRpbmcgcnVsZSB3aXRoIHRoZSBmaXJzdCBncm91cCBhbmQgdGhlIGNhcnJpZXIgY29kZQogICAgICAgICAgICAvLyBjb21iaW5lZCBpbiB0aGUgYXBwcm9wcmlhdGUgd2F5LgogICAgICAgICAgICBudW1iZXJGb3JtYXRSdWxlID0gRklSU1RfR1JPVVBfUEFUVEVSTi5tYXRjaGVyKG51bWJlckZvcm1hdFJ1bGUpCiAgICAgICAgICAgICAgICAucmVwbGFjZUZpcnN0KGNhcnJpZXJDb2RlRm9ybWF0dGluZ1J1bGUpOwogICAgICAgICAgfQogICAgICAgICAgU3RyaW5nIG5hdGlvbmFsUHJlZml4Rm9ybWF0dGluZ1J1bGUgPSBudW1Gb3JtYXQuZ2V0TmF0aW9uYWxQcmVmaXhGb3JtYXR0aW5nUnVsZSgpOwogICAgICAgICAgaWYgKG51bWJlckZvcm1hdCA9PSBQaG9uZU51bWJlckZvcm1hdC5OQVRJT05BTCAmJgogICAgICAgICAgICAgIG5hdGlvbmFsUHJlZml4Rm9ybWF0dGluZ1J1bGUgIT0gbnVsbCAmJgogICAgICAgICAgICAgIG5hdGlvbmFsUHJlZml4Rm9ybWF0dGluZ1J1bGUubGVuZ3RoKCkgPiAwKSB7CiAgICAgICAgICAgIE1hdGNoZXIgZmlyc3RHcm91cE1hdGNoZXIgPSBGSVJTVF9HUk9VUF9QQVRURVJOLm1hdGNoZXIobnVtYmVyRm9ybWF0UnVsZSk7CiAgICAgICAgICAgIHJldHVybiBtLnJlcGxhY2VBbGwoZmlyc3RHcm91cE1hdGNoZXIucmVwbGFjZUZpcnN0KG5hdGlvbmFsUHJlZml4Rm9ybWF0dGluZ1J1bGUpKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHJldHVybiBtLnJlcGxhY2VBbGwobnVtYmVyRm9ybWF0UnVsZSk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICB9CgogICAgLy8gSWYgbm8gcGF0dGVybiBhYm92ZSBpcyBtYXRjaGVkLCB3ZSBmb3JtYXQgdGhlIG51bWJlciBhcyBhIHdob2xlLgogICAgcmV0dXJuIG5hdGlvbmFsTnVtYmVyOwogIH0KCiAgLyoqCiAgICogR2V0cyBhIHZhbGlkIG51bWJlciBmb3IgdGhlIHNwZWNpZmllZCBjb3VudHJ5LgogICAqCiAgICogQHBhcmFtIHJlZ2lvbkNvZGUgIHRoZSBJU08gMzE2Ni0xIHR3by1sZXR0ZXIgY291bnRyeSBjb2RlIHRoYXQgZGVub3RlcyB0aGUgY291bnRyeSBmb3Igd2hpY2gKICAgKiAgICAgICAgICAgICAgICAgICAgYW4gZXhhbXBsZSBudW1iZXIgaXMgbmVlZGVkCiAgICogQHJldHVybiAgYSB2YWxpZCBmaXhlZC1saW5lIG51bWJlciBmb3IgdGhlIHNwZWNpZmllZCBjb3VudHJ5LiBSZXR1cm5zIG51bGwgd2hlbiB0aGUgbWV0YWRhdGEKICAgKiAgICBkb2VzIG5vdCBjb250YWluIHN1Y2ggaW5mb3JtYXRpb24uCiAgICovCiAgcHVibGljIFBob25lTnVtYmVyIGdldEV4YW1wbGVOdW1iZXIoU3RyaW5nIHJlZ2lvbkNvZGUpIHsKICAgIHJldHVybiBnZXRFeGFtcGxlTnVtYmVyRm9yVHlwZShyZWdpb25Db2RlLCBQaG9uZU51bWJlclR5cGUuRklYRURfTElORSk7CiAgfQoKICAvKioKICAgKiBHZXRzIGEgdmFsaWQgbnVtYmVyIGZvciB0aGUgc3BlY2lmaWVkIGNvdW50cnkgYW5kIG51bWJlciB0eXBlLgogICAqCiAgICogQHBhcmFtIHJlZ2lvbkNvZGUgIHRoZSBJU08gMzE2Ni0xIHR3by1sZXR0ZXIgY291bnRyeSBjb2RlIHRoYXQgZGVub3RlcyB0aGUgY291bnRyeSBmb3Igd2hpY2gKICAgKiAgICAgICAgICAgICAgICAgICAgYW4gZXhhbXBsZSBudW1iZXIgaXMgbmVlZGVkCiAgICogQHBhcmFtIHR5cGUgIHRoZSB0eXBlIG9mIG51bWJlciB0aGF0IGlzIG5lZWRlZAogICAqIEByZXR1cm4gIGEgdmFsaWQgbnVtYmVyIGZvciB0aGUgc3BlY2lmaWVkIGNvdW50cnkgYW5kIHR5cGUuIFJldHVybnMgbnVsbCB3aGVuIHRoZSBtZXRhZGF0YQogICAqICAgICBkb2VzIG5vdCBjb250YWluIHN1Y2ggaW5mb3JtYXRpb24uCiAgICovCiAgcHVibGljIFBob25lTnVtYmVyIGdldEV4YW1wbGVOdW1iZXJGb3JUeXBlKFN0cmluZyByZWdpb25Db2RlLCBQaG9uZU51bWJlclR5cGUgdHlwZSkgewogICAgUGhvbmVOdW1iZXJEZXNjIGRlc2MgPSBnZXROdW1iZXJEZXNjQnlUeXBlKGdldE1ldGFkYXRhRm9yUmVnaW9uKHJlZ2lvbkNvZGUpLCB0eXBlKTsKICAgIHRyeSB7CiAgICAgIGlmIChkZXNjLmhhc0V4YW1wbGVOdW1iZXIoKSkgewogICAgICAgIHJldHVybiBwYXJzZShkZXNjLmdldEV4YW1wbGVOdW1iZXIoKSwgcmVnaW9uQ29kZSk7CiAgICAgIH0KICAgIH0gY2F0Y2ggKE51bWJlclBhcnNlRXhjZXB0aW9uIGUpIHsKICAgICAgTE9HR0VSLmxvZyhMZXZlbC5TRVZFUkUsIGUudG9TdHJpbmcoKSk7CiAgICB9CiAgICByZXR1cm4gbnVsbDsKICB9CgogIC8qKgogICAqIEFwcGVuZHMgdGhlIGZvcm1hdHRlZCBleHRlbnNpb24gb2YgYSBwaG9uZSBudW1iZXIgdG8gZm9ybWF0dGVkTnVtYmVyLCBpZiB0aGUgcGhvbmUgbnVtYmVyIGhhZAogICAqIGFuIGV4dGVuc2lvbiBzcGVjaWZpZWQuCiAgICovCiAgcHJpdmF0ZSB2b2lkIG1heWJlR2V0Rm9ybWF0dGVkRXh0ZW5zaW9uKFBob25lTnVtYmVyIG51bWJlciwgU3RyaW5nIHJlZ2lvbkNvZGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFN0cmluZ0J1ZmZlciBmb3JtYXR0ZWROdW1iZXIpIHsKICAgIGlmIChudW1iZXIuaGFzRXh0ZW5zaW9uKCkpIHsKICAgICAgLy8gRm9ybWF0cyB0aGUgZXh0ZW5zaW9uIHBhcnQgb2YgdGhlIHBob25lIG51bWJlciBieSBwcmVmaXhpbmcgaXQgd2l0aCB0aGUgYXBwcm9wcmlhdGUKICAgICAgLy8gZXh0ZW5zaW9uIHByZWZpeC4gVGhpcyB3aWxsIGJlIHRoZSBkZWZhdWx0IGV4dGVuc2lvbiBwcmVmaXgsIHVubGVzcyBvdmVycmlkZGVuIGJ5IGEKICAgICAgLy8gcHJlZmVycmVkIGV4dGVuc2lvbiBwcmVmaXggZm9yIHRoaXMgY291bnRyeS4KICAgICAgUGhvbmVNZXRhZGF0YSBtZXRhZGF0YSA9IGdldE1ldGFkYXRhRm9yUmVnaW9uKHJlZ2lvbkNvZGUpOwogICAgICBpZiAobWV0YWRhdGEuaGFzUHJlZmVycmVkRXh0blByZWZpeCgpKSB7CiAgICAgICAgZm9ybWF0dGVkTnVtYmVyLmFwcGVuZChtZXRhZGF0YS5nZXRQcmVmZXJyZWRFeHRuUHJlZml4KCkpOwogICAgICB9IGVsc2UgewogICAgICAgIGZvcm1hdHRlZE51bWJlci5hcHBlbmQoREVGQVVMVF9FWFROX1BSRUZJWCk7CiAgICAgIH0KICAgICAgZm9ybWF0dGVkTnVtYmVyLmFwcGVuZChudW1iZXIuZ2V0RXh0ZW5zaW9uKCkpOwogICAgfQogIH0KCiAgLyoqCiAgICogRm9ybWF0cyB0aGUgZXh0ZW5zaW9uIHBhcnQgb2YgdGhlIHBob25lIG51bWJlciBieSBwcmVmaXhpbmcgaXQgd2l0aCB0aGUgYXBwcm9wcmlhdGUgZXh0ZW5zaW9uCiAgICogcHJlZml4LiBUaGlzIHdpbGwgYmUgdGhlIGRlZmF1bHQgZXh0ZW5zaW9uIHByZWZpeCwgdW5sZXNzIG92ZXJyaWRkZW4gYnkgYSBwcmVmZXJyZWQKICAgKiBleHRlbnNpb24gcHJlZml4IGZvciB0aGlzIGNvdW50cnkuCiAgICovCiAgcHJpdmF0ZSBTdHJpbmcgZm9ybWF0RXh0ZW5zaW9uKFN0cmluZyBleHRlbnNpb25EaWdpdHMsIFN0cmluZyByZWdpb25Db2RlKSB7CiAgICBQaG9uZU1ldGFkYXRhIG1ldGFkYXRhID0gZ2V0TWV0YWRhdGFGb3JSZWdpb24ocmVnaW9uQ29kZSk7CiAgICBpZiAobWV0YWRhdGEuaGFzUHJlZmVycmVkRXh0blByZWZpeCgpKSB7CiAgICAgIHJldHVybiBtZXRhZGF0YS5nZXRQcmVmZXJyZWRFeHRuUHJlZml4KCkgKyBleHRlbnNpb25EaWdpdHM7CiAgICB9IGVsc2UgewogICAgICByZXR1cm4gREVGQVVMVF9FWFROX1BSRUZJWCArIGV4dGVuc2lvbkRpZ2l0czsKICAgIH0KICB9CgogIFBob25lTnVtYmVyRGVzYyBnZXROdW1iZXJEZXNjQnlUeXBlKFBob25lTWV0YWRhdGEgbWV0YWRhdGEsIFBob25lTnVtYmVyVHlwZSB0eXBlKSB7CiAgICBzd2l0Y2ggKHR5cGUpIHsKICAgICAgY2FzZSBQUkVNSVVNX1JBVEU6CiAgICAgICAgcmV0dXJuIG1ldGFkYXRhLmdldFByZW1pdW1SYXRlKCk7CiAgICAgIGNhc2UgVE9MTF9GUkVFOgogICAgICAgIHJldHVybiBtZXRhZGF0YS5nZXRUb2xsRnJlZSgpOwogICAgICBjYXNlIE1PQklMRToKICAgICAgICByZXR1cm4gbWV0YWRhdGEuZ2V0TW9iaWxlKCk7CiAgICAgIGNhc2UgRklYRURfTElORToKICAgICAgY2FzZSBGSVhFRF9MSU5FX09SX01PQklMRToKICAgICAgICByZXR1cm4gbWV0YWRhdGEuZ2V0Rml4ZWRMaW5lKCk7CiAgICAgIGNhc2UgU0hBUkVEX0NPU1Q6CiAgICAgICAgcmV0dXJuIG1ldGFkYXRhLmdldFNoYXJlZENvc3QoKTsKICAgICAgY2FzZSBWT0lQOgogICAgICAgIHJldHVybiBtZXRhZGF0YS5nZXRWb2lwKCk7CiAgICAgIGNhc2UgUEVSU09OQUxfTlVNQkVSOgogICAgICAgIHJldHVybiBtZXRhZGF0YS5nZXRQZXJzb25hbE51bWJlcigpOwogICAgICBkZWZhdWx0OgogICAgICAgIHJldHVybiBtZXRhZGF0YS5nZXRHZW5lcmFsRGVzYygpOwogICAgfQogIH0KCiAgLyoqCiAgICogR2V0cyB0aGUgdHlwZSBvZiBhIHBob25lIG51bWJlci4KICAgKgogICAqIEBwYXJhbSBudW1iZXIgIHRoZSBwaG9uZSBudW1iZXIgdGhhdCB3ZSB3YW50IHRvIGtub3cgdGhlIHR5cGUKICAgKiBAcmV0dXJuICB0aGUgdHlwZSBvZiB0aGUgcGhvbmUgbnVtYmVyCiAgICovCiAgcHVibGljIFBob25lTnVtYmVyVHlwZSBnZXROdW1iZXJUeXBlKFBob25lTnVtYmVyIG51bWJlcikgewogICAgU3RyaW5nIHJlZ2lvbkNvZGUgPSBnZXRSZWdpb25Db2RlRm9yTnVtYmVyKG51bWJlcik7CiAgICBpZiAoIWlzVmFsaWRSZWdpb25Db2RlKHJlZ2lvbkNvZGUpKSB7CiAgICAgIHJldHVybiBQaG9uZU51bWJlclR5cGUuVU5LTk9XTjsKICAgIH0KICAgIFN0cmluZyBuYXRpb25hbFNpZ25pZmljYW50TnVtYmVyID0gZ2V0TmF0aW9uYWxTaWduaWZpY2FudE51bWJlcihudW1iZXIpOwogICAgcmV0dXJuIGdldE51bWJlclR5cGVIZWxwZXIobmF0aW9uYWxTaWduaWZpY2FudE51bWJlciwgZ2V0TWV0YWRhdGFGb3JSZWdpb24ocmVnaW9uQ29kZSkpOwogIH0KCiAgcHJpdmF0ZSBQaG9uZU51bWJlclR5cGUgZ2V0TnVtYmVyVHlwZUhlbHBlcihTdHJpbmcgbmF0aW9uYWxOdW1iZXIsIFBob25lTWV0YWRhdGEgbWV0YWRhdGEpIHsKICAgIFBob25lTnVtYmVyRGVzYyBnZW5lcmFsTnVtYmVyRGVzYyA9IG1ldGFkYXRhLmdldEdlbmVyYWxEZXNjKCk7CiAgICBpZiAoIWdlbmVyYWxOdW1iZXJEZXNjLmhhc05hdGlvbmFsTnVtYmVyUGF0dGVybigpIHx8CiAgICAgICAgIWlzTnVtYmVyTWF0Y2hpbmdEZXNjKG5hdGlvbmFsTnVtYmVyLCBnZW5lcmFsTnVtYmVyRGVzYykpIHsKICAgICAgcmV0dXJuIFBob25lTnVtYmVyVHlwZS5VTktOT1dOOwogICAgfQoKICAgIGlmIChpc051bWJlck1hdGNoaW5nRGVzYyhuYXRpb25hbE51bWJlciwgbWV0YWRhdGEuZ2V0UHJlbWl1bVJhdGUoKSkpIHsKICAgICAgcmV0dXJuIFBob25lTnVtYmVyVHlwZS5QUkVNSVVNX1JBVEU7CiAgICB9CiAgICBpZiAoaXNOdW1iZXJNYXRjaGluZ0Rlc2MobmF0aW9uYWxOdW1iZXIsIG1ldGFkYXRhLmdldFRvbGxGcmVlKCkpKSB7CiAgICAgIHJldHVybiBQaG9uZU51bWJlclR5cGUuVE9MTF9GUkVFOwogICAgfQogICAgaWYgKGlzTnVtYmVyTWF0Y2hpbmdEZXNjKG5hdGlvbmFsTnVtYmVyLCBtZXRhZGF0YS5nZXRTaGFyZWRDb3N0KCkpKSB7CiAgICAgIHJldHVybiBQaG9uZU51bWJlclR5cGUuU0hBUkVEX0NPU1Q7CiAgICB9CiAgICBpZiAoaXNOdW1iZXJNYXRjaGluZ0Rlc2MobmF0aW9uYWxOdW1iZXIsIG1ldGFkYXRhLmdldFZvaXAoKSkpIHsKICAgICAgcmV0dXJuIFBob25lTnVtYmVyVHlwZS5WT0lQOwogICAgfQogICAgaWYgKGlzTnVtYmVyTWF0Y2hpbmdEZXNjKG5hdGlvbmFsTnVtYmVyLCBtZXRhZGF0YS5nZXRQZXJzb25hbE51bWJlcigpKSkgewogICAgICByZXR1cm4gUGhvbmVOdW1iZXJUeXBlLlBFUlNPTkFMX05VTUJFUjsKICAgIH0KCiAgICBib29sZWFuIGlzRml4ZWRMaW5lID0gaXNOdW1iZXJNYXRjaGluZ0Rlc2MobmF0aW9uYWxOdW1iZXIsIG1ldGFkYXRhLmdldEZpeGVkTGluZSgpKTsKICAgIGlmIChpc0ZpeGVkTGluZSkgewogICAgICBpZiAobWV0YWRhdGEuZ2V0U2FtZU1vYmlsZUFuZEZpeGVkTGluZVBhdHRlcm4oKSkgewogICAgICAgIHJldHVybiBQaG9uZU51bWJlclR5cGUuRklYRURfTElORV9PUl9NT0JJTEU7CiAgICAgIH0gZWxzZSBpZiAoaXNOdW1iZXJNYXRjaGluZ0Rlc2MobmF0aW9uYWxOdW1iZXIsIG1ldGFkYXRhLmdldE1vYmlsZSgpKSkgewogICAgICAgIHJldHVybiBQaG9uZU51bWJlclR5cGUuRklYRURfTElORV9PUl9NT0JJTEU7CiAgICAgIH0KICAgICAgcmV0dXJuIFBob25lTnVtYmVyVHlwZS5GSVhFRF9MSU5FOwogICAgfQogICAgLy8gT3RoZXJ3aXNlLCB0ZXN0IHRvIHNlZSBpZiB0aGUgbnVtYmVyIGlzIG1vYmlsZS4gT25seSBkbyB0aGlzIGlmIGNlcnRhaW4gdGhhdCB0aGUgcGF0dGVybnMgZm9yCiAgICAvLyBtb2JpbGUgYW5kIGZpeGVkIGxpbmUgYXJlbid0IHRoZSBzYW1lLgogICAgaWYgKCFtZXRhZGF0YS5nZXRTYW1lTW9iaWxlQW5kRml4ZWRMaW5lUGF0dGVybigpICYmCiAgICAgICAgaXNOdW1iZXJNYXRjaGluZ0Rlc2MobmF0aW9uYWxOdW1iZXIsIG1ldGFkYXRhLmdldE1vYmlsZSgpKSkgewogICAgICByZXR1cm4gUGhvbmVOdW1iZXJUeXBlLk1PQklMRTsKICAgIH0KICAgIHJldHVybiBQaG9uZU51bWJlclR5cGUuVU5LTk9XTjsKICB9CgogIFBob25lTWV0YWRhdGEgZ2V0TWV0YWRhdGFGb3JSZWdpb24oU3RyaW5nIHJlZ2lvbkNvZGUpIHsKICAgIGlmIChyZWdpb25Db2RlID09IG51bGwpIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICByZXR1cm4gY291bnRyeVRvTWV0YWRhdGFNYXAuZ2V0KHJlZ2lvbkNvZGUpOwogIH0KCiAgcHJpdmF0ZSBib29sZWFuIGlzTnVtYmVyTWF0Y2hpbmdEZXNjKFN0cmluZyBuYXRpb25hbE51bWJlciwgUGhvbmVOdW1iZXJEZXNjIG51bWJlckRlc2MpIHsKICAgIE1hdGNoZXIgcG9zc2libGVOdW1iZXJQYXR0ZXJuTWF0Y2hlciA9CiAgICAgICAgcmVnZXhDYWNoZS5nZXRQYXR0ZXJuRm9yUmVnZXgobnVtYmVyRGVzYy5nZXRQb3NzaWJsZU51bWJlclBhdHRlcm4oKSkKICAgICAgICAgICAgLm1hdGNoZXIobmF0aW9uYWxOdW1iZXIpOwogICAgTWF0Y2hlciBuYXRpb25hbE51bWJlclBhdHRlcm5NYXRjaGVyID0KICAgICAgICByZWdleENhY2hlLmdldFBhdHRlcm5Gb3JSZWdleChudW1iZXJEZXNjLmdldE5hdGlvbmFsTnVtYmVyUGF0dGVybigpKQogICAgICAgICAgICAubWF0Y2hlcihuYXRpb25hbE51bWJlcik7CiAgICByZXR1cm4gcG9zc2libGVOdW1iZXJQYXR0ZXJuTWF0Y2hlci5tYXRjaGVzKCkgJiYgbmF0aW9uYWxOdW1iZXJQYXR0ZXJuTWF0Y2hlci5tYXRjaGVzKCk7CiAgfQoKICAvKioKICAgKiBUZXN0cyB3aGV0aGVyIGEgcGhvbmUgbnVtYmVyIG1hdGNoZXMgYSB2YWxpZCBwYXR0ZXJuLiBOb3RlIHRoaXMgZG9lc24ndCB2ZXJpZnkgdGhlIG51bWJlcgogICAqIGlzIGFjdHVhbGx5IGluIHVzZSwgd2hpY2ggaXMgaW1wb3NzaWJsZSB0byB0ZWxsIGJ5IGp1c3QgbG9va2luZyBhdCBhIG51bWJlciBpdHNlbGYuCiAgICoKICAgKiBAcGFyYW0gbnVtYmVyICAgICAgIHRoZSBwaG9uZSBudW1iZXIgdGhhdCB3ZSB3YW50IHRvIHZhbGlkYXRlCiAgICogQHJldHVybiAgYSBib29sZWFuIHRoYXQgaW5kaWNhdGVzIHdoZXRoZXIgdGhlIG51bWJlciBpcyBvZiBhIHZhbGlkIHBhdHRlcm4KICAgKi8KICBwdWJsaWMgYm9vbGVhbiBpc1ZhbGlkTnVtYmVyKFBob25lTnVtYmVyIG51bWJlcikgewogICAgU3RyaW5nIHJlZ2lvbkNvZGUgPSBnZXRSZWdpb25Db2RlRm9yTnVtYmVyKG51bWJlcik7CiAgICByZXR1cm4gaXNWYWxpZFJlZ2lvbkNvZGUocmVnaW9uQ29kZSkKICAgICAgICAgICAmJiBpc1ZhbGlkTnVtYmVyRm9yUmVnaW9uKG51bWJlciwgcmVnaW9uQ29kZSk7CiAgfQoKICAvKioKICAgKiBUZXN0cyB3aGV0aGVyIGEgcGhvbmUgbnVtYmVyIGlzIHZhbGlkIGZvciBhIGNlcnRhaW4gcmVnaW9uLiBOb3RlIHRoaXMgZG9lc24ndCB2ZXJpZnkgdGhlIG51bWJlcgogICAqIGlzIGFjdHVhbGx5IGluIHVzZSwgd2hpY2ggaXMgaW1wb3NzaWJsZSB0byB0ZWxsIGJ5IGp1c3QgbG9va2luZyBhdCBhIG51bWJlciBpdHNlbGYuIElmIHRoZQogICAqIGNvdW50cnkgY29kZSBpcyBub3QgdGhlIHNhbWUgYXMgdGhlIGNvdW50cnkgY29kZSBmb3IgdGhlIHJlZ2lvbiwgdGhpcyBpbW1lZGlhdGVseSBleGl0cyB3aXRoCiAgICogZmFsc2UuIEFmdGVyIHRoaXMsIHRoZSBzcGVjaWZpYyBudW1iZXIgcGF0dGVybiBydWxlcyBmb3IgdGhlIHJlZ2lvbiBhcmUgZXhhbWluZWQuIFRoaXMgaXMKICAgKiB1c2VmdWwgZm9yIGRldGVybWluaW5nIGZvciBleGFtcGxlIHdoZXRoZXIgYSBwYXJ0aWN1bGFyIG51bWJlciBpcyB2YWxpZCBmb3IgQ2FuYWRhLCByYXRoZXIgdGhhbgogICAqIGp1c3QgYSB2YWxpZCBOQU5QQSBudW1iZXIuCiAgICoKICAgKiBAcGFyYW0gbnVtYmVyICAgICAgIHRoZSBwaG9uZSBudW1iZXIgdGhhdCB3ZSB3YW50IHRvIHZhbGlkYXRlCiAgICogQHBhcmFtIHJlZ2lvbkNvZGUgICB0aGUgSVNPIDMxNjYtMSB0d28tbGV0dGVyIGNvdW50cnkgY29kZSB0aGF0IGRlbm90ZXMgdGhlIHJlZ2lvbi9jb3VudHJ5CiAgICogICAgICAgICAgICAgICAgICAgICB0aGF0IHdlIHdhbnQgdG8gdmFsaWRhdGUgdGhlIHBob25lIG51bWJlciBmb3IKICAgKiBAcmV0dXJuICBhIGJvb2xlYW4gdGhhdCBpbmRpY2F0ZXMgd2hldGhlciB0aGUgbnVtYmVyIGlzIG9mIGEgdmFsaWQgcGF0dGVybgogICAqLwogIHB1YmxpYyBib29sZWFuIGlzVmFsaWROdW1iZXJGb3JSZWdpb24oUGhvbmVOdW1iZXIgbnVtYmVyLCBTdHJpbmcgcmVnaW9uQ29kZSkgewogICAgaWYgKG51bWJlci5nZXRDb3VudHJ5Q29kZSgpICE9IGdldENvdW50cnlDb2RlRm9yUmVnaW9uKHJlZ2lvbkNvZGUpKSB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICAgIFBob25lTWV0YWRhdGEgbWV0YWRhdGEgPSBnZXRNZXRhZGF0YUZvclJlZ2lvbihyZWdpb25Db2RlKTsKICAgIFBob25lTnVtYmVyRGVzYyBnZW5lcmFsTnVtRGVzYyA9IG1ldGFkYXRhLmdldEdlbmVyYWxEZXNjKCk7CiAgICBTdHJpbmcgbmF0aW9uYWxTaWduaWZpY2FudE51bWJlciA9IGdldE5hdGlvbmFsU2lnbmlmaWNhbnROdW1iZXIobnVtYmVyKTsKCiAgICAvLyBGb3IgY291bnRyaWVzIHdoZXJlIHdlIGRvbid0IGhhdmUgbWV0YWRhdGEgZm9yIFBob25lTnVtYmVyRGVzYywgd2UgdHJlYXQgYW55IG51bWJlciBwYXNzZWQKICAgIC8vIGluIGFzIGEgdmFsaWQgbnVtYmVyIGlmIGl0cyBuYXRpb25hbCBzaWduaWZpY2FudCBudW1iZXIgaXMgYmV0d2VlbiB0aGUgbWluaW11bSBhbmQgbWF4aW11bQogICAgLy8gbGVuZ3RocyBkZWZpbmVkIGJ5IElUVSBmb3IgYSBuYXRpb25hbCBzaWduaWZpY2FudCBudW1iZXIuCiAgICBpZiAoIWdlbmVyYWxOdW1EZXNjLmhhc05hdGlvbmFsTnVtYmVyUGF0dGVybigpKSB7CiAgICAgIGludCBudW1iZXJMZW5ndGggPSBuYXRpb25hbFNpZ25pZmljYW50TnVtYmVyLmxlbmd0aCgpOwogICAgICByZXR1cm4gbnVtYmVyTGVuZ3RoID4gTUlOX0xFTkdUSF9GT1JfTlNOICYmIG51bWJlckxlbmd0aCA8PSBNQVhfTEVOR1RIX0ZPUl9OU047CiAgICB9CiAgICByZXR1cm4gZ2V0TnVtYmVyVHlwZUhlbHBlcihuYXRpb25hbFNpZ25pZmljYW50TnVtYmVyLCBtZXRhZGF0YSkgIT0gUGhvbmVOdW1iZXJUeXBlLlVOS05PV047CiAgfQoKICAvKioKICAgKiBSZXR1cm5zIHRoZSBjb3VudHJ5L3JlZ2lvbiB3aGVyZSBhIHBob25lIG51bWJlciBpcyBmcm9tLiBUaGlzIGNvdWxkIGJlIHVzZWQgZm9yIGdlby1jb2RpbmcgaW4KICAgKiB0aGUgY291bnRyeS9yZWdpb24gbGV2ZWwuCiAgICoKICAgKiBAcGFyYW0gbnVtYmVyICB0aGUgcGhvbmUgbnVtYmVyIHdob3NlIG9yaWdpbiB3ZSB3YW50IHRvIGtub3cKICAgKiBAcmV0dXJuICB0aGUgY291bnRyeS9yZWdpb24gd2hlcmUgdGhlIHBob25lIG51bWJlciBpcyBmcm9tLCBvciBudWxsIGlmIG5vIGNvdW50cnkgbWF0Y2hlcyB0aGlzCiAgICogICAgIGNhbGxpbmcgY29kZS4KICAgKi8KICBwdWJsaWMgU3RyaW5nIGdldFJlZ2lvbkNvZGVGb3JOdW1iZXIoUGhvbmVOdW1iZXIgbnVtYmVyKSB7CiAgICBpbnQgY291bnRyeUNvZGUgPSBudW1iZXIuZ2V0Q291bnRyeUNvZGUoKTsKICAgIExpc3Q8U3RyaW5nPiByZWdpb25zID0gY291bnRyeUNvZGVUb1JlZ2lvbkNvZGVNYXAuZ2V0KGNvdW50cnlDb2RlKTsKICAgIGlmIChyZWdpb25zID09IG51bGwpIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICBpZiAocmVnaW9ucy5zaXplKCkgPT0gMSkgewogICAgICByZXR1cm4gcmVnaW9ucy5nZXQoMCk7CiAgICB9IGVsc2UgewogICAgICByZXR1cm4gZ2V0UmVnaW9uQ29kZUZvck51bWJlckZyb21SZWdpb25MaXN0KG51bWJlciwgcmVnaW9ucyk7CiAgICB9CiAgfQoKICBwcml2YXRlIFN0cmluZyBnZXRSZWdpb25Db2RlRm9yTnVtYmVyRnJvbVJlZ2lvbkxpc3QoUGhvbmVOdW1iZXIgbnVtYmVyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBMaXN0PFN0cmluZz4gcmVnaW9uQ29kZXMpIHsKICAgIFN0cmluZyBuYXRpb25hbE51bWJlciA9IFN0cmluZy52YWx1ZU9mKG51bWJlci5nZXROYXRpb25hbE51bWJlcigpKTsKICAgIGZvciAoU3RyaW5nIHJlZ2lvbkNvZGUgOiByZWdpb25Db2RlcykgewogICAgICAvLyBJZiBsZWFkaW5nRGlnaXRzIGlzIHByZXNlbnQsIHVzZSB0aGlzLiBPdGhlcndpc2UsIGRvIGZ1bGwgdmFsaWRhdGlvbi4KICAgICAgUGhvbmVNZXRhZGF0YSBtZXRhZGF0YSA9IGdldE1ldGFkYXRhRm9yUmVnaW9uKHJlZ2lvbkNvZGUpOwogICAgICBpZiAobWV0YWRhdGEuaGFzTGVhZGluZ0RpZ2l0cygpKSB7CiAgICAgICAgaWYgKHJlZ2V4Q2FjaGUuZ2V0UGF0dGVybkZvclJlZ2V4KG1ldGFkYXRhLmdldExlYWRpbmdEaWdpdHMoKSkKICAgICAgICAgICAgICAgIC5tYXRjaGVyKG5hdGlvbmFsTnVtYmVyKS5sb29raW5nQXQoKSkgewogICAgICAgICAgcmV0dXJuIHJlZ2lvbkNvZGU7CiAgICAgICAgfQogICAgICB9IGVsc2UgaWYgKGdldE51bWJlclR5cGVIZWxwZXIobmF0aW9uYWxOdW1iZXIsIG1ldGFkYXRhKSAhPSBQaG9uZU51bWJlclR5cGUuVU5LTk9XTikgewogICAgICAgIHJldHVybiByZWdpb25Db2RlOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gbnVsbDsKICB9CgogIC8qKgogICAqIFJldHVybnMgdGhlIHJlZ2lvbiBjb2RlIHRoYXQgbWF0Y2hlcyB0aGUgc3BlY2lmaWMgY291bnRyeSBjb2RlLiBJbiB0aGUgY2FzZSBvZiBubyByZWdpb24gY29kZQogICAqIGJlaW5nIGZvdW5kLCBaWiB3aWxsIGJlIHJldHVybmVkLiBJbiB0aGUgY2FzZSBvZiBtdWx0aXBsZSByZWdpb25zLCB0aGUgb25lIGRlc2lnbmF0ZWQgaW4gdGhlCiAgICogbWV0YWRhdGEgYXMgdGhlICJtYWluIiBjb3VudHJ5IGZvciB0aGlzIGNhbGxpbmcgY29kZSB3aWxsIGJlIHJldHVybmVkLgogICAqLwogIHB1YmxpYyBTdHJpbmcgZ2V0UmVnaW9uQ29kZUZvckNvdW50cnlDb2RlKGludCBjb3VudHJ5Q29kZSkgewogICAgTGlzdDxTdHJpbmc+IHJlZ2lvbkNvZGVzID0gY291bnRyeUNvZGVUb1JlZ2lvbkNvZGVNYXAuZ2V0KGNvdW50cnlDb2RlKTsKICAgIHJldHVybiByZWdpb25Db2RlcyA9PSBudWxsID8gIlpaIiA6IHJlZ2lvbkNvZGVzLmdldCgwKTsKICB9CgogIC8qKgogICAqIFJldHVybnMgdGhlIGNvdW50cnkgY2FsbGluZyBjb2RlIGZvciBhIHNwZWNpZmljIHJlZ2lvbi4gRm9yIGV4YW1wbGUsIHRoaXMgd291bGQgYmUgMSBmb3IgdGhlCiAgICogVW5pdGVkIFN0YXRlcywgYW5kIDY0IGZvciBOZXcgWmVhbGFuZC4KICAgKgogICAqIEBwYXJhbSByZWdpb25Db2RlICB0aGUgSVNPIDMxNjYtMSB0d28tbGV0dGVyIGNvdW50cnkgY29kZSB0aGF0IGRlbm90ZXMgdGhlIGNvdW50cnkvcmVnaW9uIHRoYXQKICAgKiAgICAgICAgICAgICAgICAgICAgd2Ugd2FudCB0byBnZXQgdGhlIGNvdW50cnkgY29kZSBmb3IKICAgKiBAcmV0dXJuICB0aGUgY291bnRyeSBjYWxsaW5nIGNvZGUgZm9yIHRoZSBjb3VudHJ5L3JlZ2lvbiBkZW5vdGVkIGJ5IHJlZ2lvbkNvZGUKICAgKi8KICBwdWJsaWMgaW50IGdldENvdW50cnlDb2RlRm9yUmVnaW9uKFN0cmluZyByZWdpb25Db2RlKSB7CiAgICBpZiAoIWlzVmFsaWRSZWdpb25Db2RlKHJlZ2lvbkNvZGUpKSB7CiAgICAgIHJldHVybiAwOwogICAgfQogICAgUGhvbmVNZXRhZGF0YSBtZXRhZGF0YSA9IGdldE1ldGFkYXRhRm9yUmVnaW9uKHJlZ2lvbkNvZGUpOwogICAgaWYgKG1ldGFkYXRhID09IG51bGwpIHsKICAgICAgcmV0dXJuIDA7CiAgICB9CiAgICByZXR1cm4gbWV0YWRhdGEuZ2V0Q291bnRyeUNvZGUoKTsKICB9CgogIC8qKgogICAqIENoZWNrIGlmIGEgY291bnRyeSBpcyBvbmUgb2YgdGhlIGNvdW50cmllcyB1bmRlciB0aGUgTm9ydGggQW1lcmljYW4gTnVtYmVyaW5nIFBsYW4KICAgKiBBZG1pbmlzdHJhdGlvbiAoTkFOUEEpLgogICAqCiAgICogQHJldHVybiAgdHJ1ZSBpZiByZWdpb25Db2RlIGlzIG9uZSBvZiB0aGUgY291bnRyaWVzIHVuZGVyIE5BTlBBCiAgICovCiAgcHVibGljIGJvb2xlYW4gaXNOQU5QQUNvdW50cnkoU3RyaW5nIHJlZ2lvbkNvZGUpIHsKICAgIHJldHVybiBuYW5wYUNvdW50cmllcy5jb250YWlucyhyZWdpb25Db2RlKTsKICB9CgogIC8qKgogICAqIENvbnZlbmllbmNlIHdyYXBwZXIgYXJvdW5kIGlzUG9zc2libGVOdW1iZXJXaXRoUmVhc29uLiBJbnN0ZWFkIG9mIHJldHVybmluZyB0aGUgcmVhc29uIGZvcgogICAqIGZhaWx1cmUsIHRoaXMgbWV0aG9kIHJldHVybnMgYSBib29sZWFuIHZhbHVlLgogICAqIEBwYXJhbSBudW1iZXIgIHRoZSBudW1iZXIgdGhhdCBuZWVkcyB0byBiZSBjaGVja2VkCiAgICogQHJldHVybiAgdHJ1ZSBpZiB0aGUgbnVtYmVyIGlzIHBvc3NpYmxlCiAgICovCiAgcHVibGljIGJvb2xlYW4gaXNQb3NzaWJsZU51bWJlcihQaG9uZU51bWJlciBudW1iZXIpIHsKICAgIHJldHVybiBpc1Bvc3NpYmxlTnVtYmVyV2l0aFJlYXNvbihudW1iZXIpID09IFZhbGlkYXRpb25SZXN1bHQuSVNfUE9TU0lCTEU7CiAgfQoKICAvKioKICAgKiBDaGVjayB3aGV0aGVyIGNvdW50cnlDb2RlIHJlcHJlc2VudHMgdGhlIGNvdW50cnkgY2FsbGluZyBjb2RlIGZyb20gYSBjb3VudHJ5IHdob3NlIG5hdGlvbmFsCiAgICogc2lnbmlmaWNhbnQgbnVtYmVyIGNvdWxkIGNvbnRhaW4gYSBsZWFkaW5nIHplcm8uIEFuIGV4YW1wbGUgb2Ygc3VjaCBhIGNvdW50cnkgaXMgSXRhbHkuCiAgICovCiAgcHVibGljIHN0YXRpYyBib29sZWFuIGlzTGVhZGluZ1plcm9Db3VudHJ5KGludCBjb3VudHJ5Q29kZSkgewogICAgcmV0dXJuIExFQURJTkdfWkVST19DT1VOVFJJRVMuY29udGFpbnMoY291bnRyeUNvZGUpOwogIH0KCiAgLyoqCiAgICogQ2hlY2sgd2hldGhlciBhIHBob25lIG51bWJlciBpcyBhIHBvc3NpYmxlIG51bWJlci4gSXQgcHJvdmlkZXMgYSBtb3JlIGxlbmllbnQgY2hlY2sgdGhhbgogICAqIGlzVmFsaWROdW1iZXIgaW4gdGhlIGZvbGxvd2luZyBzZW5zZToKICAgKiAgIDEuIEl0IG9ubHkgY2hlY2tzIHRoZSBsZW5ndGggb2YgcGhvbmUgbnVtYmVycy4gSW4gcGFydGljdWxhciwgaXQgZG9lc24ndCBjaGVjayBzdGFydGluZwogICAqICAgICAgZGlnaXRzIG9mIHRoZSBudW1iZXIuCiAgICogICAyLiBJdCBkb2Vzbid0IGF0dGVtcHQgdG8gZmlndXJlIG91dCB0aGUgdHlwZSBvZiB0aGUgbnVtYmVyLCBidXQgdXNlcyBnZW5lcmFsIHJ1bGVzIHdoaWNoCiAgICogICAgICBhcHBsaWVzIHRvIGFsbCB0eXBlcyBvZiBwaG9uZSBudW1iZXJzIGluIGEgY291bnRyeS4gVGhlcmVmb3JlLCBpdCBpcyBtdWNoIGZhc3RlciB0aGFuCiAgICogICAgICBpc1ZhbGlkTnVtYmVyLgogICAqICAgMy4gRm9yIGZpeGVkIGxpbmUgbnVtYmVycywgbWFueSBjb3VudHJpZXMgaGF2ZSB0aGUgY29uY2VwdCBvZiBhcmVhIGNvZGUsIHdoaWNoIHRvZ2V0aGVyIHdpdGgKICAgKiAgICAgIHN1YnNjcmliZXIgbnVtYmVyIGNvbnN0aXR1dGUgdGhlIG5hdGlvbmFsIHNpZ25pZmljYW50IG51bWJlci4gSXQgaXMgc29tZXRpbWVzIG9rYXkgdG8gZGlhbAogICAqICAgICAgdGhlIHN1YnNjcmliZXIgbnVtYmVyIG9ubHkgd2hlbiBkaWFsaW5nIGluIHRoZSBzYW1lIGFyZWEuIFRoaXMgZnVuY3Rpb24gd2lsbCByZXR1cm4KICAgKiAgICAgIHRydWUgaWYgdGhlIHN1YnNjcmliZXItbnVtYmVyLW9ubHkgdmVyc2lvbiBpcyBwYXNzZWQgaW4uIE9uIHRoZSBvdGhlciBoYW5kLCBiZWNhdXNlCiAgICogICAgICBpc1ZhbGlkTnVtYmVyIHZhbGlkYXRlcyB1c2luZyBpbmZvcm1hdGlvbiBvbiBib3RoIHN0YXJ0aW5nIGRpZ2l0cyAoZm9yIGZpeGVkIGxpbmUKICAgKiAgICAgIG51bWJlcnMsIHRoYXQgd291bGQgbW9zdCBsaWtlbHkgYmUgYXJlYSBjb2RlcykgYW5kIGxlbmd0aCAob2J2aW91c2x5IGluY2x1ZGVzIHRoZQogICAqICAgICAgbGVuZ3RoIG9mIGFyZWEgY29kZXMgZm9yIGZpeGVkIGxpbmUgbnVtYmVycyksIGl0IHdpbGwgcmV0dXJuIGZhbHNlIGZvciB0aGUKICAgKiAgICAgIHN1YnNjcmliZXItbnVtYmVyLW9ubHkgdmVyc2lvbi4KICAgKgogICAqIEBwYXJhbSBudW1iZXIgIHRoZSBudW1iZXIgdGhhdCBuZWVkcyB0byBiZSBjaGVja2VkCiAgICogQHJldHVybiAgYSBWYWxpZGF0aW9uUmVzdWx0IG9iamVjdCB3aGljaCBpbmRpY2F0ZXMgd2hldGhlciB0aGUgbnVtYmVyIGlzIHBvc3NpYmxlCiAgICovCiAgcHVibGljIFZhbGlkYXRpb25SZXN1bHQgaXNQb3NzaWJsZU51bWJlcldpdGhSZWFzb24oUGhvbmVOdW1iZXIgbnVtYmVyKSB7CiAgICBpbnQgY291bnRyeUNvZGUgPSBudW1iZXIuZ2V0Q291bnRyeUNvZGUoKTsKICAgIC8vIE5vdGU6IEZvciBSdXNzaWFuIEZlZCBhbmQgTkFOUEEgbnVtYmVycywgd2UganVzdCB1c2UgdGhlIHJ1bGVzIGZyb20gdGhlIGRlZmF1bHQgcmVnaW9uIChVUyBvcgogICAgLy8gUnVzc2lhKSBzaW5jZSB0aGUgZ2V0UmVnaW9uQ29kZUZvck51bWJlciB3aWxsIG5vdCB3b3JrIGlmIHRoZSBudW1iZXIgaXMgcG9zc2libGUgYnV0IG5vdAogICAgLy8gdmFsaWQuIFRoaXMgd291bGQgbmVlZCB0byBiZSByZXZpc2l0ZWQgaWYgdGhlIHBvc3NpYmxlIG51bWJlciBwYXR0ZXJuIGV2ZXIgZGlmZmVyZWQgYmV0d2VlbgogICAgLy8gdmFyaW91cyBjb3VudHJpZXMgd2l0aGluIHRob3NlIHBsYW5zLgogICAgU3RyaW5nIHJlZ2lvbkNvZGUgPSBnZXRSZWdpb25Db2RlRm9yQ291bnRyeUNvZGUoY291bnRyeUNvZGUpOwogICAgaWYgKCFpc1ZhbGlkUmVnaW9uQ29kZShyZWdpb25Db2RlKSkgewogICAgICByZXR1cm4gVmFsaWRhdGlvblJlc3VsdC5JTlZBTElEX0NPVU5UUllfQ09ERTsKICAgIH0KICAgIFN0cmluZyBuYXRpb25hbE51bWJlciA9IGdldE5hdGlvbmFsU2lnbmlmaWNhbnROdW1iZXIobnVtYmVyKTsKICAgIFBob25lTnVtYmVyRGVzYyBnZW5lcmFsTnVtRGVzYyA9IGdldE1ldGFkYXRhRm9yUmVnaW9uKHJlZ2lvbkNvZGUpLmdldEdlbmVyYWxEZXNjKCk7CiAgICAvLyBIYW5kbGluZyBjYXNlIG9mIG51bWJlcnMgd2l0aCBubyBtZXRhZGF0YS4KICAgIGlmICghZ2VuZXJhbE51bURlc2MuaGFzTmF0aW9uYWxOdW1iZXJQYXR0ZXJuKCkpIHsKICAgICAgTE9HR0VSLmxvZyhMZXZlbC5GSU5FUiwgIkNoZWNraW5nIGlmIG51bWJlciBpcyBwb3NzaWJsZSB3aXRoIGluY29tcGxldGUgbWV0YWRhdGEuIik7CiAgICAgIGludCBudW1iZXJMZW5ndGggPSBuYXRpb25hbE51bWJlci5sZW5ndGgoKTsKICAgICAgaWYgKG51bWJlckxlbmd0aCA8IE1JTl9MRU5HVEhfRk9SX05TTikgewogICAgICAgIHJldHVybiBWYWxpZGF0aW9uUmVzdWx0LlRPT19TSE9SVDsKICAgICAgfSBlbHNlIGlmIChudW1iZXJMZW5ndGggPiBNQVhfTEVOR1RIX0ZPUl9OU04pIHsKICAgICAgICByZXR1cm4gVmFsaWRhdGlvblJlc3VsdC5UT09fTE9ORzsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gVmFsaWRhdGlvblJlc3VsdC5JU19QT1NTSUJMRTsKICAgICAgfQogICAgfQogICAgU3RyaW5nIHBvc3NpYmxlTnVtYmVyUGF0dGVybiA9IGdlbmVyYWxOdW1EZXNjLmdldFBvc3NpYmxlTnVtYmVyUGF0dGVybigpOwogICAgTWF0Y2hlciBtID0gcmVnZXhDYWNoZS5nZXRQYXR0ZXJuRm9yUmVnZXgocG9zc2libGVOdW1iZXJQYXR0ZXJuKS5tYXRjaGVyKG5hdGlvbmFsTnVtYmVyKTsKICAgIGlmIChtLmxvb2tpbmdBdCgpKSB7CiAgICAgIHJldHVybiAobS5lbmQoKSA9PSBuYXRpb25hbE51bWJlci5sZW5ndGgoKSkgPyBWYWxpZGF0aW9uUmVzdWx0LklTX1BPU1NJQkxFCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOiBWYWxpZGF0aW9uUmVzdWx0LlRPT19MT05HOwogICAgfSBlbHNlIHsKICAgICAgcmV0dXJuIFZhbGlkYXRpb25SZXN1bHQuVE9PX1NIT1JUOwogICAgfQogIH0KCiAgLyoqCiAgICogQ2hlY2sgd2hldGhlciBhIHBob25lIG51bWJlciBpcyBhIHBvc3NpYmxlIG51bWJlciBnaXZlbiBhIG51bWJlciBpbiB0aGUgZm9ybSBvZiBhIHN0cmluZywgYW5kCiAgICogdGhlIGNvdW50cnkgd2hlcmUgdGhlIG51bWJlciBjb3VsZCBiZSBkaWFsZWQgZnJvbS4gSXQgcHJvdmlkZXMgYSBtb3JlIGxlbmllbnQgY2hlY2sgdGhhbgogICAqIGlzVmFsaWROdW1iZXIuIFNlZSBpc1Bvc3NpYmxlTnVtYmVyKFBob25lTnVtYmVyIG51bWJlcikgZm9yIGRldGFpbHMuCiAgICoKICAgKiBUaGlzIG1ldGhvZCBmaXJzdCBwYXJzZXMgdGhlIG51bWJlciwgdGhlbiBpbnZva2VzIGlzUG9zc2libGVOdW1iZXIoUGhvbmVOdW1iZXIgbnVtYmVyKSB3aXRoIHRoZQogICAqIHJlc3VsdGFudCBQaG9uZU51bWJlciBvYmplY3QuCiAgICoKICAgKiBAcGFyYW0gbnVtYmVyICB0aGUgbnVtYmVyIHRoYXQgbmVlZHMgdG8gYmUgY2hlY2tlZCwgaW4gdGhlIGZvcm0gb2YgYSBzdHJpbmcKICAgKiBAcGFyYW0gY291bnRyeURpYWxpbmdGcm9tICB0aGUgSVNPIDMxNjYtMSB0d28tbGV0dGVyIGNvdW50cnkgY29kZSB0aGF0IGRlbm90ZXMKICAgKiAgICAgICAgICAgIHRoZSBjb3VudHJ5IHRoYXQgd2UgYXJlIGV4cGVjdGluZyB0aGUgbnVtYmVyIHRvIGJlIGRpYWxlZCBmcm9tLgogICAqICAgICAgICAgICAgTm90ZSB0aGlzIGlzIGRpZmZlcmVudCBmcm9tIHRoZSBjb3VudHJ5IHdoZXJlIHRoZSBudW1iZXIgYmVsb25ncy4KICAgKiAgICAgICAgICAgIEZvciBleGFtcGxlLCB0aGUgbnVtYmVyICsxIDY1MCAyNTMgMDAwMCBpcyBhIG51bWJlciB0aGF0IGJlbG9uZ3MgdG8gVVMuCiAgICogICAgICAgICAgICBXaGVuIHdyaXR0ZW4gaW4gdGhpcyBmb3JtLCBpdCBjb3VsZCBiZSBkaWFsZWQgZnJvbSBhbnkgY291bnRyeS4KICAgKiAgICAgICAgICAgIFdoZW4gaXQgaXMgd3JpdHRlbiBhcyAwMCAxIDY1MCAyNTMgMDAwMCwgaXQgY291bGQgYmUgZGlhbGVkIGZyb20KICAgKiAgICAgICAgICAgIGFueSBjb3VudHJ5IHdoaWNoIGhhcyBpbnRlcm5hdGlvbmFsIHByZWZpeCAwMC4gV2hlbiBpdCBpcyB3cml0dGVuIGFzCiAgICogICAgICAgICAgICA2NTAgMjUzIDAwMDAsIGl0IGNvdWxkIG9ubHkgYmUgZGlhbGVkIGZyb20gVVMsIGFuZCB3aGVuIHdyaXR0ZW4gYXMKICAgKiAgICAgICAgICAgIDI1MyAwMDAwLCBpdCBjb3VsZCBvbmx5IGJlIGRpYWxlZCBmcm9tIFVTIChNb3VudGFpbiBWaWV3LCBDQSwgdG8gYmUKICAgKiAgICAgICAgICAgIG1vcmUgc3BlY2lmaWMpLgogICAqIEByZXR1cm4gIHRydWUgaWYgdGhlIG51bWJlciBpcyBwb3NzaWJsZQogICAqLwogIHB1YmxpYyBib29sZWFuIGlzUG9zc2libGVOdW1iZXIoU3RyaW5nIG51bWJlciwgU3RyaW5nIGNvdW50cnlEaWFsaW5nRnJvbSkgewogICAgdHJ5IHsKICAgICAgcmV0dXJuIGlzUG9zc2libGVOdW1iZXIocGFyc2UobnVtYmVyLCBjb3VudHJ5RGlhbGluZ0Zyb20pKTsKICAgIH0gY2F0Y2ggKE51bWJlclBhcnNlRXhjZXB0aW9uIGUpIHsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogIH0KCiAgLyoqCiAgICogR2V0cyBhbiBBc1lvdVR5cGVGb3JtYXR0ZXIgZm9yIHRoZSBzcGVjaWZpYyBjb3VudHJ5LiBOb3RlIHRoaXMgZnVuY3Rpb24gZG9lc24ndCBhdHRlbXB0IHRvCiAgICogZmlndXJlIG91dCB0aGUgdHlwZXMgb2YgcGhvbmUgbnVtYmVyIGJlaW5nIGVudGVyZWQgb24gdGhlIGZseSBkdWUgdG8gcGVyZm9ybWFuY2UgcmVhc29ucy4KICAgKiBJbnN0ZWFkLCBpdCB0cmllcyB0byBhcHBseSBhIHN0YW5kYXJkIGZvcm1hdCB0byBhbGwgdHlwZXMgb2YgcGhvbmUgbnVtYmVycy4gRm9yIGNvdW50cmllcwogICAqIHdoZXJlIGRpZmZlcmVudCB0eXBlcyBvZiBwaG9uZSBudW1iZXJzIGZvbGxvdyBkaWZmZXJlbnQgZm9ybWF0cywgdGhlIGZvcm1hdHRlciByZXR1cm5lZAogICAqIHdpbGwgZG8gbm8gZm9ybWF0dGluZyBidXQgb3V0cHV0IGV4YWN0bHkgd2hhdCBpcyBmZWQgaW50byB0aGUgaW5wdXREaWdpdCBtZXRob2QuCiAgICoKICAgKiBJZiB0aGUgdHlwZSBvZiB0aGUgcGhvbmUgbnVtYmVyIGJlaW5nIGVudGVyZWQgaXMga25vd24gYmVmb3JlaGFuZCwgdXNlCiAgICogZ2V0QXNZb3VUeXBlRm9ybWF0dGVyQnlUeXBlIGluc3RlYWQuCiAgICoKICAgKiBAcGFyYW0gcmVnaW9uQ29kZSAgdGhlIElTTyAzMTY2LTEgdHdvLWxldHRlciBjb3VudHJ5IGNvZGUgdGhhdCBkZW5vdGVzIHRoZSBjb3VudHJ5L3JlZ2lvbgogICAqICAgICAgICAgICAgICAgICAgICB3aGVyZSB0aGUgcGhvbmUgbnVtYmVyIGlzIGJlaW5nIGVudGVyZWQKICAgKiBAcmV0dXJuICBhbiBBc1lvdVR5cGVGb3JtYXR0ZXIgb2JqZWN0LCB3aGljaCBjb3VsZCBiZSB1c2VkIHRvIGZvcm1hdCBwaG9uZSBudW1iZXJzIGluIHRoZQogICAqICAgICBzcGVjaWZpYyBjb3VudHJ5ICJhcyB5b3UgdHlwZSIKICAgKi8KICBwdWJsaWMgQXNZb3VUeXBlRm9ybWF0dGVyIGdldEFzWW91VHlwZUZvcm1hdHRlcihTdHJpbmcgcmVnaW9uQ29kZSkgewogICAgcmV0dXJuIG5ldyBBc1lvdVR5cGVGb3JtYXR0ZXIocmVnaW9uQ29kZSk7CiAgfQoKICAvLyBFeHRyYWN0cyBjb3VudHJ5IGNvZGUgZnJvbSBmdWxsTnVtYmVyLCByZXR1cm5zIGl0IGFuZCBwbGFjZXMgdGhlIHJlbWFpbmluZyBudW1iZXIgaW4KICAvLyBuYXRpb25hbE51bWJlci4gSXQgYXNzdW1lcyB0aGF0IHRoZSBsZWFkaW5nIHBsdXMgc2lnbiBvciBJREQgaGFzIGFscmVhZHkgYmVlbiByZW1vdmVkLiBSZXR1cm5zCiAgLy8gMCBpZiBmdWxsTnVtYmVyIGRvZXNuJ3Qgc3RhcnQgd2l0aCBhIHZhbGlkIGNvdW50cnkgY29kZSwgYW5kIGxlYXZlcyBuYXRpb25hbE51bWJlciB1bm1vZGlmaWVkLgogIGludCBleHRyYWN0Q291bnRyeUNvZGUoU3RyaW5nQnVmZmVyIGZ1bGxOdW1iZXIsIFN0cmluZ0J1ZmZlciBuYXRpb25hbE51bWJlcikgewogICAgaW50IHBvdGVudGlhbENvdW50cnlDb2RlOwogICAgZm9yIChpbnQgaSA9IDE7IGkgPD0gMzsgaSsrKSB7CiAgICAgIHBvdGVudGlhbENvdW50cnlDb2RlID0gSW50ZWdlci5wYXJzZUludChmdWxsTnVtYmVyLnN1YnN0cmluZygwLCBpKSk7CiAgICAgIGlmIChjb3VudHJ5Q29kZVRvUmVnaW9uQ29kZU1hcC5jb250YWluc0tleShwb3RlbnRpYWxDb3VudHJ5Q29kZSkpIHsKICAgICAgICBuYXRpb25hbE51bWJlci5hcHBlbmQoZnVsbE51bWJlci5zdWJzdHJpbmcoaSkpOwogICAgICAgIHJldHVybiBwb3RlbnRpYWxDb3VudHJ5Q29kZTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIDA7CiAgfQoKICAvKioKICAgKiBUcmllcyB0byBleHRyYWN0IGEgY291bnRyeSBjb2RlIGZyb20gYSBudW1iZXIuIFRoaXMgbWV0aG9kIHdpbGwgcmV0dXJuIHplcm8gaWYgbm8gY291bnRyeSBjb2RlCiAgICogaXMgY29uc2lkZXJlZCB0byBiZSBwcmVzZW50LiBDb3VudHJ5IGNvZGVzIGFyZSBleHRyYWN0ZWQgaW4gdGhlIGZvbGxvd2luZyB3YXlzOgogICAqICAgICAtIGJ5IHN0cmlwcGluZyB0aGUgaW50ZXJuYXRpb25hbCBkaWFsaW5nIHByZWZpeCBvZiB0aGUgY291bnRyeSB0aGUgcGVyc29uIGlzIGRpYWxpbmcgZnJvbSwKICAgKiAgICAgICBpZiB0aGlzIGlzIHByZXNlbnQgaW4gdGhlIG51bWJlciwgYW5kIGxvb2tpbmcgYXQgdGhlIG5leHQgZGlnaXRzCiAgICogICAgIC0gYnkgc3RyaXBwaW5nIHRoZSAnKycgc2lnbiBpZiBwcmVzZW50IGFuZCB0aGVuIGxvb2tpbmcgYXQgdGhlIG5leHQgZGlnaXRzCiAgICogICAgIC0gYnkgY29tcGFyaW5nIHRoZSBzdGFydCBvZiB0aGUgbnVtYmVyIGFuZCB0aGUgY291bnRyeSBjb2RlIG9mIHRoZSBkZWZhdWx0IHJlZ2lvbi4gSWYgdGhlCiAgICogICAgICAgbnVtYmVyIGlzIG5vdCBjb25zaWRlcmVkIHBvc3NpYmxlIGZvciB0aGUgbnVtYmVyaW5nIHBsYW4gb2YgdGhlIGRlZmF1bHQgcmVnaW9uIGluaXRpYWxseSwKICAgKiAgICAgICBidXQgc3RhcnRzIHdpdGggdGhlIGNvdW50cnkgY29kZSBvZiB0aGlzIHJlZ2lvbiwgdmFsaWRhdGlvbiB3aWxsIGJlIHJlYXR0ZW1wdGVkIGFmdGVyCiAgICogICAgICAgc3RyaXBwaW5nIHRoaXMgY291bnRyeSBjb2RlLiBJZiB0aGlzIG51bWJlciBpcyBjb25zaWRlcmVkIGEgcG9zc2libGUgbnVtYmVyLCB0aGVuIHRoZQogICAqICAgICAgIGZpcnN0IGRpZ2l0cyB3aWxsIGJlIGNvbnNpZGVyZWQgdGhlIGNvdW50cnkgY29kZSBhbmQgcmVtb3ZlZCBhcyBzdWNoLgogICAqCiAgICogSXQgd2lsbCB0aHJvdyBhIE51bWJlclBhcnNlRXhjZXB0aW9uIGlmIHRoZSBudW1iZXIgc3RhcnRzIHdpdGggYSAnKycgYnV0IHRoZSBjb3VudHJ5IGNvZGUKICAgKiBzdXBwbGllZCBhZnRlciB0aGlzIGRvZXMgbm90IG1hdGNoIHRoYXQgb2YgYW55IGtub3duIGNvdW50cnkuCiAgICoKICAgKiBAcGFyYW0gbnVtYmVyICBub24tbm9ybWFsaXplZCB0ZWxlcGhvbmUgbnVtYmVyIHRoYXQgd2Ugd2lzaCB0byBleHRyYWN0IGEgY291bnRyeQogICAqICAgICBjb2RlIGZyb20gLSBtYXkgYmVnaW4gd2l0aCAnKycKICAgKiBAcGFyYW0gZGVmYXVsdFJlZ2lvbk1ldGFkYXRhICBtZXRhZGF0YSBhYm91dCB0aGUgcmVnaW9uIHRoaXMgbnVtYmVyIG1heSBiZSBmcm9tCiAgICogQHBhcmFtIG5hdGlvbmFsTnVtYmVyICBhIHN0cmluZyBidWZmZXIgdG8gc3RvcmUgdGhlIG5hdGlvbmFsIHNpZ25pZmljYW50IG51bWJlciBpbiwgaW4gdGhlIGNhc2UKICAgKiAgICAgdGhhdCBhIGNvdW50cnkgY29kZSB3YXMgZXh0cmFjdGVkLiBUaGUgbnVtYmVyIGlzIGFwcGVuZGVkIHRvIGFueSBleGlzdGluZyBjb250ZW50cy4gSWYgbm8KICAgKiAgICAgY291bnRyeSBjb2RlIHdhcyBleHRyYWN0ZWQsIHRoaXMgd2lsbCBiZSBsZWZ0IHVuY2hhbmdlZC4KICAgKiBAcGFyYW0gc3RvcmVDb3VudHJ5Q29kZVNvdXJjZSAgdHJ1ZSBpZiB0aGUgY291bnRyeV9jb2RlX3NvdXJjZSBmaWVsZCBvZiBwaG9uZU51bWJlciBzaG91bGQgYmUKICAgKiAgICAgcG9wdWxhdGVkLgogICAqIEBwYXJhbSBwaG9uZU51bWJlciAgdGhlIFBob25lTnVtYmVyIG9iamVjdCB0aGF0IG5lZWRzIHRvIGJlIHBvcHVsYXRlZCB3aXRoIGNvdW50cnkgY29kZQogICAqICAgICBhbmQgY291bnRyeSBjb2RlIHNvdXJjZS4gTm90ZSB0aGUgY291bnRyeSBjb2RlIGlzIGFsd2F5cyBwb3B1bGF0ZWQsIHdoZXJlYXMgY291bnRyeSBjb2RlCiAgICogICAgIHNvdXJjZSBpcyBvbmx5IHBvcHVsYXRlZCB3aGVuIGtlZXBDb3VudHJ5Q29kZVNvdXJjZSBpcyB0cnVlLgogICAqIEByZXR1cm4gIHRoZSBjb3VudHJ5IGNvZGUgZXh0cmFjdGVkIG9yIDAgaWYgbm9uZSBjb3VsZCBiZSBleHRyYWN0ZWQKICAgKi8KICBpbnQgbWF5YmVFeHRyYWN0Q291bnRyeUNvZGUoU3RyaW5nIG51bWJlciwgUGhvbmVNZXRhZGF0YSBkZWZhdWx0UmVnaW9uTWV0YWRhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFN0cmluZ0J1ZmZlciBuYXRpb25hbE51bWJlciwgYm9vbGVhbiBzdG9yZUNvdW50cnlDb2RlU291cmNlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBQaG9uZU51bWJlciBwaG9uZU51bWJlcikKICAgICAgdGhyb3dzIE51bWJlclBhcnNlRXhjZXB0aW9uIHsKICAgIGlmIChudW1iZXIubGVuZ3RoKCkgPT0gMCkgewogICAgICByZXR1cm4gMDsKICAgIH0KICAgIFN0cmluZ0J1ZmZlciBmdWxsTnVtYmVyID0gbmV3IFN0cmluZ0J1ZmZlcihudW1iZXIpOwogICAgLy8gU2V0IHRoZSBkZWZhdWx0IHByZWZpeCB0byBiZSBzb21ldGhpbmcgdGhhdCB3aWxsIG5ldmVyIG1hdGNoLgogICAgU3RyaW5nIHBvc3NpYmxlQ291bnRyeUlkZFByZWZpeCA9ICJOb25NYXRjaCI7CiAgICBpZiAoZGVmYXVsdFJlZ2lvbk1ldGFkYXRhICE9IG51bGwpIHsKICAgICAgcG9zc2libGVDb3VudHJ5SWRkUHJlZml4ID0gZGVmYXVsdFJlZ2lvbk1ldGFkYXRhLmdldEludGVybmF0aW9uYWxQcmVmaXgoKTsKICAgIH0KCiAgICBDb3VudHJ5Q29kZVNvdXJjZSBjb3VudHJ5Q29kZVNvdXJjZSA9CiAgICAgICAgbWF5YmVTdHJpcEludGVybmF0aW9uYWxQcmVmaXhBbmROb3JtYWxpemUoZnVsbE51bWJlciwgcG9zc2libGVDb3VudHJ5SWRkUHJlZml4KTsKICAgIGlmIChzdG9yZUNvdW50cnlDb2RlU291cmNlKSB7CiAgICAgIHBob25lTnVtYmVyLnNldENvdW50cnlDb2RlU291cmNlKGNvdW50cnlDb2RlU291cmNlKTsKICAgIH0KICAgIGlmIChjb3VudHJ5Q29kZVNvdXJjZSAhPSBDb3VudHJ5Q29kZVNvdXJjZS5GUk9NX0RFRkFVTFRfQ09VTlRSWSkgewogICAgICBpZiAoZnVsbE51bWJlci5sZW5ndGgoKSA8IE1JTl9MRU5HVEhfRk9SX05TTikgewogICAgICAgIHRocm93IG5ldyBOdW1iZXJQYXJzZUV4Y2VwdGlvbihOdW1iZXJQYXJzZUV4Y2VwdGlvbi5FcnJvclR5cGUuVE9PX1NIT1JUX0FGVEVSX0lERCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlBob25lIG51bWJlciBoYWQgYW4gSURELCBidXQgYWZ0ZXIgdGhpcyB3YXMgbm90ICIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKyAibG9uZyBlbm91Z2ggdG8gYmUgYSB2aWFibGUgcGhvbmUgbnVtYmVyLiIpOwogICAgICB9CiAgICAgIGludCBwb3RlbnRpYWxDb3VudHJ5Q29kZSA9IGV4dHJhY3RDb3VudHJ5Q29kZShmdWxsTnVtYmVyLCBuYXRpb25hbE51bWJlcik7CiAgICAgIGlmIChwb3RlbnRpYWxDb3VudHJ5Q29kZSAhPSAwKSB7CiAgICAgICAgcGhvbmVOdW1iZXIuc2V0Q291bnRyeUNvZGUocG90ZW50aWFsQ291bnRyeUNvZGUpOwogICAgICAgIHJldHVybiBwb3RlbnRpYWxDb3VudHJ5Q29kZTsKICAgICAgfQoKICAgICAgLy8gSWYgdGhpcyBmYWlscywgdGhleSBtdXN0IGJlIHVzaW5nIGEgc3RyYW5nZSBjb3VudHJ5IGNvZGUgdGhhdCB3ZSBkb24ndCByZWNvZ25pemUsIG9yCiAgICAgIC8vIHRoYXQgZG9lc24ndCBleGlzdC4KICAgICAgdGhyb3cgbmV3IE51bWJlclBhcnNlRXhjZXB0aW9uKE51bWJlclBhcnNlRXhjZXB0aW9uLkVycm9yVHlwZS5JTlZBTElEX0NPVU5UUllfQ09ERSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDb3VudHJ5IGNvZGUgc3VwcGxpZWQgd2FzIG5vdCByZWNvZ25pc2VkLiIpOwogICAgfSBlbHNlIGlmIChkZWZhdWx0UmVnaW9uTWV0YWRhdGEgIT0gbnVsbCkgewogICAgICAvLyBDaGVjayB0byBzZWUgaWYgdGhlIG51bWJlciBpcyB2YWxpZCBmb3IgdGhlIGRlZmF1bHQgcmVnaW9uIGFscmVhZHkuIElmIG5vdCwgd2UgY2hlY2sgdG8KICAgICAgLy8gc2VlIGlmIHRoZSBjb3VudHJ5IGNvZGUgZm9yIHRoZSBkZWZhdWx0IHJlZ2lvbiBpcyBwcmVzZW50IGF0IHRoZSBzdGFydCBvZiB0aGUgbnVtYmVyLgogICAgICBQYXR0ZXJuIHZhbGlkTnVtYmVyUGF0dGVybiA9CiAgICAgICAgICByZWdleENhY2hlLmdldFBhdHRlcm5Gb3JSZWdleChkZWZhdWx0UmVnaW9uTWV0YWRhdGEuZ2V0R2VuZXJhbERlc2MoKQogICAgICAgICAgICAgIC5nZXROYXRpb25hbE51bWJlclBhdHRlcm4oKSk7CiAgICAgIGlmICghdmFsaWROdW1iZXJQYXR0ZXJuLm1hdGNoZXIoZnVsbE51bWJlcikubWF0Y2hlcygpKSB7CiAgICAgICAgaW50IGRlZmF1bHRDb3VudHJ5Q29kZSA9IGRlZmF1bHRSZWdpb25NZXRhZGF0YS5nZXRDb3VudHJ5Q29kZSgpOwogICAgICAgIFN0cmluZyBkZWZhdWx0Q291bnRyeUNvZGVTdHJpbmcgPSBTdHJpbmcudmFsdWVPZihkZWZhdWx0Q291bnRyeUNvZGUpOwogICAgICAgIFN0cmluZyBub3JtYWxpemVkTnVtYmVyID0gZnVsbE51bWJlci50b1N0cmluZygpOwogICAgICAgIGlmIChub3JtYWxpemVkTnVtYmVyLnN0YXJ0c1dpdGgoZGVmYXVsdENvdW50cnlDb2RlU3RyaW5nKSkgewogICAgICAgICAgLy8gSWYgc28sIHN0cmlwIHRoaXMsIGFuZCBzZWUgaWYgdGhlIHJlc3VsdGFudCBudW1iZXIgaXMgdmFsaWQuCiAgICAgICAgICBTdHJpbmdCdWZmZXIgcG90ZW50aWFsTmF0aW9uYWxOdW1iZXIgPQogICAgICAgICAgICAgIG5ldyBTdHJpbmdCdWZmZXIobm9ybWFsaXplZE51bWJlci5zdWJzdHJpbmcoZGVmYXVsdENvdW50cnlDb2RlU3RyaW5nLmxlbmd0aCgpKSk7CiAgICAgICAgICBtYXliZVN0cmlwTmF0aW9uYWxQcmVmaXgoCiAgICAgICAgICAgICAgcG90ZW50aWFsTmF0aW9uYWxOdW1iZXIsCiAgICAgICAgICAgICAgZGVmYXVsdFJlZ2lvbk1ldGFkYXRhLmdldE5hdGlvbmFsUHJlZml4Rm9yUGFyc2luZygpLAogICAgICAgICAgICAgIGRlZmF1bHRSZWdpb25NZXRhZGF0YS5nZXROYXRpb25hbFByZWZpeFRyYW5zZm9ybVJ1bGUoKSwKICAgICAgICAgICAgICB2YWxpZE51bWJlclBhdHRlcm4pOwogICAgICAgICAgaWYgKHZhbGlkTnVtYmVyUGF0dGVybi5tYXRjaGVyKHBvdGVudGlhbE5hdGlvbmFsTnVtYmVyKS5tYXRjaGVzKCkpIHsKICAgICAgICAgICAgbmF0aW9uYWxOdW1iZXIuYXBwZW5kKHBvdGVudGlhbE5hdGlvbmFsTnVtYmVyKTsKICAgICAgICAgICAgaWYgKHN0b3JlQ291bnRyeUNvZGVTb3VyY2UpIHsKICAgICAgICAgICAgICBwaG9uZU51bWJlci5zZXRDb3VudHJ5Q29kZVNvdXJjZShDb3VudHJ5Q29kZVNvdXJjZS5GUk9NX05VTUJFUl9XSVRIT1VUX1BMVVNfU0lHTik7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcGhvbmVOdW1iZXIuc2V0Q291bnRyeUNvZGUoZGVmYXVsdENvdW50cnlDb2RlKTsKICAgICAgICAgICAgcmV0dXJuIGRlZmF1bHRDb3VudHJ5Q29kZTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIC8vIE5vIGNvdW50cnkgY29kZSBwcmVzZW50LgogICAgcGhvbmVOdW1iZXIuc2V0Q291bnRyeUNvZGUoMCk7CiAgICByZXR1cm4gMDsKICB9CgogIC8qKgogICAqIFN0cmlwcyB0aGUgSUREIGZyb20gdGhlIHN0YXJ0IG9mIHRoZSBudW1iZXIgaWYgcHJlc2VudC4gSGVscGVyIGZ1bmN0aW9uIHVzZWQgYnkKICAgKiBtYXliZVN0cmlwSW50ZXJuYXRpb25hbFByZWZpeEFuZE5vcm1hbGl6ZS4KICAgKi8KICBwcml2YXRlIGJvb2xlYW4gcGFyc2VQcmVmaXhBc0lkZChQYXR0ZXJuIGlkZFBhdHRlcm4sIFN0cmluZ0J1ZmZlciBudW1iZXIpIHsKICAgIE1hdGNoZXIgbSA9IGlkZFBhdHRlcm4ubWF0Y2hlcihudW1iZXIpOwogICAgaWYgKG0ubG9va2luZ0F0KCkpIHsKICAgICAgaW50IG1hdGNoRW5kID0gbS5lbmQoKTsKICAgICAgLy8gT25seSBzdHJpcCB0aGlzIGlmIHRoZSBmaXJzdCBkaWdpdCBhZnRlciB0aGUgbWF0Y2ggaXMgbm90IGEgMCwgc2luY2UgY291bnRyeSBjb2RlcyBjYW5ub3QKICAgICAgLy8gYmVnaW4gd2l0aCAwLgogICAgICBNYXRjaGVyIGRpZ2l0TWF0Y2hlciA9IENBUFRVUklOR19ESUdJVF9QQVRURVJOLm1hdGNoZXIobnVtYmVyLnN1YnN0cmluZyhtYXRjaEVuZCkpOwogICAgICBpZiAoZGlnaXRNYXRjaGVyLmZpbmQoKSkgewogICAgICAgIFN0cmluZyBub3JtYWxpemVkR3JvdXAgPSBub3JtYWxpemVIZWxwZXIoZGlnaXRNYXRjaGVyLmdyb3VwKDEpLCBESUdJVF9NQVBQSU5HUywgdHJ1ZSk7CiAgICAgICAgaWYgKG5vcm1hbGl6ZWRHcm91cC5lcXVhbHMoIjAiKSkgewogICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIH0KICAgICAgfQogICAgICBudW1iZXIuZGVsZXRlKDAsIG1hdGNoRW5kKTsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CiAgICByZXR1cm4gZmFsc2U7CiAgfQoKICAvKioKICAgKiBTdHJpcHMgYW55IGludGVybmF0aW9uYWwgcHJlZml4IChzdWNoIGFzICssIDAwLCAwMTEpIHByZXNlbnQgaW4gdGhlIG51bWJlciBwcm92aWRlZCwgbm9ybWFsaXplcwogICAqICAgICB0aGUgcmVzdWx0aW5nIG51bWJlciwgYW5kIGluZGljYXRlcyBpZiBhbiBpbnRlcm5hdGlvbmFsIHByZWZpeCB3YXMgcHJlc2VudC4KICAgKgogICAqIEBwYXJhbSBudW1iZXIgIHRoZSBub24tbm9ybWFsaXplZCB0ZWxlcGhvbmUgbnVtYmVyIHRoYXQgd2Ugd2lzaCB0byBzdHJpcCBhbnkgaW50ZXJuYXRpb25hbAogICAqICAgICBkaWFsaW5nIHByZWZpeCBmcm9tCiAgICogQHBhcmFtIHBvc3NpYmxlSWRkUHJlZml4ICB0aGUgaW50ZXJuYXRpb25hbCBkaXJlY3QgZGlhbGluZyBwcmVmaXggZnJvbSB0aGUgY291bnRyeSB3ZQogICAqICAgICB0aGluayB0aGlzIG51bWJlciBtYXkgYmUgZGlhbGVkIGluCiAgICogQHJldHVybiAgdGhlIGNvcnJlc3BvbmRpbmcgQ291bnRyeUNvZGVTb3VyY2UgaWYgYW4gaW50ZXJuYXRpb25hbCBkaWFsaW5nIHByZWZpeCBjb3VsZCBiZQogICAqICAgICByZW1vdmVkIGZyb20gdGhlIG51bWJlciwgb3RoZXJ3aXNlIENvdW50cnlDb2RlU291cmNlLkZST01fREVGQVVMVF9DT1VOVFJZIGlmIHRoZSBudW1iZXIKICAgKiAgICAgZGlkIG5vdCBzZWVtIHRvIGJlIGluIGludGVybmF0aW9uYWwgZm9ybWF0LgogICAqLwogIENvdW50cnlDb2RlU291cmNlIG1heWJlU3RyaXBJbnRlcm5hdGlvbmFsUHJlZml4QW5kTm9ybWFsaXplKAogICAgICBTdHJpbmdCdWZmZXIgbnVtYmVyLAogICAgICBTdHJpbmcgcG9zc2libGVJZGRQcmVmaXgpIHsKICAgIGlmIChudW1iZXIubGVuZ3RoKCkgPT0gMCkgewogICAgICByZXR1cm4gQ291bnRyeUNvZGVTb3VyY2UuRlJPTV9ERUZBVUxUX0NPVU5UUlk7CiAgICB9CiAgICBpZiAobnVtYmVyLmNoYXJBdCgwKSA9PSBQTFVTX1NJR04pIHsKICAgICAgbnVtYmVyLmRlbGV0ZUNoYXJBdCgwKTsKICAgICAgLy8gQ2FuIG5vdyBub3JtYWxpemUgdGhlIHJlc3Qgb2YgdGhlIG51bWJlciBzaW5jZSB3ZSd2ZSBjb25zdW1lZCB0aGUgIisiIHNpZ24gYXQgdGhlIHN0YXJ0LgogICAgICBub3JtYWxpemUobnVtYmVyKTsKICAgICAgcmV0dXJuIENvdW50cnlDb2RlU291cmNlLkZST01fTlVNQkVSX1dJVEhfUExVU19TSUdOOwogICAgfQogICAgLy8gQXR0ZW1wdCB0byBwYXJzZSB0aGUgZmlyc3QgZGlnaXRzIGFzIGFuIGludGVybmF0aW9uYWwgcHJlZml4LgogICAgUGF0dGVybiBpZGRQYXR0ZXJuID0gcmVnZXhDYWNoZS5nZXRQYXR0ZXJuRm9yUmVnZXgocG9zc2libGVJZGRQcmVmaXgpOwogICAgaWYgKHBhcnNlUHJlZml4QXNJZGQoaWRkUGF0dGVybiwgbnVtYmVyKSkgewogICAgICBub3JtYWxpemUobnVtYmVyKTsKICAgICAgcmV0dXJuIENvdW50cnlDb2RlU291cmNlLkZST01fTlVNQkVSX1dJVEhfSUREOwogICAgfQogICAgLy8gSWYgc3RpbGwgbm90IGZvdW5kLCB0aGVuIHRyeSBhbmQgbm9ybWFsaXplIHRoZSBudW1iZXIgYW5kIHRoZW4gdHJ5IGFnYWluLiBUaGlzIHNob3VsZG4ndCBiZQogICAgLy8gZG9uZSBiZWZvcmUsIHNpbmNlIG5vbi1udW1lcmljIGNoYXJhY3RlcnMgKCsgYW5kIH4pIG1heSBsZWdhbGx5IGJlIGluIHRoZSBpbnRlcm5hdGlvbmFsCiAgICAvLyBwcmVmaXguCiAgICBub3JtYWxpemUobnVtYmVyKTsKICAgIHJldHVybiBwYXJzZVByZWZpeEFzSWRkKGlkZFBhdHRlcm4sIG51bWJlcikKICAgICAgICA/IENvdW50cnlDb2RlU291cmNlLkZST01fTlVNQkVSX1dJVEhfSURECiAgICAgICAgOiBDb3VudHJ5Q29kZVNvdXJjZS5GUk9NX0RFRkFVTFRfQ09VTlRSWTsKICB9CgogIC8qKgogICAqIFN0cmlwcyBhbnkgbmF0aW9uYWwgcHJlZml4IChzdWNoIGFzIDAsIDEpIHByZXNlbnQgaW4gdGhlIG51bWJlciBwcm92aWRlZC4KICAgKgogICAqIEBwYXJhbSBudW1iZXIgIHRoZSBub3JtYWxpemVkIHRlbGVwaG9uZSBudW1iZXIgdGhhdCB3ZSB3aXNoIHRvIHN0cmlwIGFueSBuYXRpb25hbAogICAqICAgICBkaWFsaW5nIHByZWZpeCBmcm9tCiAgICogQHBhcmFtIHBvc3NpYmxlTmF0aW9uYWxQcmVmaXggIGEgcmVnZXggdGhhdCByZXByZXNlbnRzIHRoZSBuYXRpb25hbCBkaXJlY3QgZGlhbGluZyBwcmVmaXgKICAgKiAgICAgZnJvbSB0aGUgY291bnRyeSB3ZSB0aGluayB0aGlzIG51bWJlciBtYXkgYmUgZGlhbGVkIGluCiAgICogQHBhcmFtIHRyYW5zZm9ybVJ1bGUgIHRoZSBzdHJpbmcgdGhhdCBzcGVjaWZpZXMgaG93IG51bWJlciBzaG91bGQgYmUgdHJhbnNmb3JtZWQgYWNjb3JkaW5nCiAgICogICAgIHRvIHRoZSByZWdleCBzcGVjaWZpZWQgaW4gcG9zc2libGVOYXRpb25hbFByZWZpeAogICAqIEBwYXJhbSBuYXRpb25hbE51bWJlclJ1bGUgIGEgcmVndWxhciBleHByZXNzaW9uIHRoYXQgc3BlY2lmaWVzIHdoYXQgYSB2YWxpZCBwaG9uZW51bWJlciBmcm9tCiAgICogICAgIHRoaXMgcmVnaW9uIHNob3VsZCBsb29rIGxpa2UgYWZ0ZXIgYW55IG5hdGlvbmFsIHByZWZpeCB3YXMgc3RyaXBwZWQgb3IgdHJhbnNmb3JtZWQKICAgKi8KICB2b2lkIG1heWJlU3RyaXBOYXRpb25hbFByZWZpeChTdHJpbmdCdWZmZXIgbnVtYmVyLCBTdHJpbmcgcG9zc2libGVOYXRpb25hbFByZWZpeCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTdHJpbmcgdHJhbnNmb3JtUnVsZSwgUGF0dGVybiBuYXRpb25hbE51bWJlclJ1bGUpIHsKICAgIGludCBudW1iZXJMZW5ndGggPSBudW1iZXIubGVuZ3RoKCk7CiAgICBpZiAobnVtYmVyTGVuZ3RoID09IDAgfHwgcG9zc2libGVOYXRpb25hbFByZWZpeC5sZW5ndGgoKSA9PSAwKSB7CiAgICAgIC8vIEVhcmx5IHJldHVybiBmb3IgbnVtYmVycyBvZiB6ZXJvIGxlbmd0aC4KICAgICAgcmV0dXJuOwogICAgfQogICAgLy8gQXR0ZW1wdCB0byBwYXJzZSB0aGUgZmlyc3QgZGlnaXRzIGFzIGEgbmF0aW9uYWwgcHJlZml4LgogICAgTWF0Y2hlciBtID0gcmVnZXhDYWNoZS5nZXRQYXR0ZXJuRm9yUmVnZXgocG9zc2libGVOYXRpb25hbFByZWZpeCkubWF0Y2hlcihudW1iZXIpOwogICAgaWYgKG0ubG9va2luZ0F0KCkpIHsKICAgICAgLy8gbS5ncm91cCgxKSA9PSBudWxsIGltcGxpZXMgbm90aGluZyB3YXMgY2FwdHVyZWQgYnkgdGhlIGNhcHR1cmluZyBncm91cHMgaW4KICAgICAgLy8gcG9zc2libGVOYXRpb25hbFByZWZpeDsgdGhlcmVmb3JlLCBubyB0cmFuc2Zvcm1hdGlvbiBpcyBuZWNlc3NhcnksIGFuZCB3ZQogICAgICAvLyBqdXN0IHJlbW92ZSB0aGUgbmF0aW9uYWwgcHJlZml4LgogICAgICBpZiAodHJhbnNmb3JtUnVsZSA9PSBudWxsIHx8IHRyYW5zZm9ybVJ1bGUubGVuZ3RoKCkgPT0gMCB8fCBtLmdyb3VwKDEpID09IG51bGwpIHsKICAgICAgICAvLyBDaGVjayB0aGF0IHRoZSByZXN1bHRhbnQgbnVtYmVyIGlzIHZpYWJsZS4gSWYgbm90LCByZXR1cm4uCiAgICAgICAgTWF0Y2hlciBuYXRpb25hbE51bWJlciA9IG5hdGlvbmFsTnVtYmVyUnVsZS5tYXRjaGVyKG51bWJlci5zdWJzdHJpbmcobS5lbmQoKSkpOwogICAgICAgIGlmICghbmF0aW9uYWxOdW1iZXIubWF0Y2hlcygpKSB7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQogICAgICAgIG51bWJlci5kZWxldGUoMCwgbS5lbmQoKSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgLy8gQ2hlY2sgdGhhdCB0aGUgcmVzdWx0YW50IG51bWJlciBpcyB2aWFibGUuIElmIG5vdCwgcmV0dXJuLiBDaGVjayB0aGlzIGJ5IGNvcHlpbmcgdGhlCiAgICAgICAgLy8gc3RyaW5nIGJ1ZmZlciBhbmQgbWFraW5nIHRoZSB0cmFuc2Zvcm1hdGlvbiBvbiB0aGUgY29weSBmaXJzdC4KICAgICAgICBTdHJpbmdCdWZmZXIgdHJhbnNmb3JtZWROdW1iZXIgPSBuZXcgU3RyaW5nQnVmZmVyKG51bWJlcik7CiAgICAgICAgdHJhbnNmb3JtZWROdW1iZXIucmVwbGFjZSgwLCBudW1iZXJMZW5ndGgsIG0ucmVwbGFjZUZpcnN0KHRyYW5zZm9ybVJ1bGUpKTsKICAgICAgICBNYXRjaGVyIG5hdGlvbmFsTnVtYmVyID0gbmF0aW9uYWxOdW1iZXJSdWxlLm1hdGNoZXIodHJhbnNmb3JtZWROdW1iZXIudG9TdHJpbmcoKSk7CiAgICAgICAgaWYgKCFuYXRpb25hbE51bWJlci5tYXRjaGVzKCkpIHsKICAgICAgICAgIHJldHVybjsKICAgICAgICB9CiAgICAgICAgbnVtYmVyLnJlcGxhY2UoMCwgbnVtYmVyLmxlbmd0aCgpLCB0cmFuc2Zvcm1lZE51bWJlci50b1N0cmluZygpKTsKICAgICAgfQogICAgfQogIH0KCiAgLyoqCiAgICogU3RyaXBzIGFueSBleHRlbnNpb24gKGFzIGluLCB0aGUgcGFydCBvZiB0aGUgbnVtYmVyIGRpYWxsZWQgYWZ0ZXIgdGhlIGNhbGwgaXMgY29ubmVjdGVkLAogICAqIHVzdWFsbHkgaW5kaWNhdGVkIHdpdGggZXh0biwgZXh0LCB4IG9yIHNpbWlsYXIpIGZyb20gdGhlIGVuZCBvZiB0aGUgbnVtYmVyLCBhbmQgcmV0dXJucyBpdC4KICAgKgogICAqIEBwYXJhbSBudW1iZXIgIHRoZSBub24tbm9ybWFsaXplZCB0ZWxlcGhvbmUgbnVtYmVyIHRoYXQgd2Ugd2lzaCB0byBzdHJpcCB0aGUgZXh0ZW5zaW9uIGZyb20KICAgKiBAcmV0dXJuICAgICAgICB0aGUgcGhvbmUgZXh0ZW5zaW9uCiAgICovCiAgU3RyaW5nIG1heWJlU3RyaXBFeHRlbnNpb24oU3RyaW5nQnVmZmVyIG51bWJlcikgewogICAgTWF0Y2hlciBtID0gRVhUTl9QQVRURVJOLm1hdGNoZXIobnVtYmVyKTsKICAgIC8vIElmIHdlIGZpbmQgYSBwb3RlbnRpYWwgZXh0ZW5zaW9uLCBhbmQgdGhlIG51bWJlciBwcmVjZWRpbmcgdGhpcyBpcyBhIHZpYWJsZSBudW1iZXIsIHdlIGFzc3VtZQogICAgLy8gaXQgaXMgYW4gZXh0ZW5zaW9uLgogICAgaWYgKG0uZmluZCgpICYmIGlzVmlhYmxlUGhvbmVOdW1iZXIobnVtYmVyLnN1YnN0cmluZygwLCBtLnN0YXJ0KCkpKSkgewogICAgICAvLyBUaGUgbnVtYmVycyBhcmUgY2FwdHVyZWQgaW50byBncm91cHMgaW4gdGhlIHJlZ3VsYXIgZXhwcmVzc2lvbi4KICAgICAgZm9yIChpbnQgaSA9IDEsIGxlbmd0aCA9IG0uZ3JvdXBDb3VudCgpOyBpIDw9IGxlbmd0aDsgaSsrKSB7CiAgICAgICAgaWYgKG0uZ3JvdXAoaSkgIT0gbnVsbCkgewogICAgICAgICAgLy8gV2UgZ28gdGhyb3VnaCB0aGUgY2FwdHVyaW5nIGdyb3VwcyB1bnRpbCB3ZSBmaW5kIG9uZSB0aGF0IGNhcHR1cmVkIHNvbWUgZGlnaXRzLiBJZiBub25lCiAgICAgICAgICAvLyBkaWQsIHRoZW4gd2Ugd2lsbCByZXR1cm4gdGhlIGVtcHR5IHN0cmluZy4KICAgICAgICAgIFN0cmluZyBleHRlbnNpb24gPSBtLmdyb3VwKGkpOwogICAgICAgICAgbnVtYmVyLmRlbGV0ZShtLnN0YXJ0KCksIG51bWJlci5sZW5ndGgoKSk7CiAgICAgICAgICByZXR1cm4gZXh0ZW5zaW9uOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgcmV0dXJuICIiOwogIH0KCiAgLyoqCiAgICogUGFyc2VzIGEgc3RyaW5nIGFuZCByZXR1cm5zIGl0IGluIHByb3RvIGJ1ZmZlciBmb3JtYXQuIFRoaXMgbWV0aG9kIHdpbGwgdGhyb3cgYQogICAqIE51bWJlclBhcnNlRXhjZXB0aW9uIGV4Y2VwdGlvbiBpZiB0aGUgbnVtYmVyIGlzIG5vdCBjb25zaWRlcmVkIHRvIGJlIGEgcG9zc2libGUgbnVtYmVyLiBOb3RlCiAgICogdGhhdCB2YWxpZGF0aW9uIG9mIHdoZXRoZXIgdGhlIG51bWJlciBpcyBhY3R1YWxseSBhIHZhbGlkIG51bWJlciBmb3IgYSBwYXJ0aWN1bGFyCiAgICogY291bnRyeS9yZWdpb24gaXMgbm90IHBlcmZvcm1lZC4gVGhpcyBjYW4gYmUgZG9uZSBzZXBhcmF0ZWx5IHdpdGggaXNWYWxpZE51bWJlci4KICAgKgogICAqIEBwYXJhbSBudW1iZXJUb1BhcnNlICAgICBudW1iZXIgdGhhdCB3ZSBhcmUgYXR0ZW1wdGluZyB0byBwYXJzZS4gVGhpcyBjYW4gY29udGFpbiBmb3JtYXR0aW5nCiAgICogICAgICAgICAgICAgICAgICAgICAgICAgIHN1Y2ggYXMgKywgKCBhbmQgLSwgYXMgd2VsbCBhcyBhIHBob25lIG51bWJlciBleHRlbnNpb24uCiAgICogQHBhcmFtIGRlZmF1bHRDb3VudHJ5ICAgIHRoZSBJU08gMzE2Ni0xIHR3by1sZXR0ZXIgY291bnRyeSBjb2RlIHRoYXQgZGVub3RlcyB0aGUgY291bnRyeSB0aGF0CiAgICogICAgICAgICAgICAgICAgICAgICAgICAgIHdlIGFyZSBleHBlY3RpbmcgdGhlIG51bWJlciB0byBiZSBmcm9tLiBUaGlzIGlzIG9ubHkgdXNlZAogICAqICAgICAgICAgICAgICAgICAgICAgICAgICBpZiB0aGUgbnVtYmVyIGJlaW5nIHBhcnNlZCBpcyBub3Qgd3JpdHRlbiBpbiBpbnRlcm5hdGlvbmFsIGZvcm1hdC4KICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgVGhlIGNvdW50cnkgY29kZSBmb3IgdGhlIG51bWJlciBpbiB0aGlzIGNhc2Ugd291bGQgYmUgc3RvcmVkIGFzIHRoYXQKICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgb2YgdGhlIGRlZmF1bHQgY291bnRyeSBzdXBwbGllZC4KICAgKiBAcmV0dXJuICAgICAgICAgICAgICAgICAgYSBwaG9uZSBudW1iZXIgcHJvdG8gYnVmZmVyIGZpbGxlZCB3aXRoIHRoZSBwYXJzZWQgbnVtYmVyCiAgICogQHRocm93cyBOdW1iZXJQYXJzZUV4Y2VwdGlvbiAgaWYgdGhlIHN0cmluZyBpcyBub3QgY29uc2lkZXJlZCB0byBiZSBhIHZpYWJsZSBwaG9uZSBudW1iZXIgb3IgaWYKICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBubyBkZWZhdWx0IGNvdW50cnkgd2FzIHN1cHBsaWVkCiAgICovCiAgcHVibGljIFBob25lTnVtYmVyIHBhcnNlKFN0cmluZyBudW1iZXJUb1BhcnNlLCBTdHJpbmcgZGVmYXVsdENvdW50cnkpCiAgICAgIHRocm93cyBOdW1iZXJQYXJzZUV4Y2VwdGlvbiB7CiAgICBQaG9uZU51bWJlciBwaG9uZU51bWJlciA9IG5ldyBQaG9uZU51bWJlcigpOwogICAgcGFyc2UobnVtYmVyVG9QYXJzZSwgZGVmYXVsdENvdW50cnksIHBob25lTnVtYmVyKTsKICAgIHJldHVybiBwaG9uZU51bWJlcjsKICB9CgogIC8vIFNhbWUgYXMgcGFyc2UoU3RyaW5nLCBTdHJpbmcpLCBidXQgYWNjZXB0cyBtdXRhYmxlIFBob25lTnVtYmVyIGFzIGEgcGFyYW1ldGVyIHRvCiAgLy8gZGVjcmVhc2Ugb2JqZWN0IGNyZWF0aW9uIHdoZW4gaW52b2tlZCBtYW55IHRpbWVzLgogIHB1YmxpYyB2b2lkIHBhcnNlKFN0cmluZyBudW1iZXJUb1BhcnNlLCBTdHJpbmcgZGVmYXVsdENvdW50cnksIFBob25lTnVtYmVyIHBob25lTnVtYmVyKQogICAgICB0aHJvd3MgTnVtYmVyUGFyc2VFeGNlcHRpb24gewogICAgaWYgKCFpc1ZhbGlkUmVnaW9uQ29kZShkZWZhdWx0Q291bnRyeSkpIHsKICAgICAgaWYgKG51bWJlclRvUGFyc2UuY2hhckF0KDApICE9IFBMVVNfU0lHTikgewogICAgICAgIHRocm93IG5ldyBOdW1iZXJQYXJzZUV4Y2VwdGlvbihOdW1iZXJQYXJzZUV4Y2VwdGlvbi5FcnJvclR5cGUuSU5WQUxJRF9DT1VOVFJZX0NPREUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJNaXNzaW5nIG9yIGludmFsaWQgZGVmYXVsdCBjb3VudHJ5LiIpOwogICAgICB9CiAgICB9CiAgICBwYXJzZUhlbHBlcihudW1iZXJUb1BhcnNlLCBkZWZhdWx0Q291bnRyeSwgZmFsc2UsIHBob25lTnVtYmVyKTsKICB9CgogIC8qKgogICAqIFBhcnNlcyBhIHN0cmluZyBhbmQgcmV0dXJucyBpdCBpbiBwcm90byBidWZmZXIgZm9ybWF0LiBUaGlzIG1ldGhvZCBkaWZmZXJzIGZyb20gcGFyc2UoKSBpbiB0aGF0CiAgICogaXQgYWx3YXlzIHBvcHVsYXRlcyB0aGUgcmF3X2lucHV0IGZpZWxkIG9mIHRoZSBwcm90b2NvbCBidWZmZXIgd2l0aCBudW1iZXJUb1BhcnNlIGFzIHdlbGwgYXMKICAgKiB0aGUgY291bnRyeV9jb2RlX3NvdXJjZSBmaWVsZC4KICAgKgogICAqIEBwYXJhbSBudW1iZXJUb1BhcnNlICAgICBudW1iZXIgdGhhdCB3ZSBhcmUgYXR0ZW1wdGluZyB0byBwYXJzZS4gVGhpcyBjYW4gY29udGFpbiBmb3JtYXR0aW5nCiAgICogICAgICAgICAgICAgICAgICAgICAgICAgIHN1Y2ggYXMgKywgKCBhbmQgLSwgYXMgd2VsbCBhcyBhIHBob25lIG51bWJlciBleHRlbnNpb24uCiAgICogQHBhcmFtIGRlZmF1bHRDb3VudHJ5ICAgIHRoZSBJU08gMzE2Ni0xIHR3by1sZXR0ZXIgY291bnRyeSBjb2RlIHRoYXQgZGVub3RlcyB0aGUgY291bnRyeSB0aGF0CiAgICogICAgICAgICAgICAgICAgICAgICAgICAgIHdlIGFyZSBleHBlY3RpbmcgdGhlIG51bWJlciB0byBiZSBmcm9tLiBUaGlzIGlzIG9ubHkgdXNlZAogICAqICAgICAgICAgICAgICAgICAgICAgICAgICBpZiB0aGUgbnVtYmVyIGJlaW5nIHBhcnNlZCBpcyBub3Qgd3JpdHRlbiBpbiBpbnRlcm5hdGlvbmFsIGZvcm1hdC4KICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgVGhlIGNvdW50cnkgY29kZSBmb3IgdGhlIG51bWJlciBpbiB0aGlzIGNhc2Ugd291bGQgYmUgc3RvcmVkIGFzIHRoYXQKICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgb2YgdGhlIGRlZmF1bHQgY291bnRyeSBzdXBwbGllZC4KICAgKiBAcmV0dXJuICAgICAgICAgICAgICAgICAgYSBwaG9uZSBudW1iZXIgcHJvdG8gYnVmZmVyIGZpbGxlZCB3aXRoIHRoZSBwYXJzZWQgbnVtYmVyCiAgICogQHRocm93cyBOdW1iZXJQYXJzZUV4Y2VwdGlvbiAgaWYgdGhlIHN0cmluZyBpcyBub3QgY29uc2lkZXJlZCB0byBiZSBhIHZpYWJsZSBwaG9uZSBudW1iZXIgb3IgaWYKICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBubyBkZWZhdWx0IGNvdW50cnkgd2FzIHN1cHBsaWVkCiAgICovCiAgcHVibGljIFBob25lTnVtYmVyIHBhcnNlQW5kS2VlcFJhd0lucHV0KFN0cmluZyBudW1iZXJUb1BhcnNlLCBTdHJpbmcgZGVmYXVsdENvdW50cnkpCiAgICAgIHRocm93cyBOdW1iZXJQYXJzZUV4Y2VwdGlvbiB7CiAgICBQaG9uZU51bWJlciBwaG9uZU51bWJlciA9IG5ldyBQaG9uZU51bWJlcigpOwogICAgcGFyc2VBbmRLZWVwUmF3SW5wdXQobnVtYmVyVG9QYXJzZSwgZGVmYXVsdENvdW50cnksIHBob25lTnVtYmVyKTsKICAgIHJldHVybiBwaG9uZU51bWJlcjsKICB9CgogIC8vIFNhbWUgYXMgcGFyc2VBbmRLZWVwUmF3SW5wdXQoU3RyaW5nLCBTdHJpbmcpLCBidXQgYWNjZXB0cyBtdXRhYmxlIFBob25lTnVtYmVyIGFzIGEgcGFyYW1ldGVyIHRvCiAgLy8gZGVjcmVhc2Ugb2JqZWN0IGNyZWF0aW9uIHdoZW4gaW52b2tlZCBtYW55IHRpbWVzLgogIHB1YmxpYyB2b2lkIHBhcnNlQW5kS2VlcFJhd0lucHV0KFN0cmluZyBudW1iZXJUb1BhcnNlLCBTdHJpbmcgZGVmYXVsdENvdW50cnksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUGhvbmVOdW1iZXIgcGhvbmVOdW1iZXIpCiAgICAgIHRocm93cyBOdW1iZXJQYXJzZUV4Y2VwdGlvbiB7CiAgICBpZiAoIWlzVmFsaWRSZWdpb25Db2RlKGRlZmF1bHRDb3VudHJ5KSkgewogICAgICBpZiAobnVtYmVyVG9QYXJzZS5jaGFyQXQoMCkgIT0gUExVU19TSUdOKSB7CiAgICAgICAgdGhyb3cgbmV3IE51bWJlclBhcnNlRXhjZXB0aW9uKE51bWJlclBhcnNlRXhjZXB0aW9uLkVycm9yVHlwZS5JTlZBTElEX0NPVU5UUllfQ09ERSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk1pc3Npbmcgb3IgaW52YWxpZCBkZWZhdWx0IGNvdW50cnkuIik7CiAgICAgIH0KICAgIH0KICAgIHBhcnNlSGVscGVyKG51bWJlclRvUGFyc2UsIGRlZmF1bHRDb3VudHJ5LCB0cnVlLCBwaG9uZU51bWJlcik7CiAgfQoKCgoKICAvKioKICAgKiBQYXJzZXMgYSBzdHJpbmcgYW5kIGZpbGxzIHVwIHRoZSBwaG9uZU51bWJlci4gVGhpcyBtZXRob2QgaXMgdGhlIHNhbWUgYXMgdGhlIHB1YmxpYwogICAqIHBhcnNlKCkgbWV0aG9kLCB3aXRoIHRoZSBleGNlcHRpb24gdGhhdCBpdCBhbGxvd3MgdGhlIGRlZmF1bHQgY291bnRyeSB0byBiZSBudWxsLCBmb3IgdXNlIGJ5CiAgICogaXNOdW1iZXJNYXRjaCgpLgogICAqLwogIHByaXZhdGUgdm9pZCBwYXJzZUhlbHBlcihTdHJpbmcgbnVtYmVyVG9QYXJzZSwgU3RyaW5nIGRlZmF1bHRDb3VudHJ5LAogICAgICAgICAgICAgICAgICAgICAgICAgICBCb29sZWFuIGtlZXBSYXdJbnB1dCwgUGhvbmVOdW1iZXIgcGhvbmVOdW1iZXIpCiAgICAgIHRocm93cyBOdW1iZXJQYXJzZUV4Y2VwdGlvbiB7CiAgICAvLyBFeHRyYWN0IGEgcG9zc2libGUgbnVtYmVyIGZyb20gdGhlIHN0cmluZyBwYXNzZWQgaW4gKHRoaXMgc3RyaXBzIGxlYWRpbmcgY2hhcmFjdGVycyB0aGF0CiAgICAvLyBjb3VsZCBub3QgYmUgdGhlIHN0YXJ0IG9mIGEgcGhvbmUgbnVtYmVyLikKICAgIFN0cmluZyBudW1iZXIgPSBleHRyYWN0UG9zc2libGVOdW1iZXIobnVtYmVyVG9QYXJzZSk7CiAgICBpZiAoIWlzVmlhYmxlUGhvbmVOdW1iZXIobnVtYmVyKSkgewogICAgICB0aHJvdyBuZXcgTnVtYmVyUGFyc2VFeGNlcHRpb24oTnVtYmVyUGFyc2VFeGNlcHRpb24uRXJyb3JUeXBlLk5PVF9BX05VTUJFUiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJUaGUgc3RyaW5nIHN1cHBsaWVkIGRpZCBub3Qgc2VlbSB0byBiZSBhIHBob25lIG51bWJlci4iKTsKICAgIH0KCiAgICBpZiAoa2VlcFJhd0lucHV0KSB7CiAgICAgIHBob25lTnVtYmVyLnNldFJhd0lucHV0KG51bWJlclRvUGFyc2UpOwogICAgfQogICAgU3RyaW5nQnVmZmVyIG5hdGlvbmFsTnVtYmVyID0gbmV3IFN0cmluZ0J1ZmZlcihudW1iZXIpOwogICAgLy8gQXR0ZW1wdCB0byBwYXJzZSBleHRlbnNpb24gZmlyc3QsIHNpbmNlIGl0IGRvZXNuJ3QgcmVxdWlyZSBjb3VudHJ5LXNwZWNpZmljIGRhdGEgYW5kIHdlIHdhbnQKICAgIC8vIHRvIGhhdmUgdGhlIG5vbi1ub3JtYWxpc2VkIG51bWJlciBoZXJlLgogICAgU3RyaW5nIGV4dGVuc2lvbiA9IG1heWJlU3RyaXBFeHRlbnNpb24obmF0aW9uYWxOdW1iZXIpOwogICAgaWYgKGV4dGVuc2lvbi5sZW5ndGgoKSA+IDApIHsKICAgICAgcGhvbmVOdW1iZXIuc2V0RXh0ZW5zaW9uKGV4dGVuc2lvbik7CiAgICB9CgogICAgUGhvbmVNZXRhZGF0YSBjb3VudHJ5TWV0YWRhdGEgPSBnZXRNZXRhZGF0YUZvclJlZ2lvbihkZWZhdWx0Q291bnRyeSk7CiAgICAvLyBDaGVjayB0byBzZWUgaWYgdGhlIG51bWJlciBpcyBnaXZlbiBpbiBpbnRlcm5hdGlvbmFsIGZvcm1hdCBzbyB3ZSBrbm93IHdoZXRoZXIgdGhpcyBudW1iZXIgaXMKICAgIC8vIGZyb20gdGhlIGRlZmF1bHQgY291bnRyeSBvciBub3QuCiAgICBTdHJpbmdCdWZmZXIgbm9ybWFsaXplZE5hdGlvbmFsTnVtYmVyID0gbmV3IFN0cmluZ0J1ZmZlcigpOwogICAgLy8gYmVlbiBjcmVhdGVkLCBhbmQganVzdCByZW1vdmUgdGhlIHByZWZpeCwgcmF0aGVyIHRoYW4gdGFraW5nIGluIGEgc3RyaW5nIGFuZCB0aGVuIG91dHB1dHRpbmcKICAgIC8vIGEgc3RyaW5nIGJ1ZmZlci4KICAgIGludCBjb3VudHJ5Q29kZSA9IG1heWJlRXh0cmFjdENvdW50cnlDb2RlKG5hdGlvbmFsTnVtYmVyLnRvU3RyaW5nKCksIGNvdW50cnlNZXRhZGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vcm1hbGl6ZWROYXRpb25hbE51bWJlciwga2VlcFJhd0lucHV0LCBwaG9uZU51bWJlcik7CiAgICBpZiAoY291bnRyeUNvZGUgIT0gMCkgewogICAgICBTdHJpbmcgcGhvbmVOdW1iZXJSZWdpb24gPSBnZXRSZWdpb25Db2RlRm9yQ291bnRyeUNvZGUoY291bnRyeUNvZGUpOwogICAgICBpZiAoIXBob25lTnVtYmVyUmVnaW9uLmVxdWFscyhkZWZhdWx0Q291bnRyeSkpIHsKICAgICAgICBjb3VudHJ5TWV0YWRhdGEgPSBnZXRNZXRhZGF0YUZvclJlZ2lvbihwaG9uZU51bWJlclJlZ2lvbik7CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIC8vIElmIG5vIGV4dHJhY3RlZCBjb3VudHJ5IGNvZGUsIHVzZSB0aGUgcmVnaW9uIHN1cHBsaWVkIGluc3RlYWQuIFRoZSBuYXRpb25hbCBudW1iZXIgaXMganVzdAogICAgICAvLyB0aGUgbm9ybWFsaXplZCB2ZXJzaW9uIG9mIHRoZSBudW1iZXIgd2Ugd2VyZSBnaXZlbiB0byBwYXJzZS4KICAgICAgbm9ybWFsaXplKG5hdGlvbmFsTnVtYmVyKTsKICAgICAgbm9ybWFsaXplZE5hdGlvbmFsTnVtYmVyLmFwcGVuZChuYXRpb25hbE51bWJlcik7CiAgICAgIGlmIChkZWZhdWx0Q291bnRyeSAhPSBudWxsKSB7CiAgICAgICAgY291bnRyeUNvZGUgPSBjb3VudHJ5TWV0YWRhdGEuZ2V0Q291bnRyeUNvZGUoKTsKICAgICAgICBwaG9uZU51bWJlci5zZXRDb3VudHJ5Q29kZShjb3VudHJ5Q29kZSk7CiAgICAgIH0gZWxzZSBpZiAoa2VlcFJhd0lucHV0KSB7CiAgICAgICAgcGhvbmVOdW1iZXIuY2xlYXJDb3VudHJ5Q29kZVNvdXJjZSgpOwogICAgICB9CiAgICB9CiAgICBpZiAobm9ybWFsaXplZE5hdGlvbmFsTnVtYmVyLmxlbmd0aCgpIDwgTUlOX0xFTkdUSF9GT1JfTlNOKSB7CiAgICAgIHRocm93IG5ldyBOdW1iZXJQYXJzZUV4Y2VwdGlvbihOdW1iZXJQYXJzZUV4Y2VwdGlvbi5FcnJvclR5cGUuVE9PX1NIT1JUX05TTiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJUaGUgc3RyaW5nIHN1cHBsaWVkIGlzIHRvbyBzaG9ydCB0byBiZSBhIHBob25lIG51bWJlci4iKTsKICAgIH0KICAgIGlmIChjb3VudHJ5TWV0YWRhdGEgIT0gbnVsbCkgewogICAgICBQYXR0ZXJuIHZhbGlkTnVtYmVyUGF0dGVybiA9CiAgICAgICAgICByZWdleENhY2hlLmdldFBhdHRlcm5Gb3JSZWdleChjb3VudHJ5TWV0YWRhdGEuZ2V0R2VuZXJhbERlc2MoKQogICAgICAgICAgICAgIC5nZXROYXRpb25hbE51bWJlclBhdHRlcm4oKSk7CiAgICAgIG1heWJlU3RyaXBOYXRpb25hbFByZWZpeChub3JtYWxpemVkTmF0aW9uYWxOdW1iZXIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3VudHJ5TWV0YWRhdGEuZ2V0TmF0aW9uYWxQcmVmaXhGb3JQYXJzaW5nKCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3VudHJ5TWV0YWRhdGEuZ2V0TmF0aW9uYWxQcmVmaXhUcmFuc2Zvcm1SdWxlKCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWxpZE51bWJlclBhdHRlcm4pOwogICAgfQogICAgaW50IGxlbmd0aE9mTmF0aW9uYWxOdW1iZXIgPSBub3JtYWxpemVkTmF0aW9uYWxOdW1iZXIubGVuZ3RoKCk7CiAgICBpZiAobGVuZ3RoT2ZOYXRpb25hbE51bWJlciA8IE1JTl9MRU5HVEhfRk9SX05TTikgewogICAgICB0aHJvdyBuZXcgTnVtYmVyUGFyc2VFeGNlcHRpb24oTnVtYmVyUGFyc2VFeGNlcHRpb24uRXJyb3JUeXBlLlRPT19TSE9SVF9OU04sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiVGhlIHN0cmluZyBzdXBwbGllZCBpcyB0b28gc2hvcnQgdG8gYmUgYSBwaG9uZSBudW1iZXIuIik7CiAgICB9CiAgICBpZiAobGVuZ3RoT2ZOYXRpb25hbE51bWJlciA+IE1BWF9MRU5HVEhfRk9SX05TTikgewogICAgICB0aHJvdyBuZXcgTnVtYmVyUGFyc2VFeGNlcHRpb24oTnVtYmVyUGFyc2VFeGNlcHRpb24uRXJyb3JUeXBlLlRPT19MT05HLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlRoZSBzdHJpbmcgc3VwcGxpZWQgaXMgdG9vIGxvbmcgdG8gYmUgYSBwaG9uZSBudW1iZXIuIik7CiAgICB9CiAgICBpZiAobm9ybWFsaXplZE5hdGlvbmFsTnVtYmVyLmNoYXJBdCgwKSA9PSAnMCcgJiYgaXNMZWFkaW5nWmVyb0NvdW50cnkoY291bnRyeUNvZGUpKSB7CiAgICAgIHBob25lTnVtYmVyLnNldEl0YWxpYW5MZWFkaW5nWmVybyh0cnVlKTsKICAgIH0KICAgIHBob25lTnVtYmVyLnNldE5hdGlvbmFsTnVtYmVyKExvbmcucGFyc2VMb25nKG5vcm1hbGl6ZWROYXRpb25hbE51bWJlci50b1N0cmluZygpKSk7CiAgfQoKICAvKioKICAgKiBUYWtlcyB0d28gcGhvbmUgbnVtYmVycyBhbmQgY29tcGFyZXMgdGhlbSBmb3IgZXF1YWxpdHkuCiAgICoKICAgKiBSZXR1cm5zIEVYQUNUX01BVENIIGlmIHRoZSBjb3VudHJ5IGNvZGUsIE5TTiwgcHJlc2VuY2Ugb2YgYSBsZWFkaW5nIHplcm8gZm9yIEl0YWxpYW4gbnVtYmVycwogICAqIGFuZCBhbnkgZXh0ZW5zaW9uIHByZXNlbnQgYXJlIHRoZSBzYW1lLgogICAqIFJldHVybnMgTlNOX01BVENIIGlmIGVpdGhlciBvciBib3RoIGhhcyBubyBjb3VudHJ5IHNwZWNpZmllZCwgYW5kIHRoZSBOU05zIGFuZCBleHRlbnNpb25zIGFyZQogICAqIHRoZSBzYW1lLgogICAqIFJldHVybnMgU0hPUlRfTlNOX01BVENIIGlmIGVpdGhlciBvciBib3RoIGhhcyBubyBjb3VudHJ5IHNwZWNpZmllZCwgb3IgdGhlIGNvdW50cnkgc3BlY2lmaWVkCiAgICogaXMgdGhlIHNhbWUsIGFuZCBvbmUgTlNOIGNvdWxkIGJlIGEgc2hvcnRlciB2ZXJzaW9uIG9mIHRoZSBvdGhlciBudW1iZXIuIFRoaXMgaW5jbHVkZXMgdGhlIGNhc2UKICAgKiB3aGVyZSBvbmUgaGFzIGFuIGV4dGVuc2lvbiBzcGVjaWZpZWQsIGFuZCB0aGUgb3RoZXIgZG9lcyBub3QuCiAgICogUmV0dXJucyBOT19NQVRDSCBvdGhlcndpc2UuCiAgICogRm9yIGV4YW1wbGUsIHRoZSBudW1iZXJzICsxIDM0NSA2NTcgMTIzNCBhbmQgNjU3IDEyMzQgYXJlIGEgU0hPUlRfTlNOX01BVENILgogICAqIFRoZSBudW1iZXJzICsxIDM0NSA2NTcgMTIzNCBhbmQgMzQ1IDY1NyBhcmUgYSBOT19NQVRDSC4KICAgKgogICAqIEBwYXJhbSBmaXJzdE51bWJlckluICBmaXJzdCBudW1iZXIgdG8gY29tcGFyZQogICAqIEBwYXJhbSBzZWNvbmROdW1iZXJJbiAgc2Vjb25kIG51bWJlciB0byBjb21wYXJlCiAgICoKICAgKiBAcmV0dXJuICBOT19NQVRDSCwgU0hPUlRfTlNOX01BVENILCBOU05fTUFUQ0ggb3IgRVhBQ1RfTUFUQ0ggZGVwZW5kaW5nIG9uIHRoZSBsZXZlbCBvZiBlcXVhbGl0eQogICAqICAgICBvZiB0aGUgdHdvIG51bWJlcnMsIGRlc2NyaWJlZCBpbiB0aGUgbWV0aG9kIGRlZmluaXRpb24uCiAgICovCiAgcHVibGljIE1hdGNoVHlwZSBpc051bWJlck1hdGNoKFBob25lTnVtYmVyIGZpcnN0TnVtYmVySW4sIFBob25lTnVtYmVyIHNlY29uZE51bWJlckluKSB7CiAgICAvLyBNYWtlIGNvcGllcyBvZiB0aGUgcGhvbmUgbnVtYmVyIHNvIHRoYXQgdGhlIG51bWJlcnMgcGFzc2VkIGluIGFyZSBub3QgZWRpdGVkLgogICAgUGhvbmVOdW1iZXIgZmlyc3ROdW1iZXIgPSBuZXcgUGhvbmVOdW1iZXIoKTsKICAgIGZpcnN0TnVtYmVyLm1lcmdlRnJvbShmaXJzdE51bWJlckluKTsKICAgIFBob25lTnVtYmVyIHNlY29uZE51bWJlciA9IG5ldyBQaG9uZU51bWJlcigpOwogICAgc2Vjb25kTnVtYmVyLm1lcmdlRnJvbShzZWNvbmROdW1iZXJJbik7CiAgICAvLyBGaXJzdCBjbGVhciByYXdfaW5wdXQgYW5kIGNvdW50cnlfY29kZV9zb3VyY2UgZmllbGQgYW5kIGFueSBlbXB0eS1zdHJpbmcgZXh0ZW5zaW9ucyBzbyB0aGF0CiAgICAvLyB3ZSBjYW4gdXNlIHRoZSBQaG9uZU51bWJlci5leGFjdGx5U2FtZUFzKCkgbWV0aG9kLgogICAgZmlyc3ROdW1iZXIuY2xlYXJSYXdJbnB1dCgpOwogICAgZmlyc3ROdW1iZXIuY2xlYXJDb3VudHJ5Q29kZVNvdXJjZSgpOwogICAgc2Vjb25kTnVtYmVyLmNsZWFyUmF3SW5wdXQoKTsKICAgIHNlY29uZE51bWJlci5jbGVhckNvdW50cnlDb2RlU291cmNlKCk7CiAgICBpZiAoZmlyc3ROdW1iZXIuaGFzRXh0ZW5zaW9uKCkgJiYKICAgICAgICBmaXJzdE51bWJlci5nZXRFeHRlbnNpb24oKS5sZW5ndGgoKSA9PSAwKSB7CiAgICAgICAgZmlyc3ROdW1iZXIuY2xlYXJFeHRlbnNpb24oKTsKICAgIH0KICAgIGlmIChzZWNvbmROdW1iZXIuaGFzRXh0ZW5zaW9uKCkgJiYKICAgICAgICBzZWNvbmROdW1iZXIuZ2V0RXh0ZW5zaW9uKCkubGVuZ3RoKCkgPT0gMCkgewogICAgICAgIHNlY29uZE51bWJlci5jbGVhckV4dGVuc2lvbigpOwogICAgfQoKICAgIC8vIEVhcmx5IGV4aXQgaWYgYm90aCBoYWQgZXh0ZW5zaW9ucyBhbmQgdGhlc2UgYXJlIGRpZmZlcmVudC4KICAgIGlmIChmaXJzdE51bWJlci5oYXNFeHRlbnNpb24oKSAmJiBzZWNvbmROdW1iZXIuaGFzRXh0ZW5zaW9uKCkgJiYKICAgICAgICAhZmlyc3ROdW1iZXIuZ2V0RXh0ZW5zaW9uKCkuZXF1YWxzKHNlY29uZE51bWJlci5nZXRFeHRlbnNpb24oKSkpIHsKICAgICAgcmV0dXJuIE1hdGNoVHlwZS5OT19NQVRDSDsKICAgIH0KICAgIGludCBmaXJzdE51bWJlckNvdW50cnlDb2RlID0gZmlyc3ROdW1iZXIuZ2V0Q291bnRyeUNvZGUoKTsKICAgIGludCBzZWNvbmROdW1iZXJDb3VudHJ5Q29kZSA9IHNlY29uZE51bWJlci5nZXRDb3VudHJ5Q29kZSgpOwogICAgLy8gQm90aCBoYWQgY291bnRyeSBjb2RlIHNwZWNpZmllZC4KICAgIGlmIChmaXJzdE51bWJlckNvdW50cnlDb2RlICE9IDAgJiYgc2Vjb25kTnVtYmVyQ291bnRyeUNvZGUgIT0gMCkgewogICAgICBpZiAoZmlyc3ROdW1iZXIuZXhhY3RseVNhbWVBcyhzZWNvbmROdW1iZXIpKSB7CiAgICAgICAgcmV0dXJuIE1hdGNoVHlwZS5FWEFDVF9NQVRDSDsKICAgICAgfSBlbHNlIGlmIChmaXJzdE51bWJlckNvdW50cnlDb2RlID09IHNlY29uZE51bWJlckNvdW50cnlDb2RlICYmCiAgICAgICAgICAgICAgICAgaXNOYXRpb25hbE51bWJlclN1ZmZpeE9mVGhlT3RoZXIoZmlyc3ROdW1iZXIsIHNlY29uZE51bWJlcikpIHsKICAgICAgICAvLyBBIFNIT1JUX05TTl9NQVRDSCBvY2N1cnMgaWYgdGhlcmUgaXMgYSBkaWZmZXJlbmNlIGJlY2F1c2Ugb2YgdGhlIHByZXNlbmNlIG9yIGFic2VuY2Ugb2YKICAgICAgICAvLyBhbiAnSXRhbGlhbiBsZWFkaW5nIHplcm8nLCB0aGUgcHJlc2VuY2Ugb3IgYWJzZW5jZSBvZiBhbiBleHRlbnNpb24sIG9yIG9uZSBOU04gYmVpbmcgYQogICAgICAgIC8vIHNob3J0ZXIgdmFyaWFudCBvZiB0aGUgb3RoZXIuCiAgICAgICAgcmV0dXJuIE1hdGNoVHlwZS5TSE9SVF9OU05fTUFUQ0g7CiAgICAgIH0KICAgICAgLy8gVGhpcyBpcyBub3QgYSBtYXRjaC4KICAgICAgcmV0dXJuIE1hdGNoVHlwZS5OT19NQVRDSDsKICAgIH0KICAgIC8vIENoZWNrcyBjYXNlcyB3aGVyZSBvbmUgb3IgYm90aCBjb3VudHJ5IGNvZGVzIHdlcmUgbm90IHNwZWNpZmllZC4gVG8gbWFrZSBlcXVhbGl0eSBjaGVja3MKICAgIC8vIGVhc2llciwgd2UgZmlyc3Qgc2V0IHRoZSBjb3VudHJ5IGNvZGVzIHRvIGJlIGVxdWFsLgogICAgZmlyc3ROdW1iZXIuc2V0Q291bnRyeUNvZGUoc2Vjb25kTnVtYmVyQ291bnRyeUNvZGUpOwogICAgLy8gSWYgYWxsIGVsc2Ugd2FzIHRoZSBzYW1lLCB0aGVuIHRoaXMgaXMgYW4gTlNOX01BVENILgogICAgaWYgKGZpcnN0TnVtYmVyLmV4YWN0bHlTYW1lQXMoc2Vjb25kTnVtYmVyKSkgewogICAgICByZXR1cm4gTWF0Y2hUeXBlLk5TTl9NQVRDSDsKICAgIH0KICAgIGlmIChpc05hdGlvbmFsTnVtYmVyU3VmZml4T2ZUaGVPdGhlcihmaXJzdE51bWJlciwgc2Vjb25kTnVtYmVyKSkgewogICAgICByZXR1cm4gTWF0Y2hUeXBlLlNIT1JUX05TTl9NQVRDSDsKICAgIH0KICAgIHJldHVybiBNYXRjaFR5cGUuTk9fTUFUQ0g7CiAgfQoKICAvLyBSZXR1cm5zIHRydWUgd2hlbiBvbmUgbmF0aW9uYWwgbnVtYmVyIGlzIHRoZSBzdWZmaXggb2YgdGhlIG90aGVyIG9yIGJvdGggYXJlIHRoZSBzYW1lLgogIHByaXZhdGUgYm9vbGVhbiBpc05hdGlvbmFsTnVtYmVyU3VmZml4T2ZUaGVPdGhlcihQaG9uZU51bWJlciBmaXJzdE51bWJlciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUGhvbmVOdW1iZXIgc2Vjb25kTnVtYmVyKSB7CiAgICBTdHJpbmcgZmlyc3ROdW1iZXJOYXRpb25hbE51bWJlciA9IFN0cmluZy52YWx1ZU9mKGZpcnN0TnVtYmVyLmdldE5hdGlvbmFsTnVtYmVyKCkpOwogICAgU3RyaW5nIHNlY29uZE51bWJlck5hdGlvbmFsTnVtYmVyID0gU3RyaW5nLnZhbHVlT2Yoc2Vjb25kTnVtYmVyLmdldE5hdGlvbmFsTnVtYmVyKCkpOwogICAgLy8gTm90ZSB0aGF0IGVuZHNXaXRoIHJldHVybnMgdHJ1ZSBpZiB0aGUgbnVtYmVycyBhcmUgZXF1YWwuCiAgICByZXR1cm4gZmlyc3ROdW1iZXJOYXRpb25hbE51bWJlci5lbmRzV2l0aChzZWNvbmROdW1iZXJOYXRpb25hbE51bWJlcikgfHwKICAgICAgICAgICBzZWNvbmROdW1iZXJOYXRpb25hbE51bWJlci5lbmRzV2l0aChmaXJzdE51bWJlck5hdGlvbmFsTnVtYmVyKTsKICB9CgogIC8qKgogICAqIFRha2VzIHR3byBwaG9uZSBudW1iZXJzIGFzIHN0cmluZ3MgYW5kIGNvbXBhcmVzIHRoZW0gZm9yIGVxdWFsaXR5LiBUaGlzIGlzIGEgY29udmVuaWVuY2UKICAgKiB3cmFwcGVyIGZvciBpc051bWJlck1hdGNoKFBob25lTnVtYmVyIGZpcnN0TnVtYmVyLCBQaG9uZU51bWJlciBzZWNvbmROdW1iZXIpLiBObyBkZWZhdWx0IHJlZ2lvbgogICAqIGlzIGtub3duLgogICAqCiAgICogQHBhcmFtIGZpcnN0TnVtYmVyICBmaXJzdCBudW1iZXIgdG8gY29tcGFyZS4gQ2FuIGNvbnRhaW4gZm9ybWF0dGluZywgYW5kIGNhbiBoYXZlIGNvdW50cnkgY29kZQogICAqICAgICBzcGVjaWZpZWQgd2l0aCArIGF0IHRoZSBzdGFydC4KICAgKiBAcGFyYW0gc2Vjb25kTnVtYmVyICBzZWNvbmQgbnVtYmVyIHRvIGNvbXBhcmUuIENhbiBjb250YWluIGZvcm1hdHRpbmcsIGFuZCBjYW4gaGF2ZSBjb3VudHJ5CiAgICogICAgIGNvZGUgc3BlY2lmaWVkIHdpdGggKyBhdCB0aGUgc3RhcnQuCiAgICogQHJldHVybiAgTk9fTUFUQ0gsIFNIT1JUX05TTl9NQVRDSCwgTlNOX01BVENILCBFWEFDVF9NQVRDSC4gU2VlIGlzTnVtYmVyTWF0Y2goUGhvbmVOdW1iZXIKICAgKiAgICAgZmlyc3ROdW1iZXIsIFBob25lTnVtYmVyIHNlY29uZE51bWJlcikgZm9yIG1vcmUgZGV0YWlscy4KICAgKiBAdGhyb3dzIE51bWJlclBhcnNlRXhjZXB0aW9uICBpZiBlaXRoZXIgbnVtYmVyIGlzIG5vdCBjb25zaWRlcmVkIHRvIGJlIGEgdmlhYmxlIHBob25lCiAgICogICAgIG51bWJlcgogICAqLwogIHB1YmxpYyBNYXRjaFR5cGUgaXNOdW1iZXJNYXRjaChTdHJpbmcgZmlyc3ROdW1iZXIsIFN0cmluZyBzZWNvbmROdW1iZXIpCiAgICAgIHRocm93cyBOdW1iZXJQYXJzZUV4Y2VwdGlvbiB7CiAgICBQaG9uZU51bWJlciBudW1iZXIxID0gbmV3IFBob25lTnVtYmVyKCk7CiAgICBwYXJzZUhlbHBlcihmaXJzdE51bWJlciwgbnVsbCwgZmFsc2UsIG51bWJlcjEpOwogICAgUGhvbmVOdW1iZXIgbnVtYmVyMiA9IG5ldyBQaG9uZU51bWJlcigpOwogICAgcGFyc2VIZWxwZXIoc2Vjb25kTnVtYmVyLCBudWxsLCBmYWxzZSwgbnVtYmVyMik7CiAgICByZXR1cm4gaXNOdW1iZXJNYXRjaChudW1iZXIxLCBudW1iZXIyKTsKICB9CgogIC8qKgogICAqIFRha2VzIHR3byBwaG9uZSBudW1iZXJzIGFuZCBjb21wYXJlcyB0aGVtIGZvciBlcXVhbGl0eS4gVGhpcyBpcyBhIGNvbnZlbmllbmNlIHdyYXBwZXIgZm9yCiAgICogaXNOdW1iZXJNYXRjaChQaG9uZU51bWJlciBmaXJzdE51bWJlciwgUGhvbmVOdW1iZXIgc2Vjb25kTnVtYmVyKS4gTm8gZGVmYXVsdCByZWdpb24gaXMga25vd24uCiAgICoKICAgKiBAcGFyYW0gZmlyc3ROdW1iZXIgIGZpcnN0IG51bWJlciB0byBjb21wYXJlIGluIHByb3RvIGJ1ZmZlciBmb3JtYXQuCiAgICogQHBhcmFtIHNlY29uZE51bWJlciAgc2Vjb25kIG51bWJlciB0byBjb21wYXJlLiBDYW4gY29udGFpbiBmb3JtYXR0aW5nLCBhbmQgY2FuIGhhdmUgY291bnRyeQogICAqICAgICBjb2RlIHNwZWNpZmllZCB3aXRoICsgYXQgdGhlIHN0YXJ0LgogICAqIEByZXR1cm4gIE5PX01BVENILCBTSE9SVF9OU05fTUFUQ0gsIE5TTl9NQVRDSCwgRVhBQ1RfTUFUQ0guIFNlZSBpc051bWJlck1hdGNoKFBob25lTnVtYmVyCiAgICogICAgIGZpcnN0TnVtYmVyLCBQaG9uZU51bWJlciBzZWNvbmROdW1iZXIpIGZvciBtb3JlIGRldGFpbHMuCiAgICogQHRocm93cyBOdW1iZXJQYXJzZUV4Y2VwdGlvbiAgaWYgdGhlIHNlY29uZCBudW1iZXIgaXMgbm90IGNvbnNpZGVyZWQgdG8gYmUgYSB2aWFibGUgcGhvbmUKICAgKiAgICAgbnVtYmVyCiAgICovCiAgcHVibGljIE1hdGNoVHlwZSBpc051bWJlck1hdGNoKFBob25lTnVtYmVyIGZpcnN0TnVtYmVyLCBTdHJpbmcgc2Vjb25kTnVtYmVyKQogICAgICB0aHJvd3MgTnVtYmVyUGFyc2VFeGNlcHRpb24gewogICAgUGhvbmVOdW1iZXIgbnVtYmVyMiA9IG5ldyBQaG9uZU51bWJlcigpOwogICAgcGFyc2VIZWxwZXIoc2Vjb25kTnVtYmVyLCBudWxsLCBmYWxzZSwgbnVtYmVyMik7CiAgICByZXR1cm4gaXNOdW1iZXJNYXRjaChmaXJzdE51bWJlciwgbnVtYmVyMik7CiAgfQp9Cg==