You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by ab...@apache.org on 2020/10/01 06:06:10 UTC

[lucene-solr] branch jira/solr-14749 updated (d5198c0 -> a8658ce)

This is an automated email from the ASF dual-hosted git repository.

ab pushed a change to branch jira/solr-14749
in repository https://gitbox.apache.org/repos/asf/lucene-solr.git.


    from d5198c0  Merge branch 'master' into jira/solr-14749
     add 876de8b  SOLR-14828: reduce 'error' logging noise in BaseCloudSolrClient.requestWithRetryOnStaleState (#1825)
     add ea77d24  SOLR-11167: Avoid $SOLR_STOP_WAIT use during 'bin/solr start' if $SOLR_START_WAIT is supplied. (#1913)
     add 7be262e  move 9x upgrade notes out of changes.txt (#1914)
     add ac58472  SOLR-14036: Remove explicit distrib=false from /terms handler (#1900)
     add ddd1072  SOLR-14503: use specified waitForZk val as conn timeout for zk
     add c032cd1  Revert "LUCENE-9535: Reduce the size of compressed blocks of stored fields by 2x."
     add e28e8c0  add regenerate gradle script for nori dictionary (#1924)
     add 5e617cc  LUCENE-9317: Clean up split package in analyzers-common (#1836)
     add 6b0149e  Revert "add regenerate gradle script for nori dictionary (#1924)"
     add 4105414  SOLR-13528: Implement API Based Config For Rate Limiters (#1906)
     add 00d7f5e  LUCENE-9544: Port Nori dictionary compilation (#1926)
     add 32041c8  SOLR-14850: Fix ExactStatsCache NullPointerException when shards.tolerant=true.
     add c3f97fb  Compute RAM usage ByteBuffersDataOutput on the fly. (#1919)
     add fc6d0a4  LUCENE-9317: Remove unused imports.
     add 24aadc2  LUCENE-9444: add utility class to retrieve facet labels from the taxonomy index for a facet field (#1893)
     add 98a49ed  LUCENE-9444: add CHANGES.txt entry
     add 01da67c  SOLR-14901: TestPackages uses binary precompiled classes to refer to analysis factory FQCNs
     add a65e9dd  SOLR-14151: cleanup
     add 8b329a0  SOLR-14850: Correct the spelling in contributor's name.
     add 3ae0b50  LUCENE-9546: Configure Nori and Kuromoji generation lazily when java plugin is applied to the projects
     add 65a62b0  Remove unused imports.
     add 2b692cc  LUCENE-9547: Race condition in maven artifact configuration results in wrong group/ artifact name
     new 126b236  Merge branch 'master' into jira/solr-14749
     new a8658ce  SOLR-14749: Fix the race between plugin loading and registration and Overseer leader election. Make events implement MapWriter-s. Add more unit tests.

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 build.gradle                                       |   1 +
 gradle/documentation/render-javadoc.gradle         |   4 +-
 gradle/generation/jflex.gradle                     |   4 +-
 gradle/generation/kuromoji.gradle                  | 173 +++++++-------
 gradle/generation/nori.gradle                      |  85 +++++++
 gradle/maven/defaults-maven.gradle                 |  41 ++--
 gradle/validation/validate-source-patterns.gradle  |   2 +-
 lucene/CHANGES.txt                                 |  13 +-
 lucene/MIGRATE.md                                  |  18 ++
 .../ar/ArabicNormalizationFilterFactory.java       |   2 +-
 .../analysis/ar/ArabicStemFilterFactory.java       |   2 +-
 .../analysis/bg/BulgarianStemFilterFactory.java    |   2 +-
 .../bn/BengaliNormalizationFilterFactory.java      |   2 +-
 .../analysis/bn/BengaliStemFilterFactory.java      |   2 +-
 .../boost/DelimitedBoostTokenFilterFactory.java    |   2 +-
 .../analysis/br/BrazilianStemFilterFactory.java    |   2 +-
 .../charfilter/HTMLStripCharFilterFactory.java     |   2 +-
 .../charfilter/MappingCharFilterFactory.java       |   6 +-
 .../analysis/cjk/CJKBigramFilterFactory.java       |   2 +-
 .../lucene/analysis/cjk/CJKWidthFilterFactory.java |   2 +-
 .../ckb/SoraniNormalizationFilterFactory.java      |   2 +-
 .../analysis/ckb/SoraniStemFilterFactory.java      |   2 +-
 .../{standard => classic}/ClassicAnalyzer.java     |   3 +-
 .../{standard => classic}/ClassicFilter.java       |   2 +-
 .../ClassicFilterFactory.java                      |   4 +-
 .../{standard => classic}/ClassicTokenizer.java    |   4 +-
 .../ClassicTokenizerFactory.java                   |   5 +-
 .../ClassicTokenizerImpl.java                      |   2 +-
 .../ClassicTokenizerImpl.jflex                     |   0
 .../analysis/{standard => classic}/package.html    |  21 +-
 .../commongrams/CommonGramsFilterFactory.java      |   6 +-
 .../DictionaryCompoundWordTokenFilterFactory.java  |   6 +-
 .../HyphenationCompoundWordTokenFilterFactory.java |   6 +-
 .../analysis/core/DecimalDigitFilterFactory.java   |   2 +-
 .../analysis/core/FlattenGraphFilterFactory.java   |   2 +-
 .../analysis/core/KeywordTokenizerFactory.java     |   2 +-
 .../analysis/core/LetterTokenizerFactory.java      |   2 +-
 .../analysis/core/LowerCaseFilterFactory.java      |   2 +-
 .../lucene/analysis/core/StopFilterFactory.java    |   6 +-
 .../analysis/core/TypeTokenFilterFactory.java      |   6 +-
 .../analysis/core/UpperCaseFilterFactory.java      |   2 +-
 .../analysis/core/WhitespaceTokenizerFactory.java  |   2 +-
 .../lucene/analysis/custom/CustomAnalyzer.java     |  16 +-
 .../lucene/analysis/cz/CzechStemFilterFactory.java |   2 +-
 .../analysis/de/GermanLightStemFilterFactory.java  |   2 +-
 .../de/GermanMinimalStemFilterFactory.java         |   2 +-
 .../de/GermanNormalizationFilterFactory.java       |   2 +-
 .../analysis/de/GermanStemFilterFactory.java       |   2 +-
 .../analysis/el/GreekLowerCaseFilterFactory.java   |   2 +-
 .../lucene/analysis/el/GreekStemFilterFactory.java |   2 +-
 .../{standard => email}/ASCIITLD.jflex-macro       |   0
 .../{standard => email}/UAX29URLEmailAnalyzer.java |   5 +-
 .../UAX29URLEmailTokenizer.java                    |   4 +-
 .../UAX29URLEmailTokenizerFactory.java             |   5 +-
 .../UAX29URLEmailTokenizerImpl.java                |   2 +-
 .../UAX29URLEmailTokenizerImpl.jflex               |   2 +-
 .../analysis/{standard => email}/package.html      |  21 +-
 .../en/EnglishMinimalStemFilterFactory.java        |   2 +-
 .../en/EnglishPossessiveFilterFactory.java         |   2 +-
 .../lucene/analysis/en/KStemFilterFactory.java     |   2 +-
 .../analysis/en/PorterStemFilterFactory.java       |   2 +-
 .../analysis/es/SpanishLightStemFilterFactory.java |   2 +-
 .../es/SpanishMinimalStemFilterFactory.java        |   2 +-
 .../analysis/fa/PersianCharFilterFactory.java      |   2 +-
 .../fa/PersianNormalizationFilterFactory.java      |   2 +-
 .../analysis/fi/FinnishLightStemFilterFactory.java |   2 +-
 .../analysis/fr/FrenchLightStemFilterFactory.java  |   2 +-
 .../fr/FrenchMinimalStemFilterFactory.java         |   2 +-
 .../analysis/ga/IrishLowerCaseFilterFactory.java   |   2 +-
 .../gl/GalicianMinimalStemFilterFactory.java       |   2 +-
 .../analysis/gl/GalicianStemFilterFactory.java     |   2 +-
 .../hi/HindiNormalizationFilterFactory.java        |   2 +-
 .../lucene/analysis/hi/HindiStemFilterFactory.java |   2 +-
 .../hu/HungarianLightStemFilterFactory.java        |   2 +-
 .../hunspell/HunspellStemFilterFactory.java        |   6 +-
 .../analysis/id/IndonesianStemFilterFactory.java   |   2 +-
 .../in/IndicNormalizationFilterFactory.java        |   2 +-
 .../analysis/it/ItalianLightStemFilterFactory.java |   2 +-
 .../analysis/lv/LatvianStemFilterFactory.java      |   2 +-
 .../analysis/minhash/MinHashFilterFactory.java     |   4 +-
 .../miscellaneous/ASCIIFoldingFilterFactory.java   |   2 +-
 .../miscellaneous/CapitalizationFilterFactory.java |   2 +-
 .../miscellaneous/CodepointCountFilterFactory.java |   2 +-
 .../ConcatenateGraphFilterFactory.java             |   2 +-
 .../ConditionalTokenFilterFactory.java             |   6 +-
 .../miscellaneous/DateRecognizerFilterFactory.java |   2 +-
 .../DelimitedTermFrequencyTokenFilterFactory.java  |   2 +-
 .../miscellaneous/FingerprintFilterFactory.java    |   2 +-
 .../FixBrokenOffsetsFilterFactory.java             |   2 +-
 .../HyphenatedWordsFilterFactory.java              |   2 +-
 .../miscellaneous/KeepWordFilterFactory.java       |   6 +-
 .../miscellaneous/KeywordMarkerFilterFactory.java  |   6 +-
 .../miscellaneous/KeywordRepeatFilterFactory.java  |   2 +-
 .../miscellaneous/LengthFilterFactory.java         |   2 +-
 .../LimitTokenCountFilterFactory.java              |   2 +-
 .../LimitTokenOffsetFilterFactory.java             |   2 +-
 .../LimitTokenPositionFilterFactory.java           |   2 +-
 .../miscellaneous/ProtectedTermFilterFactory.java  |   6 +-
 .../RemoveDuplicatesTokenFilterFactory.java        |   2 +-
 .../ScandinavianFoldingFilterFactory.java          |   2 +-
 .../ScandinavianNormalizationFilterFactory.java    |   2 +-
 .../StemmerOverrideFilterFactory.java              |   6 +-
 .../analysis/miscellaneous/TrimFilterFactory.java  |   2 +-
 .../miscellaneous/TruncateTokenFilterFactory.java  |   2 +-
 .../miscellaneous/TypeAsSynonymFilterFactory.java  |   2 +-
 .../miscellaneous/WordDelimiterFilterFactory.java  |   6 +-
 .../WordDelimiterGraphFilterFactory.java           |   6 +-
 .../analysis/ngram/EdgeNGramFilterFactory.java     |   2 +-
 .../analysis/ngram/EdgeNGramTokenizerFactory.java  |   2 +-
 .../lucene/analysis/ngram/NGramFilterFactory.java  |   2 +-
 .../analysis/ngram/NGramTokenizerFactory.java      |   2 +-
 .../no/NorwegianLightStemFilterFactory.java        |   2 +-
 .../no/NorwegianMinimalStemFilterFactory.java      |   2 +-
 .../path/PathHierarchyTokenizerFactory.java        |   2 +-
 .../pattern/PatternCaptureGroupFilterFactory.java  |   2 +-
 .../pattern/PatternReplaceCharFilterFactory.java   |   2 +-
 .../pattern/PatternReplaceFilterFactory.java       |   2 +-
 .../analysis/pattern/PatternTokenizerFactory.java  |   2 +-
 .../SimplePatternSplitTokenizerFactory.java        |   2 +-
 .../pattern/SimplePatternTokenizerFactory.java     |   2 +-
 .../DelimitedPayloadTokenFilterFactory.java        |   6 +-
 .../payloads/NumericPayloadTokenFilterFactory.java |   2 +-
 .../TokenOffsetPayloadTokenFilterFactory.java      |   2 +-
 .../payloads/TypeAsPayloadTokenFilterFactory.java  |   2 +-
 .../pt/PortugueseLightStemFilterFactory.java       |   2 +-
 .../pt/PortugueseMinimalStemFilterFactory.java     |   2 +-
 .../analysis/pt/PortugueseStemFilterFactory.java   |   2 +-
 .../reverse/ReverseStringFilterFactory.java        |   2 +-
 .../analysis/ru/RussianLightStemFilterFactory.java |   2 +-
 .../shingle/FixedShingleFilterFactory.java         |   2 +-
 .../analysis/shingle/ShingleFilterFactory.java     |   2 +-
 .../snowball/SnowballPorterFilterFactory.java      |   6 +-
 .../sr/SerbianNormalizationFilterFactory.java      |   2 +-
 .../analysis/sv/SwedishLightStemFilterFactory.java |   2 +-
 .../analysis/synonym/SynonymFilterFactory.java     |   8 +-
 .../synonym/SynonymGraphFilterFactory.java         |   8 +-
 .../lucene/analysis/th/ThaiTokenizerFactory.java   |   2 +-
 .../analysis/tr/ApostropheFilterFactory.java       |   2 +-
 .../analysis/tr/TurkishLowerCaseFilterFactory.java |   2 +-
 .../lucene/analysis/util/ElisionFilterFactory.java |   3 +
 .../analysis/util/FilesystemResourceLoader.java    |   3 +
 .../wikipedia/WikipediaTokenizerFactory.java       |   2 +-
 ...> org.apache.lucene.analysis.CharFilterFactory} |   0
 ... org.apache.lucene.analysis.TokenFilterFactory} |   2 +-
 ...=> org.apache.lucene.analysis.TokenizerFactory} |   5 +-
 .../lucene/analysis/ar/TestArabicFilters.java      |   2 +-
 .../bg/TestBulgarianStemFilterFactory.java         |   2 +-
 .../lucene/analysis/bn/TestBengaliFilters.java     |   2 +-
 .../br/TestBrazilianStemFilterFactory.java         |   2 +-
 .../charfilter/TestHTMLStripCharFilterFactory.java |   2 +-
 .../charfilter/TestMappingCharFilterFactory.java   |   2 +-
 .../analysis/cjk/TestCJKBigramFilterFactory.java   |   2 +-
 .../analysis/cjk/TestCJKWidthFilterFactory.java    |   2 +-
 .../ckb/TestSoraniNormalizationFilterFactory.java  |   2 +-
 .../analysis/ckb/TestSoraniStemFilterFactory.java  |   2 +-
 .../{standard => classic}/TestClassicAnalyzer.java |   2 +-
 .../analysis/classic/TestClassicFactories.java     |  81 +++++++
 .../commongrams/TestCommonGramsFilterFactory.java  |   6 +-
 .../TestCommonGramsQueryFilterFactory.java         |   6 +-
 ...stDictionaryCompoundWordTokenFilterFactory.java |   2 +-
 ...tHyphenationCompoundWordTokenFilterFactory.java |   2 +-
 .../core/TestAllAnalyzersHaveFactories.java        |  10 +-
 .../lucene/analysis/core/TestCoreFactories.java    |  76 ++++++
 .../core/TestDecimalDigitFilterFactory.java        |   2 +-
 .../apache/lucene/analysis/core/TestFactories.java |  10 +-
 .../analysis/core/TestStopFilterFactory.java       |   6 +-
 .../analysis/core/TestTypeTokenFilterFactory.java  |   4 +-
 .../lucene/analysis/custom/TestCustomAnalyzer.java |   8 +-
 .../analysis/cz/TestCzechStemFilterFactory.java    |   2 +-
 .../de/TestGermanLightStemFilterFactory.java       |   2 +-
 .../de/TestGermanMinimalStemFilterFactory.java     |   2 +-
 .../de/TestGermanNormalizationFilterFactory.java   |   2 +-
 .../analysis/de/TestGermanStemFilterFactory.java   |   2 +-
 .../el/TestGreekLowerCaseFilterFactory.java        |   2 +-
 .../analysis/el/TestGreekStemFilterFactory.java    |   2 +-
 .../LuceneResourcesWikiPage.html                   |   0
 .../LuceneResourcesWikiPageURLs.txt                |   0
 .../TestUAX29URLEmailAnalyzer.java                 |   2 +-
 .../TestUAX29URLEmailTokenizer.java                |   4 +-
 .../TestUAX29URLEmailTokenizerFactory.java         |   4 +-
 ...esses.from.random.text.with.email.addresses.txt |   0
 .../random.text.with.email.addresses.txt           |   0
 .../{standard => email}/random.text.with.urls.txt  |   0
 .../urls.from.random.text.with.urls.txt            |   0
 .../en/TestEnglishMinimalStemFilterFactory.java    |   2 +-
 .../lucene/analysis/en/TestKStemFilterFactory.java |   2 +-
 .../analysis/en/TestPorterStemFilterFactory.java   |   2 +-
 .../es/TestSpanishLightStemFilterFactory.java      |   2 +-
 .../es/TestSpanishMinimalStemFilterFactory.java    |   2 +-
 .../fa/TestPersianNormalizationFilterFactory.java  |   2 +-
 .../fi/TestFinnishLightStemFilterFactory.java      |   2 +-
 .../fr/TestFrenchLightStemFilterFactory.java       |   2 +-
 .../fr/TestFrenchMinimalStemFilterFactory.java     |   2 +-
 .../ga/TestIrishLowerCaseFilterFactory.java        |   2 +-
 .../gl/TestGalicianMinimalStemFilterFactory.java   |   2 +-
 .../analysis/gl/TestGalicianStemFilterFactory.java |   2 +-
 .../lucene/analysis/hi/TestHindiFilters.java       |   2 +-
 .../hu/TestHungarianLightStemFilterFactory.java    |   2 +-
 .../hunspell/TestHunspellStemFilterFactory.java    |   2 +-
 .../id/TestIndonesianStemFilterFactory.java        |   2 +-
 .../it/TestItalianLightStemFilterFactory.java      |   2 +-
 .../analysis/lv/TestLatvianStemFilterFactory.java  |   2 +-
 .../TestAsciiFoldingFilterFactory.java             |   4 +-
 .../TestCapitalizationFilterFactory.java           |   2 +-
 .../TestCodepointCountFilterFactory.java           |   2 +-
 .../TestConcatenateGraphFilterFactory.java         |   2 +-
 .../miscellaneous/TestConditionalTokenFilter.java  |   2 +-
 .../TestFingerprintFilterFactory.java              |   2 +-
 .../miscellaneous/TestKeepFilterFactory.java       |   6 +-
 .../TestKeywordMarkerFilterFactory.java            |   2 +-
 .../miscellaneous/TestLengthFilterFactory.java     |   2 +-
 .../TestLimitTokenCountFilterFactory.java          |   2 +-
 .../TestLimitTokenOffsetFilterFactory.java         |   2 +-
 .../TestLimitTokenPositionFilterFactory.java       |   2 +-
 ...actory.java => TestMiscellaneousFactories.java} |  29 ++-
 .../TestProtectedTermFilterFactory.java            |   2 +-
 .../TestRemoveDuplicatesTokenFilterFactory.java    |   2 +-
 .../TestScandinavianFoldingFilterFactory.java      |   2 +-
 ...TestScandinavianNormalizationFilterFactory.java |   2 +-
 .../TestStemmerOverrideFilterFactory.java          |   2 +-
 .../miscellaneous/TestTrimFilterFactory.java       |   2 +-
 .../TestTruncateTokenFilterFactory.java            |   2 +-
 .../TestTypeAsSynonymFilterFactory.java            |   2 +-
 .../lucene/analysis/ngram/TestNGramFilters.java    |   2 +-
 .../no/TestNorwegianLightStemFilterFactory.java    |   2 +-
 .../no/TestNorwegianMinimalStemFilterFactory.java  |   2 +-
 .../TestPatternReplaceCharFilterFactory.java       |   2 +-
 .../pattern/TestPatternReplaceFilterFactory.java   |   2 +-
 .../pattern/TestPatternTokenizerFactory.java       |   2 +-
 .../TestDelimitedPayloadTokenFilterFactory.java    |   2 +-
 .../pt/TestPortugueseLightStemFilterFactory.java   |   2 +-
 .../pt/TestPortugueseMinimalStemFilterFactory.java |   2 +-
 .../pt/TestPortugueseStemFilterFactory.java        |   2 +-
 .../reverse/TestReverseStringFilterFactory.java    |   2 +-
 .../ru/TestRussianLightStemFilterFactory.java      |   2 +-
 .../analysis/shingle/TestShingleFilterFactory.java |   2 +-
 .../snowball/TestSnowballPorterFilterFactory.java  |   2 +-
 .../sr/TestSerbianNormalizationFilterFactory.java  |   2 +-
 .../analysis/standard/TestStandardFactories.java   | 170 --------------
 .../sv/TestSwedishLightStemFilterFactory.java      |   2 +-
 .../analysis/synonym/TestMultiWordSynonyms.java    |   2 +-
 .../analysis/synonym/TestSynonymFilterFactory.java |   4 +-
 .../analysis/th/TestThaiTokenizerFactory.java      |   2 +-
 .../analysis/tr/TestApostropheFilterFactory.java   |   2 +-
 .../tr/TestTurkishLowerCaseFilterFactory.java      |   2 +-
 .../analysis/util/StringMockResourceLoader.java    |   2 +
 .../analysis/util/TestElisionFilterFactory.java    |   1 +
 .../util/TestFilesystemResourceLoader.java         |   2 +
 .../wikipedia/TestWikipediaTokenizerFactory.java   |   2 +-
 .../analysis/icu/ICUFoldingFilterFactory.java      |   2 +-
 .../icu/ICUNormalizer2CharFilterFactory.java       |   2 +-
 .../analysis/icu/ICUNormalizer2FilterFactory.java  |   2 +-
 .../analysis/icu/ICUTransformFilterFactory.java    |   2 +-
 .../icu/segmentation/ICUTokenizerFactory.java      |   6 +-
 ...> org.apache.lucene.analysis.CharFilterFactory} |   0
 ... org.apache.lucene.analysis.TokenFilterFactory} |   0
 ...=> org.apache.lucene.analysis.TokenizerFactory} |   0
 .../icu/segmentation/TestICUTokenizerFactory.java  |   2 +-
 .../analysis/ja/JapaneseBaseFormFilterFactory.java |   2 +-
 .../ja/JapaneseIterationMarkCharFilterFactory.java |   2 +-
 .../ja/JapaneseKatakanaStemFilterFactory.java      |   2 +-
 .../analysis/ja/JapaneseNumberFilterFactory.java   |   2 +-
 .../ja/JapanesePartOfSpeechStopFilterFactory.java  |   6 +-
 .../ja/JapaneseReadingFormFilterFactory.java       |   2 +-
 .../analysis/ja/JapaneseTokenizerFactory.java      |   6 +-
 ...> org.apache.lucene.analysis.CharFilterFactory} |   0
 ... org.apache.lucene.analysis.TokenFilterFactory} |   0
 ...=> org.apache.lucene.analysis.TokenizerFactory} |   0
 .../analysis/ja/StringMockResourceLoader.java      |   2 +-
 .../apache/lucene/analysis/ja/TestFactories.java   |  10 +-
 .../morfologik/MorfologikFilterFactory.java        |   6 +-
 ... org.apache.lucene.analysis.TokenFilterFactory} |   0
 .../morfologik/TestMorfologikFilterFactory.java    |   4 +-
 .../analysis/ko/KoreanNumberFilterFactory.java     |   2 +-
 .../ko/KoreanPartOfSpeechStopFilterFactory.java    |   2 +-
 .../ko/KoreanReadingFormFilterFactory.java         |   2 +-
 .../lucene/analysis/ko/KoreanTokenizerFactory.java |   6 +-
 ... org.apache.lucene.analysis.TokenFilterFactory} |   0
 ...=> org.apache.lucene.analysis.TokenizerFactory} |   0
 .../analysis/ko/StringMockResourceLoader.java      |   2 +-
 .../opennlp/OpenNLPChunkerFilterFactory.java       |   6 +-
 .../opennlp/OpenNLPLemmatizerFilterFactory.java    |   6 +-
 .../analysis/opennlp/OpenNLPPOSFilterFactory.java  |   6 +-
 .../analysis/opennlp/OpenNLPTokenizerFactory.java  |   6 +-
 .../analysis/opennlp/tools/OpenNLPOpsFactory.java  |   2 +-
 ... org.apache.lucene.analysis.TokenFilterFactory} |   0
 ...=> org.apache.lucene.analysis.TokenizerFactory} |   0
 .../opennlp/TestOpenNLPChunkerFilterFactory.java   |   2 +-
 .../TestOpenNLPLemmatizerFilterFactory.java        |   2 +-
 .../opennlp/TestOpenNLPPOSFilterFactory.java       |   2 +-
 .../opennlp/TestOpenNLPSentenceBreakIterator.java  |   2 +-
 .../opennlp/TestOpenNLPTokenizerFactory.java       |   2 +-
 .../phonetic/BeiderMorseFilterFactory.java         |   2 +-
 .../DaitchMokotoffSoundexFilterFactory.java        |   2 +-
 .../phonetic/DoubleMetaphoneFilterFactory.java     |   2 +-
 .../analysis/phonetic/PhoneticFilterFactory.java   |   6 +-
 ... org.apache.lucene.analysis.TokenFilterFactory} |   0
 .../phonetic/TestPhoneticFilterFactory.java        |   2 +-
 .../cn/smart/HMMChineseTokenizerFactory.java       |   2 +-
 ...=> org.apache.lucene.analysis.TokenizerFactory} |   0
 .../cn/smart/TestHMMChineseTokenizerFactory.java   |   2 +-
 .../stempel/StempelPolishStemFilterFactory.java    |   2 +-
 ... org.apache.lucene.analysis.TokenFilterFactory} |   0
 .../byTask/tasks/AnalyzerFactoryTask.java          |  10 +-
 .../benchmark/byTask/utils/AnalyzerFactory.java    |   6 +-
 .../lucene/benchmark/quality/TestQualityRun.java   |   2 +-
 .../lucene/analysis}/AbstractAnalysisFactory.java  |   7 +-
 .../apache/lucene/analysis}/AnalysisSPILoader.java |   2 +-
 .../apache/lucene/analysis}/CharFilterFactory.java |   4 +-
 .../lucene/analysis}/TokenFilterFactory.java       |   4 +-
 .../apache/lucene/analysis}/TokenizerFactory.java  |   4 +-
 .../standard/StandardTokenizerFactory.java         |   2 +-
 .../lucene87/LZ4WithPresetDictCompressionMode.java |   4 +-
 .../lucene87/Lucene87StoredFieldsFormat.java       |   6 +-
 .../apache/lucene/store/ByteBuffersDataOutput.java |  15 +-
 .../lucene}/util/ClasspathResourceLoader.java      |   4 +-
 .../org/apache/lucene}/util/ResourceLoader.java    |   2 +-
 .../apache/lucene}/util/ResourceLoaderAware.java   |   2 +-
 .../org.apache.lucene.analysis.TokenizerFactory}   |   2 +-
 .../org.apache.lucene.analysis.CharFilterFactory}  |   2 +-
 .../org.apache.lucene.analysis.TokenFilterFactory} |   2 +-
 .../lucene/analysis/FakeCharFilterFactory.java     |  24 +-
 .../lucene/analysis/FakeTokenFilterFactory.java    |  23 +-
 .../analysis}/TestAbstractAnalysisFactory.java     |  18 +-
 .../lucene/analysis}/TestAnalysisSPILoader.java    |  58 ++---
 .../analysis/standard/TestStandardFactories.java   |  63 +++++
 .../lucene/store/TestByteBuffersDataOutput.java    |  42 ++++
 .../lucene/facet/taxonomy/TaxonomyFacetLabels.java | 195 ++++++++++++++++
 .../org/apache/lucene/facet/FacetTestCase.java     |  42 +++-
 .../facet/taxonomy/TestTaxonomyFacetCounts.java    |  44 +++-
 .../facet/taxonomy/TestTaxonomyFacetLabels.java    | 194 ++++++++++++++++
 lucene/luke/build.gradle                           |   2 -
 .../analysis/AnalysisChainDialogFactory.java       |   6 +-
 .../lucene/luke/models/analysis/Analysis.java      |   6 +-
 .../lucene/luke/models/analysis/AnalysisImpl.java  |   6 +-
 .../luke/models/util/twentynewsgroups/Message.java |   2 +-
 .../analyzing/SuggestStopFilterFactory.java        |   6 +-
 ... org.apache.lucene.analysis.TokenFilterFactory} |   0
 .../analyzing/TestSuggestStopFilterFactory.java    |   4 +-
 .../analysis}/BaseTokenStreamFactoryTestCase.java  |  10 +-
 solr/CHANGES.txt                                   |  20 +-
 solr/bin/solr                                      |   9 +-
 solr/bin/solr.cmd                                  |   4 +
 solr/bin/solr.in.sh                                |  10 +-
 .../org/apache/solr/schema/ICUCollationField.java  |   2 +-
 .../apache/solr/schema/TestICUCollationField.java  |   2 +-
 .../SolrStopwordsCarrot2LexicalDataFactory.java    |   2 +-
 .../apache/solr/ltr/search/LTRQParserPlugin.java   |   4 +-
 .../solr/analysis/LowerCaseTokenizerFactory.java   |   2 +-
 .../analysis/ReversedWildcardFilterFactory.java    |   2 +-
 .../org/apache/solr/analysis/TokenizerChain.java   |   6 +-
 .../src/java/org/apache/solr/api/AnnotatedApi.java |  15 +-
 .../apache/solr/api/CustomContainerPlugins.java    |  13 +-
 .../src/java/org/apache/solr/cloud/Overseer.java   |  55 +++--
 .../apache/solr/cluster/events/ClusterEvent.java   |  10 +-
 .../events/ClusterPropertiesChangedEvent.java      |   6 +
 .../solr/cluster/events/CollectionsAddedEvent.java |   7 +
 .../cluster/events/CollectionsRemovedEvent.java    |   7 +
 .../apache/solr/cluster/events/NodesDownEvent.java |   7 +
 .../apache/solr/cluster/events/NodesUpEvent.java   |   7 +
 .../solr/cluster/events/ReplicasDownEvent.java     |   7 +
 .../events/impl/ClusterEventProducerImpl.java      |  21 +-
 .../impl/CollectionsRepairEventListener.java       |   3 +-
 .../src/java/org/apache/solr/core/ConfigSet.java   |   2 +-
 .../java/org/apache/solr/core/CoreContainer.java   | 103 +++++++--
 .../src/java/org/apache/solr/core/PluginBag.java   |   4 +-
 .../org/apache/solr/core/RateLimiterConfig.java    |  53 +++++
 .../src/java/org/apache/solr/core/SolrCore.java    |   4 +-
 .../org/apache/solr/core/SolrResourceLoader.java   |  10 +-
 .../solr/handler/AnalysisRequestHandlerBase.java   |   6 +-
 .../java/org/apache/solr/handler/ClusterAPI.java   |  19 +-
 .../org/apache/solr/handler/SolrConfigHandler.java |   2 +-
 .../solr/handler/admin/ContainerPluginsApi.java    |   6 +-
 .../solr/handler/admin/LukeRequestHandler.java     |   6 +-
 .../component/PhrasesIdentificationComponent.java  |   2 +-
 .../solr/handler/component/TermsComponent.java     |  46 ----
 .../solr/handler/tagger/TaggerRequestHandler.java  |   2 +-
 .../apache/solr/parser/SolrQueryParserBase.java    |   2 +-
 .../solr/pkg/PackageListeningClassLoader.java      |   2 +-
 .../org/apache/solr/pkg/PackagePluginHolder.java   |   2 +-
 .../analysis/BaseManagedTokenFilterFactory.java    |   6 +-
 .../analysis/ManagedSynonymFilterFactory.java      |   2 +-
 .../analysis/ManagedSynonymGraphFilterFactory.java |   2 +-
 .../org/apache/solr/schema/CollationField.java     |   2 +-
 .../java/org/apache/solr/schema/CurrencyField.java |   2 +-
 .../org/apache/solr/schema/CurrencyFieldType.java  |   4 +-
 .../apache/solr/schema/ExchangeRateProvider.java   |   2 +-
 .../src/java/org/apache/solr/schema/FieldType.java |   8 +-
 .../apache/solr/schema/FieldTypePluginLoader.java  |   6 +-
 .../solr/schema/FileExchangeRateProvider.java      |   2 +-
 .../org/apache/solr/schema/ManagedIndexSchema.java |   8 +-
 .../solr/schema/OpenExchangeRatesOrgProvider.java  |   2 +-
 .../java/org/apache/solr/schema/SchemaManager.java |   4 +-
 .../apache/solr/search/ExtendedDismaxQParser.java  |   2 +-
 .../apache/solr/search/stats/ExactStatsCache.java  |   6 +
 .../solr/security/MultiDestinationAuditLogger.java |   4 +-
 .../org/apache/solr/servlet/QueryRateLimiter.java  | 107 +++++++--
 .../org/apache/solr/servlet/RateLimitManager.java  |  31 ++-
 .../apache/solr/servlet/RequestRateLimiter.java    |  55 +----
 .../apache/solr/servlet/SolrDispatchFilter.java    |  18 +-
 .../java/org/apache/solr/util/PayloadUtils.java    |   2 +-
 .../java/org/apache/solr/util/SafeXMLParsing.java  |   2 +-
 .../org/apache/solr/util/SystemIdResolver.java     |   2 +-
 .../apache/solr/util/xslt/TransformerProvider.java |   2 +-
 solr/core/src/resources/ImplicitPlugins.json       |   3 +-
 ... org.apache.lucene.analysis.TokenFilterFactory} |   0
 .../MyPatternReplaceCharFilterFactory.java}        |  15 +-
 .../runtimecode/MyTextField.java}                  |  11 +-
 .../runtimecode/MyWhitespaceTokenizerFactory.java} |  14 +-
 .../test-files/runtimecode/schema-plugins.jar.bin  | Bin 6814 -> 1461 bytes
 .../analysis/ProtectedTermFilterFactoryTest.java   |   2 +-
 .../analysis/TestWordDelimiterFilterFactory.java   |   2 +-
 .../analysis/ThrowingMockTokenFilterFactory.java   |   2 +-
 .../apache/solr/analysis/TokenizerChainTest.java   |   2 +-
 .../test/org/apache/solr/cloud/OverseerTest.java   |  24 +-
 .../test/org/apache/solr/cloud/ZkFailoverTest.java |  35 ++-
 .../solr/cluster/events/AllEventsListener.java     |   3 -
 .../cluster/events/ClusterEventProducerTest.java   | 127 +++++++++-
 .../org/apache/solr/core/ResourceLoaderTest.java   |   6 +-
 .../handler/FieldAnalysisRequestHandlerTest.java   |   4 +-
 .../apache/solr/handler/TestContainerPlugin.java   |   8 +-
 .../component/CustomTermsComponentTest.java        | 257 ---------------------
 .../component/DistributedTermsComponentTest.java   |  32 +--
 .../tagger/WordLengthTaggingFilterFactory.java     |   2 +-
 .../src/test/org/apache/solr/pkg/TestPackages.java | 197 ++++++++++------
 .../apache/solr/rest/schema/TestBulkSchemaAPI.java |   2 +-
 .../apache/solr/schema/CustomAnalyzerStrField.java |   4 +-
 .../solr/schema/MockExchangeRateProvider.java      |   2 +-
 .../schema/OpenExchangeRatesOrgProviderTest.java   |   2 +-
 .../solr/search/stats/TestExactStatsCache.java     |  74 +++++-
 .../solr/servlet/TestRequestRateLimiter.java       |  21 +-
 .../org/apache/solr/util/TestSafeXMLParsing.java   |   2 +-
 .../org/apache/solr/util/TestSystemIdResolver.java |   2 +-
 solr/solr-ref-guide/src/filter-descriptions.adoc   |   2 +-
 .../src/major-changes-in-solr-9.adoc               |   7 +
 solr/solr-ref-guide/src/rate-limiters.adoc         |  64 ++---
 solr/solr-ref-guide/src/the-terms-component.adoc   |   1 -
 solr/solr-ref-guide/src/tokenizers.adoc            |   2 +-
 .../client/solrj/impl/BaseCloudSolrClient.java     |   8 +-
 .../client/solrj/io/stream/ScoreNodesStream.java   |   4 -
 .../solrj/request/beans/RateLimiterMeta.java       |  73 ++++++
 .../solr/analysis/MockCharFilterFactory.java       |   2 +-
 .../solr/analysis/MockTokenFilterFactory.java      |   2 +-
 .../apache/solr/analysis/MockTokenizerFactory.java |   2 +-
 .../analysis/StringMockSolrResourceLoader.java     |   2 +-
 445 files changed, 2524 insertions(+), 1577 deletions(-)
 create mode 100644 gradle/generation/nori.gradle
 rename lucene/analysis/common/src/java/org/apache/lucene/analysis/{standard => classic}/ClassicAnalyzer.java (97%)
 rename lucene/analysis/common/src/java/org/apache/lucene/analysis/{standard => classic}/ClassicFilter.java (98%)
 rename lucene/analysis/common/src/java/org/apache/lucene/analysis/{standard => classic}/ClassicFilterFactory.java (94%)
 rename lucene/analysis/common/src/java/org/apache/lucene/analysis/{standard => classic}/ClassicTokenizer.java (97%)
 rename lucene/analysis/common/src/java/org/apache/lucene/analysis/{standard => classic}/ClassicTokenizerFactory.java (92%)
 rename lucene/analysis/common/src/java/org/apache/lucene/analysis/{standard => classic}/ClassicTokenizerImpl.java (99%)
 rename lucene/analysis/common/src/java/org/apache/lucene/analysis/{standard => classic}/ClassicTokenizerImpl.jflex (100%)
 copy lucene/analysis/common/src/java/org/apache/lucene/analysis/{standard => classic}/package.html (53%)
 rename lucene/analysis/common/src/java/org/apache/lucene/analysis/{standard => email}/ASCIITLD.jflex-macro (100%)
 rename lucene/analysis/common/src/java/org/apache/lucene/analysis/{standard => email}/UAX29URLEmailAnalyzer.java (96%)
 rename lucene/analysis/common/src/java/org/apache/lucene/analysis/{standard => email}/UAX29URLEmailTokenizer.java (97%)
 rename lucene/analysis/common/src/java/org/apache/lucene/analysis/{standard => email}/UAX29URLEmailTokenizerFactory.java (93%)
 rename lucene/analysis/common/src/java/org/apache/lucene/analysis/{standard => email}/UAX29URLEmailTokenizerImpl.java (99%)
 rename lucene/analysis/common/src/java/org/apache/lucene/analysis/{standard => email}/UAX29URLEmailTokenizerImpl.jflex (99%)
 rename lucene/analysis/common/src/java/org/apache/lucene/analysis/{standard => email}/package.html (55%)
 rename lucene/analysis/common/src/resources/META-INF/services/{org.apache.lucene.analysis.util.CharFilterFactory => org.apache.lucene.analysis.CharFilterFactory} (100%)
 rename lucene/analysis/common/src/resources/META-INF/services/{org.apache.lucene.analysis.util.TokenFilterFactory => org.apache.lucene.analysis.TokenFilterFactory} (99%)
 rename lucene/analysis/common/src/resources/META-INF/services/{org.apache.lucene.analysis.util.TokenizerFactory => org.apache.lucene.analysis.TokenizerFactory} (88%)
 rename lucene/analysis/common/src/test/org/apache/lucene/analysis/{standard => classic}/TestClassicAnalyzer.java (99%)
 create mode 100644 lucene/analysis/common/src/test/org/apache/lucene/analysis/classic/TestClassicFactories.java
 create mode 100644 lucene/analysis/common/src/test/org/apache/lucene/analysis/core/TestCoreFactories.java
 rename lucene/analysis/common/src/test/org/apache/lucene/analysis/{standard => email}/LuceneResourcesWikiPage.html (100%)
 rename lucene/analysis/common/src/test/org/apache/lucene/analysis/{standard => email}/LuceneResourcesWikiPageURLs.txt (100%)
 rename lucene/analysis/common/src/test/org/apache/lucene/analysis/{standard => email}/TestUAX29URLEmailAnalyzer.java (99%)
 rename lucene/analysis/common/src/test/org/apache/lucene/analysis/{standard => email}/TestUAX29URLEmailTokenizer.java (99%)
 rename lucene/analysis/common/src/test/org/apache/lucene/analysis/{standard => email}/TestUAX29URLEmailTokenizerFactory.java (98%)
 rename lucene/analysis/common/src/test/org/apache/lucene/analysis/{standard => email}/email.addresses.from.random.text.with.email.addresses.txt (100%)
 rename lucene/analysis/common/src/test/org/apache/lucene/analysis/{standard => email}/random.text.with.email.addresses.txt (100%)
 rename lucene/analysis/common/src/test/org/apache/lucene/analysis/{standard => email}/random.text.with.urls.txt (100%)
 rename lucene/analysis/common/src/test/org/apache/lucene/analysis/{standard => email}/urls.from.random.text.with.urls.txt (100%)
 copy lucene/analysis/common/src/test/org/apache/lucene/analysis/miscellaneous/{TestScandinavianFoldingFilterFactory.java => TestMiscellaneousFactories.java} (65%)
 delete mode 100644 lucene/analysis/common/src/test/org/apache/lucene/analysis/standard/TestStandardFactories.java
 rename lucene/analysis/icu/src/resources/META-INF/services/{org.apache.lucene.analysis.util.CharFilterFactory => org.apache.lucene.analysis.CharFilterFactory} (100%)
 rename lucene/analysis/icu/src/resources/META-INF/services/{org.apache.lucene.analysis.util.TokenFilterFactory => org.apache.lucene.analysis.TokenFilterFactory} (100%)
 rename lucene/analysis/icu/src/resources/META-INF/services/{org.apache.lucene.analysis.util.TokenizerFactory => org.apache.lucene.analysis.TokenizerFactory} (100%)
 rename lucene/analysis/kuromoji/src/resources/META-INF/services/{org.apache.lucene.analysis.util.CharFilterFactory => org.apache.lucene.analysis.CharFilterFactory} (100%)
 rename lucene/analysis/kuromoji/src/resources/META-INF/services/{org.apache.lucene.analysis.util.TokenFilterFactory => org.apache.lucene.analysis.TokenFilterFactory} (100%)
 rename lucene/analysis/kuromoji/src/resources/META-INF/services/{org.apache.lucene.analysis.util.TokenizerFactory => org.apache.lucene.analysis.TokenizerFactory} (100%)
 rename lucene/analysis/morfologik/src/resources/META-INF/services/{org.apache.lucene.analysis.util.TokenFilterFactory => org.apache.lucene.analysis.TokenFilterFactory} (100%)
 rename lucene/analysis/nori/src/resources/META-INF/services/{org.apache.lucene.analysis.util.TokenFilterFactory => org.apache.lucene.analysis.TokenFilterFactory} (100%)
 copy lucene/analysis/nori/src/resources/META-INF/services/{org.apache.lucene.analysis.util.TokenizerFactory => org.apache.lucene.analysis.TokenizerFactory} (100%)
 rename lucene/analysis/opennlp/src/resources/META-INF/services/{org.apache.lucene.analysis.util.TokenFilterFactory => org.apache.lucene.analysis.TokenFilterFactory} (100%)
 rename lucene/analysis/opennlp/src/resources/META-INF/services/{org.apache.lucene.analysis.util.TokenizerFactory => org.apache.lucene.analysis.TokenizerFactory} (100%)
 rename lucene/analysis/phonetic/src/resources/META-INF/services/{org.apache.lucene.analysis.util.TokenFilterFactory => org.apache.lucene.analysis.TokenFilterFactory} (100%)
 rename lucene/analysis/smartcn/src/resources/META-INF/services/{org.apache.lucene.analysis.util.TokenizerFactory => org.apache.lucene.analysis.TokenizerFactory} (100%)
 rename lucene/analysis/stempel/src/resources/META-INF/services/{org.apache.lucene.analysis.util.TokenFilterFactory => org.apache.lucene.analysis.TokenFilterFactory} (100%)
 rename lucene/{analysis/common/src/java/org/apache/lucene/analysis/util => core/src/java/org/apache/lucene/analysis}/AbstractAnalysisFactory.java (98%)
 rename lucene/{analysis/common/src/java/org/apache/lucene/analysis/util => core/src/java/org/apache/lucene/analysis}/AnalysisSPILoader.java (99%)
 rename lucene/{analysis/common/src/java/org/apache/lucene/analysis/util => core/src/java/org/apache/lucene/analysis}/CharFilterFactory.java (97%)
 rename lucene/{analysis/common/src/java/org/apache/lucene/analysis/util => core/src/java/org/apache/lucene/analysis}/TokenFilterFactory.java (97%)
 rename lucene/{analysis/common/src/java/org/apache/lucene/analysis/util => core/src/java/org/apache/lucene/analysis}/TokenizerFactory.java (96%)
 rename lucene/{analysis/common => core}/src/java/org/apache/lucene/analysis/standard/StandardTokenizerFactory.java (97%)
 rename lucene/{analysis/common/src/java/org/apache/lucene/analysis => core/src/java/org/apache/lucene}/util/ClasspathResourceLoader.java (97%)
 rename lucene/{analysis/common/src/java/org/apache/lucene/analysis => core/src/java/org/apache/lucene}/util/ResourceLoader.java (97%)
 rename lucene/{analysis/common/src/java/org/apache/lucene/analysis => core/src/java/org/apache/lucene}/util/ResourceLoaderAware.java (96%)
 copy lucene/{analysis/nori/src/resources/META-INF/services/org.apache.lucene.analysis.util.TokenizerFactory => core/src/resources/META-INF/services/org.apache.lucene.analysis.TokenizerFactory} (92%)
 copy lucene/{analysis/nori/src/resources/META-INF/services/org.apache.lucene.analysis.util.TokenizerFactory => core/src/test/META-INF/services/org.apache.lucene.analysis.CharFilterFactory} (93%)
 rename lucene/{analysis/nori/src/resources/META-INF/services/org.apache.lucene.analysis.util.TokenizerFactory => core/src/test/META-INF/services/org.apache.lucene.analysis.TokenFilterFactory} (93%)
 copy solr/core/src/java/org/apache/solr/cluster/events/ClusterPropertiesChangedEvent.java => lucene/core/src/test/org/apache/lucene/analysis/FakeCharFilterFactory.java (63%)
 copy solr/core/src/java/org/apache/solr/cluster/events/ClusterPropertiesChangedEvent.java => lucene/core/src/test/org/apache/lucene/analysis/FakeTokenFilterFactory.java (63%)
 rename lucene/{analysis/common/src/test/org/apache/lucene/analysis/util => core/src/test/org/apache/lucene/analysis}/TestAbstractAnalysisFactory.java (59%)
 rename lucene/{analysis/common/src/test/org/apache/lucene/analysis/util => core/src/test/org/apache/lucene/analysis}/TestAnalysisSPILoader.java (54%)
 create mode 100644 lucene/core/src/test/org/apache/lucene/analysis/standard/TestStandardFactories.java
 create mode 100644 lucene/facet/src/java/org/apache/lucene/facet/taxonomy/TaxonomyFacetLabels.java
 create mode 100644 lucene/facet/src/test/org/apache/lucene/facet/taxonomy/TestTaxonomyFacetLabels.java
 rename lucene/suggest/src/resources/META-INF/services/{org.apache.lucene.analysis.util.TokenFilterFactory => org.apache.lucene.analysis.TokenFilterFactory} (100%)
 rename lucene/{analysis/common/src/test/org/apache/lucene/analysis/util => test-framework/src/java/org/apache/lucene/analysis}/BaseTokenStreamFactoryTestCase.java (93%)
 create mode 100644 solr/core/src/java/org/apache/solr/core/RateLimiterConfig.java
 rename solr/core/src/resources/META-INF/services/{org.apache.lucene.analysis.util.TokenFilterFactory => org.apache.lucene.analysis.TokenFilterFactory} (100%)
 copy solr/core/src/{test/org/apache/solr/search/stats/TestExactStatsCache.java => test-files/runtimecode/MyPatternReplaceCharFilterFactory.java} (74%)
 copy solr/core/src/{test/org/apache/solr/search/stats/TestExactStatsCache.java => test-files/runtimecode/MyTextField.java} (79%)
 copy solr/core/src/{test/org/apache/solr/search/stats/TestExactStatsCache.java => test-files/runtimecode/MyWhitespaceTokenizerFactory.java} (75%)
 delete mode 100644 solr/core/src/test/org/apache/solr/handler/component/CustomTermsComponentTest.java
 create mode 100644 solr/solrj/src/java/org/apache/solr/client/solrj/request/beans/RateLimiterMeta.java


[lucene-solr] 02/02: SOLR-14749: Fix the race between plugin loading and registration and Overseer leader election. Make events implement MapWriter-s. Add more unit tests.

Posted by ab...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ab pushed a commit to branch jira/solr-14749
in repository https://gitbox.apache.org/repos/asf/lucene-solr.git

commit a8658cef6cf14bb2c7ee667801b5241e4e875467
Author: Andrzej Bialecki <ab...@apache.org>
AuthorDate: Thu Oct 1 08:04:08 2020 +0200

    SOLR-14749: Fix the race between plugin loading and registration and
    Overseer leader election. Make events implement MapWriter-s.
    Add more unit tests.
---
 .../src/java/org/apache/solr/api/AnnotatedApi.java |  15 ++-
 .../apache/solr/api/CustomContainerPlugins.java    |  11 +-
 .../src/java/org/apache/solr/cloud/Overseer.java   |  55 ++++++---
 .../apache/solr/cluster/events/ClusterEvent.java   |  10 +-
 .../events/ClusterPropertiesChangedEvent.java      |   6 +
 .../solr/cluster/events/CollectionsAddedEvent.java |   7 ++
 .../cluster/events/CollectionsRemovedEvent.java    |   7 ++
 .../apache/solr/cluster/events/NodesDownEvent.java |   7 ++
 .../apache/solr/cluster/events/NodesUpEvent.java   |   7 ++
 .../solr/cluster/events/ReplicasDownEvent.java     |   7 ++
 .../events/impl/ClusterEventProducerImpl.java      |  21 +---
 .../impl/CollectionsRepairEventListener.java       |   3 +-
 .../java/org/apache/solr/core/CoreContainer.java   |  95 ++++++++++++---
 .../solr/handler/admin/ContainerPluginsApi.java    |   6 +-
 .../test/org/apache/solr/cloud/OverseerTest.java   |  24 ++--
 .../solr/cluster/events/AllEventsListener.java     |   3 -
 .../cluster/events/ClusterEventProducerTest.java   | 127 ++++++++++++++++++++-
 .../apache/solr/handler/TestContainerPlugin.java   |   4 +-
 18 files changed, 335 insertions(+), 80 deletions(-)

diff --git a/solr/core/src/java/org/apache/solr/api/AnnotatedApi.java b/solr/core/src/java/org/apache/solr/api/AnnotatedApi.java
index fd77413..1558f1c 100644
--- a/solr/core/src/java/org/apache/solr/api/AnnotatedApi.java
+++ b/solr/core/src/java/org/apache/solr/api/AnnotatedApi.java
@@ -85,9 +85,18 @@ public class AnnotatedApi extends Api implements PermissionNameProvider , Closea
   }
 
   public static List<Api> getApis(Object obj) {
-    return getApis(obj.getClass(), obj);
+    return getApis(obj.getClass(), obj, true);
   }
-  public static List<Api> getApis(Class<? extends Object> theClass , Object obj)  {
+
+  /**
+   * Get a list of Api-s supported by this class.
+   * @param theClass class
+   * @param obj object of this class (may be null)
+   * @param required if true then an exception is thrown if no Api-s can be retrieved, if false
+   *                then absence of Api-s is silently ignored.
+   * @return list of discovered Api-s
+   */
+  public static List<Api> getApis(Class<? extends Object> theClass , Object obj, boolean required)  {
     Class<?> klas = null;
     try {
       klas = MethodHandles.publicLookup().accessClass(theClass);
@@ -122,7 +131,7 @@ public class AnnotatedApi extends Api implements PermissionNameProvider , Closea
         SpecProvider specProvider = readSpec(endPoint, Collections.singletonList(m));
         apis.add(new AnnotatedApi(specProvider, endPoint, Collections.singletonMap("", cmd), null));
       }
-      if (apis.isEmpty()) {
+      if (required && apis.isEmpty()) {
         throw new RuntimeException("Invalid Class : " + klas.getName() + " No @EndPoints");
       }
 
diff --git a/solr/core/src/java/org/apache/solr/api/CustomContainerPlugins.java b/solr/core/src/java/org/apache/solr/api/CustomContainerPlugins.java
index c6bfca6..ec3e4e3 100644
--- a/solr/core/src/java/org/apache/solr/api/CustomContainerPlugins.java
+++ b/solr/core/src/java/org/apache/solr/api/CustomContainerPlugins.java
@@ -180,9 +180,10 @@ public class CustomContainerPlugins implements ClusterPropertiesListener, MapWri
       Object instance = newApiInfo.getInstance();
       if (instance instanceof ClusterSingleton) {
         ClusterSingleton singleton = (ClusterSingleton) instance;
-        coreContainer.getClusterSingletons().put(singleton.getName(), singleton);
+        coreContainer.getClusterSingletons().getSingletons().put(singleton.getName(), singleton);
         // easy check to see if we should immediately start this singleton
-        if (coreContainer.getClusterEventProducer().isRunning()) {
+        if (coreContainer.getClusterEventProducer() != null &&
+            coreContainer.getClusterEventProducer().isRunning()) {
           try {
             singleton.start();
           } catch (Exception exc) {
@@ -206,7 +207,7 @@ public class CustomContainerPlugins implements ClusterPropertiesListener, MapWri
       if (instance instanceof ClusterSingleton) {
         ClusterSingleton singleton = (ClusterSingleton) instance;
         singleton.stop();
-        coreContainer.getClusterSingletons().remove(singleton.getName());
+        coreContainer.getClusterSingletons().getSingletons().remove(singleton.getName());
       }
       if (instance instanceof ClusterEventListener) {
         coreContainer.getClusterEventProducer().unregisterListener((ClusterEventListener) instance);
@@ -322,7 +323,7 @@ public class CustomContainerPlugins implements ClusterPropertiesListener, MapWri
       }
 
       try {
-        List<Api> apis = AnnotatedApi.getApis(klas, null);
+        List<Api> apis = AnnotatedApi.getApis(klas, null, false);
         for (Object api : apis) {
           EndPoint endPoint = ((AnnotatedApi) api).getEndPoint();
           if (endPoint.path().length > 1 || endPoint.method().length > 1) {
@@ -374,7 +375,7 @@ public class CustomContainerPlugins implements ClusterPropertiesListener, MapWri
         }
       }
       this.holders = new ArrayList<>();
-      for (Api api : AnnotatedApi.getApis(instance)) {
+      for (Api api : AnnotatedApi.getApis(instance.getClass(), instance, false)) {
         holders.add(new ApiHolder((AnnotatedApi) api));
       }
     }
diff --git a/solr/core/src/java/org/apache/solr/cloud/Overseer.java b/solr/core/src/java/org/apache/solr/cloud/Overseer.java
index b8403f4..2465f8a 100644
--- a/solr/core/src/java/org/apache/solr/cloud/Overseer.java
+++ b/solr/core/src/java/org/apache/solr/cloud/Overseer.java
@@ -29,6 +29,8 @@ import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 import java.util.function.BiConsumer;
 
 import org.apache.lucene.util.Version;
@@ -782,34 +784,48 @@ public class Overseer implements SolrCloseable {
    * Start {@link ClusterSingleton} plugins when we become the leader.
    */
   public void startClusterSingletons() {
-    Map<String, ClusterSingleton> singletons = getCoreContainer().getClusterSingletons();
-    if (singletons == null) {
-      return;
-    }
-    if (isClosed()) {
-      return;
-    }
-    singletons.forEach((name, singleton) -> {
+    CoreContainer.ClusterSingletons singletons = getCoreContainer().getClusterSingletons();
+    final Runnable initializer = () -> {
+      if (isClosed()) {
+        return;
+      }
       try {
-        singleton.start();
-        if (singleton instanceof ClusterEventListener) {
-          getCoreContainer().getClusterEventProducer().registerListener((ClusterEventListener) singleton);
-        }
-      } catch (Exception e) {
-        log.warn("Exception starting ClusterSingleton {}: {}", singleton, e);
+        singletons.waitUntilReady(60, TimeUnit.SECONDS);
+      } catch (InterruptedException e) {
+        log.warn("Interrupted initialization of ClusterSingleton-s");
+        return;
+      } catch (TimeoutException te) {
+        log.warn("Timed out during initialization of ClusterSingleton-s");
+        return;
       }
-    });
+      singletons.getSingletons().forEach((name, singleton) -> {
+        try {
+          singleton.start();
+          if (singleton instanceof ClusterEventListener) {
+            getCoreContainer().getClusterEventProducer().registerListener((ClusterEventListener) singleton);
+          }
+        } catch (Exception e) {
+          log.warn("Exception starting ClusterSingleton {}: {}", singleton, e);
+        }
+      });
+    };
+    if (singletons.isReady()) {
+      // wait until all singleton-s are ready for the first startup
+      getCoreContainer().runAsync(initializer);
+    } else {
+      initializer.run();
+    }
   }
 
   /**
    * Stop {@link ClusterSingleton} plugins when we lose leadership.
    */
   private void stopClusterSingletons() {
-    Map<String, ClusterSingleton> singletons = getCoreContainer().getClusterSingletons();
+    CoreContainer.ClusterSingletons singletons = getCoreContainer().getClusterSingletons();
     if (singletons == null) {
       return;
     }
-    singletons.forEach((name, singleton) -> {
+    singletons.getSingletons().forEach((name, singleton) -> {
       if (singleton instanceof ClusterEventListener) {
         getCoreContainer().getClusterEventProducer().unregisterListener((ClusterEventListener) singleton);
       }
@@ -856,10 +872,13 @@ public class Overseer implements SolrCloseable {
     if (this.id != null) {
       log.info("Overseer (id={}) closing", id);
     }
+    // stop singletons only on the leader
+    if (!this.closed) {
+      stopClusterSingletons();
+    }
     this.closed = true;
     doClose();
 
-    stopClusterSingletons();
 
     assert ObjectReleaseTracker.release(this);
   }
diff --git a/solr/core/src/java/org/apache/solr/cluster/events/ClusterEvent.java b/solr/core/src/java/org/apache/solr/cluster/events/ClusterEvent.java
index 1929f0c..2dc7a32 100644
--- a/solr/core/src/java/org/apache/solr/cluster/events/ClusterEvent.java
+++ b/solr/core/src/java/org/apache/solr/cluster/events/ClusterEvent.java
@@ -16,12 +16,15 @@
  */
 package org.apache.solr.cluster.events;
 
+import org.apache.solr.common.MapWriter;
+
+import java.io.IOException;
 import java.time.Instant;
 
 /**
  * Cluster-level event.
  */
-public interface ClusterEvent {
+public interface ClusterEvent extends MapWriter {
 
   enum EventType {
     /** One or more nodes went down. */
@@ -46,4 +49,9 @@ public interface ClusterEvent {
   /** Get event timestamp. This is the instant when the event was generated (not necessarily when
    * the underlying condition first occurred). */
   Instant getTimestamp();
+
+  default void writeMap(EntryWriter ew) throws IOException {
+    ew.put("type", getType());
+    ew.put("timestamp", getTimestamp().toEpochMilli());
+  }
 }
diff --git a/solr/core/src/java/org/apache/solr/cluster/events/ClusterPropertiesChangedEvent.java b/solr/core/src/java/org/apache/solr/cluster/events/ClusterPropertiesChangedEvent.java
index ee513d8..ad9c0b8 100644
--- a/solr/core/src/java/org/apache/solr/cluster/events/ClusterPropertiesChangedEvent.java
+++ b/solr/core/src/java/org/apache/solr/cluster/events/ClusterPropertiesChangedEvent.java
@@ -16,6 +16,7 @@
  */
 package org.apache.solr.cluster.events;
 
+import java.io.IOException;
 import java.util.Map;
 
 /**
@@ -30,4 +31,9 @@ public interface ClusterPropertiesChangedEvent extends ClusterEvent {
 
   Map<String, Object> getNewClusterProperties();
 
+  @Override
+  default void writeMap(EntryWriter ew) throws IOException {
+    ClusterEvent.super.writeMap(ew);
+    ew.put("newClusterProperties", getNewClusterProperties());
+  }
 }
diff --git a/solr/core/src/java/org/apache/solr/cluster/events/CollectionsAddedEvent.java b/solr/core/src/java/org/apache/solr/cluster/events/CollectionsAddedEvent.java
index 0b1c46b..78046f8 100644
--- a/solr/core/src/java/org/apache/solr/cluster/events/CollectionsAddedEvent.java
+++ b/solr/core/src/java/org/apache/solr/cluster/events/CollectionsAddedEvent.java
@@ -16,6 +16,7 @@
  */
 package org.apache.solr.cluster.events;
 
+import java.io.IOException;
 import java.util.Iterator;
 
 /**
@@ -29,4 +30,10 @@ public interface CollectionsAddedEvent extends ClusterEvent {
   }
 
   Iterator<String> getCollectionNames();
+
+  @Override
+  default void writeMap(EntryWriter ew) throws IOException {
+    ClusterEvent.super.writeMap(ew);
+    ew.put("collectionNames", getCollectionNames());
+  }
 }
diff --git a/solr/core/src/java/org/apache/solr/cluster/events/CollectionsRemovedEvent.java b/solr/core/src/java/org/apache/solr/cluster/events/CollectionsRemovedEvent.java
index e6fc64e..a93be4c 100644
--- a/solr/core/src/java/org/apache/solr/cluster/events/CollectionsRemovedEvent.java
+++ b/solr/core/src/java/org/apache/solr/cluster/events/CollectionsRemovedEvent.java
@@ -16,6 +16,7 @@
  */
 package org.apache.solr.cluster.events;
 
+import java.io.IOException;
 import java.util.Iterator;
 
 /**
@@ -29,4 +30,10 @@ public interface CollectionsRemovedEvent extends ClusterEvent {
   }
 
   Iterator<String> getCollectionNames();
+
+  @Override
+  default void writeMap(EntryWriter ew) throws IOException {
+    ClusterEvent.super.writeMap(ew);
+    ew.put("collectionNames", getCollectionNames());
+  }
 }
diff --git a/solr/core/src/java/org/apache/solr/cluster/events/NodesDownEvent.java b/solr/core/src/java/org/apache/solr/cluster/events/NodesDownEvent.java
index a8e7a2e..5001ccb 100644
--- a/solr/core/src/java/org/apache/solr/cluster/events/NodesDownEvent.java
+++ b/solr/core/src/java/org/apache/solr/cluster/events/NodesDownEvent.java
@@ -16,6 +16,7 @@
  */
 package org.apache.solr.cluster.events;
 
+import java.io.IOException;
 import java.util.Iterator;
 
 /**
@@ -29,4 +30,10 @@ public interface NodesDownEvent extends ClusterEvent {
   }
 
   Iterator<String> getNodeNames();
+
+  @Override
+  default void writeMap(EntryWriter ew) throws IOException {
+    ClusterEvent.super.writeMap(ew);
+    ew.put("nodeNames", getNodeNames());
+  }
 }
diff --git a/solr/core/src/java/org/apache/solr/cluster/events/NodesUpEvent.java b/solr/core/src/java/org/apache/solr/cluster/events/NodesUpEvent.java
index f83bf91..fa08f85 100644
--- a/solr/core/src/java/org/apache/solr/cluster/events/NodesUpEvent.java
+++ b/solr/core/src/java/org/apache/solr/cluster/events/NodesUpEvent.java
@@ -16,6 +16,7 @@
  */
 package org.apache.solr.cluster.events;
 
+import java.io.IOException;
 import java.util.Iterator;
 
 /**
@@ -29,4 +30,10 @@ public interface NodesUpEvent extends ClusterEvent {
   }
 
   Iterator<String> getNodeNames();
+
+  @Override
+  default void writeMap(EntryWriter ew) throws IOException {
+    ClusterEvent.super.writeMap(ew);
+    ew.put("nodeNames", getNodeNames());
+  }
 }
diff --git a/solr/core/src/java/org/apache/solr/cluster/events/ReplicasDownEvent.java b/solr/core/src/java/org/apache/solr/cluster/events/ReplicasDownEvent.java
index 69ec48c..1d3ce9b 100644
--- a/solr/core/src/java/org/apache/solr/cluster/events/ReplicasDownEvent.java
+++ b/solr/core/src/java/org/apache/solr/cluster/events/ReplicasDownEvent.java
@@ -18,6 +18,7 @@ package org.apache.solr.cluster.events;
 
 import org.apache.solr.common.cloud.Replica;
 
+import java.io.IOException;
 import java.util.Iterator;
 
 /**
@@ -31,4 +32,10 @@ public interface ReplicasDownEvent extends ClusterEvent {
   }
 
   Iterator<Replica> getReplicas();
+
+  @Override
+  default void writeMap(EntryWriter ew) throws IOException {
+    ClusterEvent.super.writeMap(ew);
+    ew.put("replicas", getReplicas());
+  }
 }
diff --git a/solr/core/src/java/org/apache/solr/cluster/events/impl/ClusterEventProducerImpl.java b/solr/core/src/java/org/apache/solr/cluster/events/impl/ClusterEventProducerImpl.java
index 5886d67..034fa8a 100644
--- a/solr/core/src/java/org/apache/solr/cluster/events/impl/ClusterEventProducerImpl.java
+++ b/solr/core/src/java/org/apache/solr/cluster/events/impl/ClusterEventProducerImpl.java
@@ -16,16 +16,12 @@
  */
 package org.apache.solr.cluster.events.impl;
 
-import java.io.Closeable;
-import java.io.IOException;
 import java.lang.invoke.MethodHandles;
 import java.time.Instant;
 import java.util.Arrays;
-import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
-import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.Set;
 
@@ -53,7 +49,7 @@ import org.slf4j.LoggerFactory;
  * (not in parallel) and in arbitrary order. This means that if any listener blocks the
  * processing other listeners may be invoked much later or not at all.</p>
  */
-public class ClusterEventProducerImpl implements ClusterEventProducer, ClusterSingleton, Closeable {
+public class ClusterEventProducerImpl implements ClusterEventProducer, ClusterSingleton {
   private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
 
   private final Map<ClusterEvent.EventType, Set<ClusterEventListener>> listeners = new HashMap<>();
@@ -62,7 +58,7 @@ public class ClusterEventProducerImpl implements ClusterEventProducer, ClusterSi
   private CloudCollectionsListener cloudCollectionsListener;
   private ClusterPropertiesListener clusterPropertiesListener;
   private ZkController zkController;
-  private boolean running;
+  private volatile boolean running;
 
   private final Set<ClusterEvent.EventType> supportedEvents =
       new HashSet<>(Arrays.asList(
@@ -73,8 +69,6 @@ public class ClusterEventProducerImpl implements ClusterEventProducer, ClusterSi
           ClusterEvent.EventType.CLUSTER_PROPERTIES_CHANGED
       ));
 
-  private volatile boolean isClosed = false;
-
   public ClusterEventProducerImpl(CoreContainer coreContainer) {
     this.coreContainer = coreContainer;
   }
@@ -96,7 +90,7 @@ public class ClusterEventProducerImpl implements ClusterEventProducer, ClusterSi
     // register liveNodesListener
     liveNodesListener = (oldNodes, newNodes) -> {
       // already closed but still registered
-      if (isClosed) {
+      if (!running) {
         // remove the listener
         return true;
       }
@@ -196,6 +190,8 @@ public class ClusterEventProducerImpl implements ClusterEventProducer, ClusterSi
 
     // XXX register collection state listener?
     // XXX not sure how to efficiently monitor for REPLICA_DOWN events
+
+    running = true;
   }
 
   @Override
@@ -239,13 +235,6 @@ public class ClusterEventProducerImpl implements ClusterEventProducer, ClusterSi
   }
 
   @Override
-  public void close() throws IOException {
-    stop();
-    isClosed = true;
-    listeners.clear();
-  }
-
-  @Override
   public Map<ClusterEvent.EventType, Set<ClusterEventListener>> getEventListeners() {
     return listeners;
   }
diff --git a/solr/core/src/java/org/apache/solr/cluster/events/impl/CollectionsRepairEventListener.java b/solr/core/src/java/org/apache/solr/cluster/events/impl/CollectionsRepairEventListener.java
index 88df58f..42dcde3 100644
--- a/solr/core/src/java/org/apache/solr/cluster/events/impl/CollectionsRepairEventListener.java
+++ b/solr/core/src/java/org/apache/solr/cluster/events/impl/CollectionsRepairEventListener.java
@@ -19,7 +19,6 @@ package org.apache.solr.cluster.events.impl;
 import java.io.IOException;
 import java.lang.invoke.MethodHandles;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -60,7 +59,7 @@ public class CollectionsRepairEventListener implements ClusterEventListener {
   private final SolrClient solrClient;
   private final SolrCloudManager solrCloudManager;
 
-  private boolean running = false;
+  private volatile boolean running = false;
 
   public CollectionsRepairEventListener(CoreContainer cc) {
     this.solrClient = cc.getSolrClientCache().getCloudSolrClient(cc.getZkController().getZkClient().getZkServerAddress());
diff --git a/solr/core/src/java/org/apache/solr/core/CoreContainer.java b/solr/core/src/java/org/apache/solr/core/CoreContainer.java
index f8ec18a..1427dad 100644
--- a/solr/core/src/java/org/apache/solr/core/CoreContainer.java
+++ b/solr/core/src/java/org/apache/solr/core/CoreContainer.java
@@ -39,9 +39,12 @@ import java.util.Properties;
 import java.util.Set;
 import java.util.UUID;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 import java.util.function.Supplier;
 
 import com.google.common.annotations.VisibleForTesting;
@@ -69,9 +72,10 @@ import org.apache.solr.client.solrj.io.SolrClientCache;
 import org.apache.solr.client.solrj.util.SolrIdentifierValidator;
 import org.apache.solr.cloud.CloudDescriptor;
 import org.apache.solr.cloud.ClusterSingleton;
-import org.apache.solr.cloud.Overseer;
 import org.apache.solr.cloud.OverseerTaskQueue;
 import org.apache.solr.cloud.ZkController;
+import org.apache.solr.cluster.events.ClusterEvent;
+import org.apache.solr.cluster.events.ClusterEventListener;
 import org.apache.solr.cluster.events.ClusterEventProducer;
 import org.apache.solr.cluster.events.impl.ClusterEventProducerImpl;
 import org.apache.solr.common.AlreadyClosedException;
@@ -172,6 +176,72 @@ public class CoreContainer {
     }
   }
 
+  public static class ClusterSingletons {
+    private Map<String, ClusterSingleton> singletonMap = new ConcurrentHashMap<>();
+    // we use this latch to delay the initial startup of singletons, due to
+    // the leader election occurring in parallel with the rest of the load() method.
+    private CountDownLatch readyLatch = new CountDownLatch(1);
+
+    public Map<String, ClusterSingleton> getSingletons() {
+      return singletonMap;
+    }
+
+    public boolean isReady() {
+      return readyLatch.getCount() > 0;
+    }
+
+    public void setReady() {
+      readyLatch.countDown();
+    }
+
+    public void waitUntilReady(long timeout, TimeUnit timeUnit)
+        throws InterruptedException, TimeoutException {
+      boolean await = readyLatch.await(timeout, timeUnit);
+      if (!await) {
+        throw new TimeoutException("Timed out waiting for ClusterSingletons to become ready.");
+      }
+    }
+  }
+
+  /**
+   * This class helps in handling the initial registration of plugin-based listeners,
+   * when both the final {@link ClusterEventProducer} implementation and listeners
+   * are configured using plugins.
+   */
+  public static class InitialClusterEventProducer implements ClusterEventProducer {
+    Map<ClusterEvent.EventType, Set<ClusterEventListener>> initialListeners = new HashMap<>();
+
+    @Override
+    public Map<ClusterEvent.EventType, Set<ClusterEventListener>> getEventListeners() {
+      return initialListeners;
+    }
+
+    public void transferListeners(ClusterEventProducer target) {
+      initialListeners.forEach((type, listeners) -> {
+        listeners.forEach(listener -> {
+          try {
+            target.registerListener(listener, type);
+          } catch (Exception e) {
+            log.warn("Unable to register event listener for type {}: {}", type, e);
+          }
+        });
+      });
+    }
+
+    @Override
+    public void start() throws Exception {
+    }
+
+    @Override
+    public boolean isRunning() {
+      return false;
+    }
+
+    @Override
+    public void stop() {
+    }
+  }
+
   private volatile PluginBag<SolrRequestHandler> containerHandlers = new PluginBag<>(SolrRequestHandler.class, null);
 
   /**
@@ -247,12 +317,11 @@ public class CoreContainer {
 
   private volatile SolrClientCache solrClientCache;
 
-  private volatile ClusterEventProducer clusterEventProducer;
+  private volatile ClusterEventProducer clusterEventProducer = new InitialClusterEventProducer();
 
   private final ObjectCache objectCache = new ObjectCache();
 
-  private final Map<String, ClusterSingleton> clusterSingletons = new ConcurrentHashMap<>();
-
+  private final ClusterSingletons clusterSingletons = new ClusterSingletons();
   private PackageStoreAPI packageStoreAPI;
   private PackageLoader packageLoader;
 
@@ -903,30 +972,28 @@ public class CoreContainer {
 
       // init ClusterSingleton-s
 
-      // register handlers that are also ClusterSingleton
+      // register the handlers that are also ClusterSingleton
       containerHandlers.keySet().forEach(handlerName -> {
         SolrRequestHandler handler = containerHandlers.get(handlerName);
         if (handler instanceof ClusterSingleton) {
-          clusterSingletons.put(handlerName, (ClusterSingleton) handler);
+          clusterSingletons.singletonMap.put(handlerName, (ClusterSingleton) handler);
         }
       });
       // create the ClusterEventProducer
+      InitialClusterEventProducer initialClusterEventProducer = (InitialClusterEventProducer) clusterEventProducer;
       CustomContainerPlugins.ApiInfo clusterEventProducerInfo = customContainerPlugins.getPlugin(ClusterEventProducer.PLUGIN_NAME);
       if (clusterEventProducerInfo != null) {
         clusterEventProducer = (ClusterEventProducer) clusterEventProducerInfo.getInstance();
       } else {
         clusterEventProducer = new ClusterEventProducerImpl(this);
-        clusterSingletons.put(ClusterEventProducer.PLUGIN_NAME, clusterEventProducer);
+        clusterSingletons.singletonMap.put(ClusterEventProducer.PLUGIN_NAME, clusterEventProducer);
       }
+      // transfer those listeners that were already registered to the initial impl
+      initialClusterEventProducer.transferListeners(clusterEventProducer);
 
+      clusterSingletons.setReady();
       zkSys.getZkController().checkOverseerDesignate();
 
-      // XXX note that ClusterSingleton components are registered too late -
-      // XXX the Overseer leader may be already started
-      Overseer overseer = zkSys.getZkController().getOverseer();
-      if (!overseer.isClosed()) { // we are the leader
-        overseer.startClusterSingletons();
-      }
     }
     // This is a bit redundant but these are two distinct concepts for all they're accomplished at the same time.
     status |= LOAD_COMPLETE | INITIAL_CORE_LOAD_COMPLETE;
@@ -2124,7 +2191,7 @@ public class CoreContainer {
     return customContainerPlugins;
   }
 
-  public Map<String, ClusterSingleton> getClusterSingletons() {
+  public ClusterSingletons getClusterSingletons() {
     return clusterSingletons;
   }
 
diff --git a/solr/core/src/java/org/apache/solr/handler/admin/ContainerPluginsApi.java b/solr/core/src/java/org/apache/solr/handler/admin/ContainerPluginsApi.java
index 9f2f459..ad95423 100644
--- a/solr/core/src/java/org/apache/solr/handler/admin/ContainerPluginsApi.java
+++ b/solr/core/src/java/org/apache/solr/handler/admin/ContainerPluginsApi.java
@@ -51,7 +51,7 @@ import static org.apache.lucene.util.IOUtils.closeWhileHandlingException;
 public class ContainerPluginsApi {
   private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
 
-  public static final String PLUGINS = "plugins";
+  public static final String PLUGINS = "plugin";
   private final Supplier<SolrZkClient> zkClientSupplier;
   private final CoreContainer coreContainer;
   public final Read readAPI = new Read();
@@ -64,7 +64,7 @@ public class ContainerPluginsApi {
 
   public class Read {
     @EndPoint(method = METHOD.GET,
-        path = "/cluster/plugins",
+        path = "/cluster/plugin",
         permission = PermissionNameProvider.Name.COLL_READ_PERM)
     public void list(SolrQueryRequest req, SolrQueryResponse rsp) throws IOException {
       rsp.add(PLUGINS, plugins(zkClientSupplier));
@@ -72,7 +72,7 @@ public class ContainerPluginsApi {
   }
 
   @EndPoint(method = METHOD.POST,
-      path = "/cluster/plugins",
+      path = "/cluster/plugin",
       permission = PermissionNameProvider.Name.COLL_EDIT_PERM)
   public class Edit {
 
diff --git a/solr/core/src/test/org/apache/solr/cloud/OverseerTest.java b/solr/core/src/test/org/apache/solr/cloud/OverseerTest.java
index cf30ca9..f3e73e2 100644
--- a/solr/core/src/test/org/apache/solr/cloud/OverseerTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/OverseerTest.java
@@ -17,13 +17,7 @@
 package org.apache.solr.cloud;
 
 import static org.apache.solr.cloud.AbstractDistribZkTestBase.verifyReplicaStatus;
-import static org.mockito.Mockito.anyBoolean;
-import static org.mockito.Mockito.anyInt;
-import static org.mockito.Mockito.anyString;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.*;
 
 import java.io.IOException;
 import java.lang.invoke.MethodHandles;
@@ -118,7 +112,6 @@ public class OverseerTest extends SolrTestCaseJ4 {
 
   private static SolrZkClient zkClient;
 
-
   private volatile boolean testDone = false;
 
   private final List<ZkController> zkControllers = Collections.synchronizedList(new ArrayList<>());
@@ -128,7 +121,6 @@ public class OverseerTest extends SolrTestCaseJ4 {
   private final List<HttpShardHandlerFactory> httpShardHandlerFactorys = Collections.synchronizedList(new ArrayList<>());
   private final List<UpdateShardHandler> updateShardHandlers = Collections.synchronizedList(new ArrayList<>());
   private final List<CloudSolrClient> solrClients = Collections.synchronizedList(new ArrayList<>());
-
   private static final String COLLECTION = SolrTestCaseJ4.DEFAULT_TEST_COLLECTION_NAME;
 
   public static class MockZKController{
@@ -307,6 +299,7 @@ public class OverseerTest extends SolrTestCaseJ4 {
   @Before
   public void setUp() throws Exception {
     testDone = false;
+
     super.setUp();
   }
 
@@ -323,6 +316,7 @@ public class OverseerTest extends SolrTestCaseJ4 {
     }
 
     server = null;
+
   }
 
   @After
@@ -1429,7 +1423,10 @@ public class OverseerTest extends SolrTestCaseJ4 {
         Mockito.withSettings().defaultAnswer(Mockito.CALLS_REAL_METHODS));
     when(mockAlwaysUpCoreContainer.isShutDown()).thenReturn(testDone);  // Allow retry on session expiry
     when(mockAlwaysUpCoreContainer.getResourceLoader()).thenReturn(new SolrResourceLoader());
-    FieldSetter.setField(mockAlwaysUpCoreContainer, CoreContainer.class.getDeclaredField("containerSingletons"), Collections.emptyMap());
+    CoreContainer.ClusterSingletons singletons = new CoreContainer.ClusterSingletons();
+    // don't wait for all singletons
+    singletons.setReady();
+    FieldSetter.setField(mockAlwaysUpCoreContainer, CoreContainer.class.getDeclaredField("clusterSingletons"), singletons);
     ClusterEventProducerImpl clusterEventProducer = new ClusterEventProducerImpl(mockAlwaysUpCoreContainer);
     when(mockAlwaysUpCoreContainer.getClusterEventProducer()).thenReturn(clusterEventProducer);
     FieldSetter.setField(zkController, ZkController.class.getDeclaredField("zkClient"), zkClient);
@@ -1437,6 +1434,13 @@ public class OverseerTest extends SolrTestCaseJ4 {
     when(zkController.getCoreContainer()).thenReturn(mockAlwaysUpCoreContainer);
     when(zkController.getZkClient()).thenReturn(zkClient);
     when(zkController.getZkStateReader()).thenReturn(reader);
+    // primitive support for CC.runAsync
+    doAnswer(invocable -> {
+      Runnable r = invocable.getArgument(0);
+      Thread t = new Thread(r);
+      t.start();
+      return null;
+    }).when(mockAlwaysUpCoreContainer).runAsync(any(Runnable.class));
 
     when(zkController.getLeaderProps(anyString(), anyString(), anyInt())).thenCallRealMethod();
     when(zkController.getLeaderProps(anyString(), anyString(), anyInt(), anyBoolean())).thenCallRealMethod();
diff --git a/solr/core/src/test/org/apache/solr/cluster/events/AllEventsListener.java b/solr/core/src/test/org/apache/solr/cluster/events/AllEventsListener.java
index 9d03c8d..8da6bea 100644
--- a/solr/core/src/test/org/apache/solr/cluster/events/AllEventsListener.java
+++ b/solr/core/src/test/org/apache/solr/cluster/events/AllEventsListener.java
@@ -20,12 +20,9 @@ package org.apache.solr.cluster.events;
 import org.junit.Assert;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
diff --git a/solr/core/src/test/org/apache/solr/cluster/events/ClusterEventProducerTest.java b/solr/core/src/test/org/apache/solr/cluster/events/ClusterEventProducerTest.java
index 12079b2..ea6c5f5 100644
--- a/solr/core/src/test/org/apache/solr/cluster/events/ClusterEventProducerTest.java
+++ b/solr/core/src/test/org/apache/solr/cluster/events/ClusterEventProducerTest.java
@@ -19,39 +19,64 @@ package org.apache.solr.cluster.events;
 
 import org.apache.solr.client.solrj.embedded.JettySolrRunner;
 import org.apache.solr.client.solrj.request.CollectionAdminRequest;
+import org.apache.solr.client.solrj.request.V2Request;
+import org.apache.solr.client.solrj.request.beans.PluginMeta;
+import org.apache.solr.client.solrj.response.V2Response;
 import org.apache.solr.cloud.SolrCloudTestCase;
 import org.apache.solr.common.cloud.ClusterProperties;
+import org.apache.solr.common.util.Utils;
+import org.junit.After;
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
+import java.lang.invoke.MethodHandles;
+import java.time.Instant;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import static java.util.Collections.singletonMap;
+import static org.apache.solr.client.solrj.SolrRequest.METHOD.GET;
+import static org.apache.solr.client.solrj.SolrRequest.METHOD.POST;
 
 /**
  *
  */
 public class ClusterEventProducerTest extends SolrCloudTestCase {
 
-  private static AllEventsListener eventsListener = new AllEventsListener();
+  private AllEventsListener eventsListener;
 
   @BeforeClass
   public static void setupCluster() throws Exception {
     configureCluster(3)
         .addConfig("conf", TEST_PATH().resolve("configsets").resolve("cloud-minimal").resolve("conf"))
         .configure();
-    cluster.getOpenOverseer().getCoreContainer().getClusterEventProducer().registerListener(eventsListener);
   }
 
   @Before
   public void setUp() throws Exception  {
+    System.setProperty("enable.packages", "true");
     super.setUp();
     cluster.deleteAllCollections();
+    eventsListener = new AllEventsListener();
+    cluster.getOpenOverseer().getCoreContainer().getClusterEventProducer().registerListener(eventsListener);
+  }
+
+  @After
+  public void teardown() {
+    System.clearProperty("enable.packages");
+    if (eventsListener != null) {
+      cluster.getOpenOverseer().getCoreContainer().getClusterEventProducer().unregisterListener(eventsListener);
+    }
   }
 
   @Test
-  public void testNodesEvent() throws Exception {
+  public void testEvents() throws Exception {
 
     // NODES_DOWN
 
@@ -149,4 +174,100 @@ public class ClusterEventProducerTest extends SolrCloudTestCase {
         null, propertiesChanged.getNewClusterProperties().get("ext.foo"));
 
   }
+
+  private static CountDownLatch dummyEventLatch = new CountDownLatch(1);
+  private static ClusterEvent lastEvent = null;
+
+  public static class DummyEventListener implements ClusterEventListener {
+    private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+    boolean running = false;
+    @Override
+    public void onEvent(ClusterEvent event) {
+      if (!running) {
+        log.debug("skipped event, not running: {}", event);
+        return;
+      }
+      if (event.getType() == ClusterEvent.EventType.COLLECTIONS_ADDED ||
+          event.getType() == ClusterEvent.EventType.COLLECTIONS_REMOVED) {
+        log.debug("recorded event {}", Utils.toJSONString(event));
+        lastEvent = event;
+        dummyEventLatch.countDown();
+      } else {
+        log.debug("skipped event, wrong type: {}", event.getType());
+      }
+    }
+
+    @Override
+    public String getName() {
+      return "dummy";
+    }
+
+    @Override
+    public void start() throws Exception {
+      log.debug("starting {}", Integer.toHexString(hashCode()));
+      running = true;
+    }
+
+    @Override
+    public boolean isRunning() {
+      return running;
+    }
+
+    @Override
+    public void stop() {
+      log.debug("stopping {}", Integer.toHexString(hashCode()));
+      running = false;
+    }
+  }
+
+  @Test
+  public void testListenerPlugins() throws Exception {
+    PluginMeta plugin = new PluginMeta();
+    plugin.name = "testplugin";
+    plugin.klass = DummyEventListener.class.getName();
+    V2Request req = new V2Request.Builder("/cluster/plugin")
+        .forceV2(true)
+        .withMethod(POST)
+        .withPayload(singletonMap("add", plugin))
+        .build();
+    V2Response rsp = req.process(cluster.getSolrClient());
+    //just check if the plugin is indeed registered
+    V2Request readPluginState = new V2Request.Builder("/cluster/plugin")
+        .forceV2(true)
+        .withMethod(GET)
+        .build();
+    rsp = readPluginState.process(cluster.getSolrClient());
+    assertEquals(DummyEventListener.class.getName(), rsp._getStr("/plugin/testplugin/class", null));
+
+    String collection = "testListenerPlugins_collection";
+    CollectionAdminRequest.Create create = CollectionAdminRequest.createCollection(collection, "conf", 1, 1);
+    cluster.getSolrClient().request(create);
+    cluster.waitForActiveCollection(collection, 1, 1);
+    boolean await = dummyEventLatch.await(30, TimeUnit.SECONDS);
+    if (!await) {
+      fail("Timed out waiting for COLLECTIONS_ADDED event, " + collection);
+    }
+    assertNotNull("lastEvent should be COLLECTIONS_ADDED", lastEvent);
+    assertEquals("lastEvent should be COLLECTIONS_ADDED", ClusterEvent.EventType.COLLECTIONS_ADDED, lastEvent.getType());
+    // verify timestamp
+    Instant now = Instant.now();
+    assertTrue("timestamp of the event is in the future", now.isAfter(lastEvent.getTimestamp()));
+    assertEquals(collection, ((CollectionsAddedEvent)lastEvent).getCollectionNames().next());
+
+    dummyEventLatch = new CountDownLatch(1);
+    lastEvent = null;
+
+    CollectionAdminRequest.Delete delete = CollectionAdminRequest.deleteCollection(collection);
+    cluster.getSolrClient().request(delete);
+    await = dummyEventLatch.await(30, TimeUnit.SECONDS);
+    if (!await) {
+      fail("Timed out waiting for COLLECTIONS_REMOVED event, " + collection);
+    }
+    assertNotNull("lastEvent should be COLLECTIONS_REMOVED", lastEvent);
+    assertEquals("lastEvent should be COLLECTIONS_REMOVED", ClusterEvent.EventType.COLLECTIONS_REMOVED, lastEvent.getType());
+    // verify timestamp
+    now = Instant.now();
+    assertTrue("timestamp of the event is in the future", now.isAfter(lastEvent.getTimestamp()));
+    assertEquals(collection, ((CollectionsRemovedEvent)lastEvent).getCollectionNames().next());
+  }
 }
diff --git a/solr/core/src/test/org/apache/solr/handler/TestContainerPlugin.java b/solr/core/src/test/org/apache/solr/handler/TestContainerPlugin.java
index 4c37c17..bd9bf7c 100644
--- a/solr/core/src/test/org/apache/solr/handler/TestContainerPlugin.java
+++ b/solr/core/src/test/org/apache/solr/handler/TestContainerPlugin.java
@@ -92,8 +92,8 @@ public class TestContainerPlugin extends SolrCloudTestCase {
       expectError(req, cluster.getSolrClient(), errPath, "No method with @Command in class");
 
       //test with an invalid class
-      plugin.klass = C1.class.getName();
-      expectError(req, cluster.getSolrClient(), errPath, "No @EndPoints");
+//      plugin.klass = C1.class.getName();
+//      expectError(req, cluster.getSolrClient(), errPath, "No @EndPoints");
 
       //test with a valid class. This should succeed now
       plugin.klass = C3.class.getName();


[lucene-solr] 01/02: Merge branch 'master' into jira/solr-14749

Posted by ab...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ab pushed a commit to branch jira/solr-14749
in repository https://gitbox.apache.org/repos/asf/lucene-solr.git

commit 126b236d2550e1084ed1e10e1450d3bf48b1a8e2
Merge: d5198c0 2b692cc
Author: Andrzej Bialecki <ab...@apache.org>
AuthorDate: Tue Sep 29 14:58:12 2020 +0200

    Merge branch 'master' into jira/solr-14749

 build.gradle                                       |   1 +
 gradle/documentation/render-javadoc.gradle         |   4 +-
 gradle/generation/jflex.gradle                     |   4 +-
 gradle/generation/kuromoji.gradle                  | 173 +++++++-------
 gradle/generation/nori.gradle                      |  85 +++++++
 gradle/maven/defaults-maven.gradle                 |  41 ++--
 gradle/validation/validate-source-patterns.gradle  |   2 +-
 lucene/CHANGES.txt                                 |  13 +-
 lucene/MIGRATE.md                                  |  18 ++
 .../ar/ArabicNormalizationFilterFactory.java       |   2 +-
 .../analysis/ar/ArabicStemFilterFactory.java       |   2 +-
 .../analysis/bg/BulgarianStemFilterFactory.java    |   2 +-
 .../bn/BengaliNormalizationFilterFactory.java      |   2 +-
 .../analysis/bn/BengaliStemFilterFactory.java      |   2 +-
 .../boost/DelimitedBoostTokenFilterFactory.java    |   2 +-
 .../analysis/br/BrazilianStemFilterFactory.java    |   2 +-
 .../charfilter/HTMLStripCharFilterFactory.java     |   2 +-
 .../charfilter/MappingCharFilterFactory.java       |   6 +-
 .../analysis/cjk/CJKBigramFilterFactory.java       |   2 +-
 .../lucene/analysis/cjk/CJKWidthFilterFactory.java |   2 +-
 .../ckb/SoraniNormalizationFilterFactory.java      |   2 +-
 .../analysis/ckb/SoraniStemFilterFactory.java      |   2 +-
 .../{standard => classic}/ClassicAnalyzer.java     |   3 +-
 .../{standard => classic}/ClassicFilter.java       |   2 +-
 .../ClassicFilterFactory.java                      |   4 +-
 .../{standard => classic}/ClassicTokenizer.java    |   4 +-
 .../ClassicTokenizerFactory.java                   |   5 +-
 .../ClassicTokenizerImpl.java                      |   2 +-
 .../ClassicTokenizerImpl.jflex                     |   0
 .../analysis/{standard => classic}/package.html    |  21 +-
 .../commongrams/CommonGramsFilterFactory.java      |   6 +-
 .../DictionaryCompoundWordTokenFilterFactory.java  |   6 +-
 .../HyphenationCompoundWordTokenFilterFactory.java |   6 +-
 .../analysis/core/DecimalDigitFilterFactory.java   |   2 +-
 .../analysis/core/FlattenGraphFilterFactory.java   |   2 +-
 .../analysis/core/KeywordTokenizerFactory.java     |   2 +-
 .../analysis/core/LetterTokenizerFactory.java      |   2 +-
 .../analysis/core/LowerCaseFilterFactory.java      |   2 +-
 .../lucene/analysis/core/StopFilterFactory.java    |   6 +-
 .../analysis/core/TypeTokenFilterFactory.java      |   6 +-
 .../analysis/core/UpperCaseFilterFactory.java      |   2 +-
 .../analysis/core/WhitespaceTokenizerFactory.java  |   2 +-
 .../lucene/analysis/custom/CustomAnalyzer.java     |  16 +-
 .../lucene/analysis/cz/CzechStemFilterFactory.java |   2 +-
 .../analysis/de/GermanLightStemFilterFactory.java  |   2 +-
 .../de/GermanMinimalStemFilterFactory.java         |   2 +-
 .../de/GermanNormalizationFilterFactory.java       |   2 +-
 .../analysis/de/GermanStemFilterFactory.java       |   2 +-
 .../analysis/el/GreekLowerCaseFilterFactory.java   |   2 +-
 .../lucene/analysis/el/GreekStemFilterFactory.java |   2 +-
 .../{standard => email}/ASCIITLD.jflex-macro       |   0
 .../{standard => email}/UAX29URLEmailAnalyzer.java |   5 +-
 .../UAX29URLEmailTokenizer.java                    |   4 +-
 .../UAX29URLEmailTokenizerFactory.java             |   5 +-
 .../UAX29URLEmailTokenizerImpl.java                |   2 +-
 .../UAX29URLEmailTokenizerImpl.jflex               |   2 +-
 .../analysis/{standard => email}/package.html      |  21 +-
 .../en/EnglishMinimalStemFilterFactory.java        |   2 +-
 .../en/EnglishPossessiveFilterFactory.java         |   2 +-
 .../lucene/analysis/en/KStemFilterFactory.java     |   2 +-
 .../analysis/en/PorterStemFilterFactory.java       |   2 +-
 .../analysis/es/SpanishLightStemFilterFactory.java |   2 +-
 .../es/SpanishMinimalStemFilterFactory.java        |   2 +-
 .../analysis/fa/PersianCharFilterFactory.java      |   2 +-
 .../fa/PersianNormalizationFilterFactory.java      |   2 +-
 .../analysis/fi/FinnishLightStemFilterFactory.java |   2 +-
 .../analysis/fr/FrenchLightStemFilterFactory.java  |   2 +-
 .../fr/FrenchMinimalStemFilterFactory.java         |   2 +-
 .../analysis/ga/IrishLowerCaseFilterFactory.java   |   2 +-
 .../gl/GalicianMinimalStemFilterFactory.java       |   2 +-
 .../analysis/gl/GalicianStemFilterFactory.java     |   2 +-
 .../hi/HindiNormalizationFilterFactory.java        |   2 +-
 .../lucene/analysis/hi/HindiStemFilterFactory.java |   2 +-
 .../hu/HungarianLightStemFilterFactory.java        |   2 +-
 .../hunspell/HunspellStemFilterFactory.java        |   6 +-
 .../analysis/id/IndonesianStemFilterFactory.java   |   2 +-
 .../in/IndicNormalizationFilterFactory.java        |   2 +-
 .../analysis/it/ItalianLightStemFilterFactory.java |   2 +-
 .../analysis/lv/LatvianStemFilterFactory.java      |   2 +-
 .../analysis/minhash/MinHashFilterFactory.java     |   4 +-
 .../miscellaneous/ASCIIFoldingFilterFactory.java   |   2 +-
 .../miscellaneous/CapitalizationFilterFactory.java |   2 +-
 .../miscellaneous/CodepointCountFilterFactory.java |   2 +-
 .../ConcatenateGraphFilterFactory.java             |   2 +-
 .../ConditionalTokenFilterFactory.java             |   6 +-
 .../miscellaneous/DateRecognizerFilterFactory.java |   2 +-
 .../DelimitedTermFrequencyTokenFilterFactory.java  |   2 +-
 .../miscellaneous/FingerprintFilterFactory.java    |   2 +-
 .../FixBrokenOffsetsFilterFactory.java             |   2 +-
 .../HyphenatedWordsFilterFactory.java              |   2 +-
 .../miscellaneous/KeepWordFilterFactory.java       |   6 +-
 .../miscellaneous/KeywordMarkerFilterFactory.java  |   6 +-
 .../miscellaneous/KeywordRepeatFilterFactory.java  |   2 +-
 .../miscellaneous/LengthFilterFactory.java         |   2 +-
 .../LimitTokenCountFilterFactory.java              |   2 +-
 .../LimitTokenOffsetFilterFactory.java             |   2 +-
 .../LimitTokenPositionFilterFactory.java           |   2 +-
 .../miscellaneous/ProtectedTermFilterFactory.java  |   6 +-
 .../RemoveDuplicatesTokenFilterFactory.java        |   2 +-
 .../ScandinavianFoldingFilterFactory.java          |   2 +-
 .../ScandinavianNormalizationFilterFactory.java    |   2 +-
 .../StemmerOverrideFilterFactory.java              |   6 +-
 .../analysis/miscellaneous/TrimFilterFactory.java  |   2 +-
 .../miscellaneous/TruncateTokenFilterFactory.java  |   2 +-
 .../miscellaneous/TypeAsSynonymFilterFactory.java  |   2 +-
 .../miscellaneous/WordDelimiterFilterFactory.java  |   6 +-
 .../WordDelimiterGraphFilterFactory.java           |   6 +-
 .../analysis/ngram/EdgeNGramFilterFactory.java     |   2 +-
 .../analysis/ngram/EdgeNGramTokenizerFactory.java  |   2 +-
 .../lucene/analysis/ngram/NGramFilterFactory.java  |   2 +-
 .../analysis/ngram/NGramTokenizerFactory.java      |   2 +-
 .../no/NorwegianLightStemFilterFactory.java        |   2 +-
 .../no/NorwegianMinimalStemFilterFactory.java      |   2 +-
 .../path/PathHierarchyTokenizerFactory.java        |   2 +-
 .../pattern/PatternCaptureGroupFilterFactory.java  |   2 +-
 .../pattern/PatternReplaceCharFilterFactory.java   |   2 +-
 .../pattern/PatternReplaceFilterFactory.java       |   2 +-
 .../analysis/pattern/PatternTokenizerFactory.java  |   2 +-
 .../SimplePatternSplitTokenizerFactory.java        |   2 +-
 .../pattern/SimplePatternTokenizerFactory.java     |   2 +-
 .../DelimitedPayloadTokenFilterFactory.java        |   6 +-
 .../payloads/NumericPayloadTokenFilterFactory.java |   2 +-
 .../TokenOffsetPayloadTokenFilterFactory.java      |   2 +-
 .../payloads/TypeAsPayloadTokenFilterFactory.java  |   2 +-
 .../pt/PortugueseLightStemFilterFactory.java       |   2 +-
 .../pt/PortugueseMinimalStemFilterFactory.java     |   2 +-
 .../analysis/pt/PortugueseStemFilterFactory.java   |   2 +-
 .../reverse/ReverseStringFilterFactory.java        |   2 +-
 .../analysis/ru/RussianLightStemFilterFactory.java |   2 +-
 .../shingle/FixedShingleFilterFactory.java         |   2 +-
 .../analysis/shingle/ShingleFilterFactory.java     |   2 +-
 .../snowball/SnowballPorterFilterFactory.java      |   6 +-
 .../sr/SerbianNormalizationFilterFactory.java      |   2 +-
 .../analysis/sv/SwedishLightStemFilterFactory.java |   2 +-
 .../analysis/synonym/SynonymFilterFactory.java     |   8 +-
 .../synonym/SynonymGraphFilterFactory.java         |   8 +-
 .../lucene/analysis/th/ThaiTokenizerFactory.java   |   2 +-
 .../analysis/tr/ApostropheFilterFactory.java       |   2 +-
 .../analysis/tr/TurkishLowerCaseFilterFactory.java |   2 +-
 .../lucene/analysis/util/ElisionFilterFactory.java |   3 +
 .../analysis/util/FilesystemResourceLoader.java    |   3 +
 .../wikipedia/WikipediaTokenizerFactory.java       |   2 +-
 ...> org.apache.lucene.analysis.CharFilterFactory} |   0
 ... org.apache.lucene.analysis.TokenFilterFactory} |   2 +-
 ...=> org.apache.lucene.analysis.TokenizerFactory} |   5 +-
 .../lucene/analysis/ar/TestArabicFilters.java      |   2 +-
 .../bg/TestBulgarianStemFilterFactory.java         |   2 +-
 .../lucene/analysis/bn/TestBengaliFilters.java     |   2 +-
 .../br/TestBrazilianStemFilterFactory.java         |   2 +-
 .../charfilter/TestHTMLStripCharFilterFactory.java |   2 +-
 .../charfilter/TestMappingCharFilterFactory.java   |   2 +-
 .../analysis/cjk/TestCJKBigramFilterFactory.java   |   2 +-
 .../analysis/cjk/TestCJKWidthFilterFactory.java    |   2 +-
 .../ckb/TestSoraniNormalizationFilterFactory.java  |   2 +-
 .../analysis/ckb/TestSoraniStemFilterFactory.java  |   2 +-
 .../{standard => classic}/TestClassicAnalyzer.java |   2 +-
 .../analysis/classic/TestClassicFactories.java     |  81 +++++++
 .../commongrams/TestCommonGramsFilterFactory.java  |   6 +-
 .../TestCommonGramsQueryFilterFactory.java         |   6 +-
 ...stDictionaryCompoundWordTokenFilterFactory.java |   2 +-
 ...tHyphenationCompoundWordTokenFilterFactory.java |   2 +-
 .../core/TestAllAnalyzersHaveFactories.java        |  10 +-
 .../lucene/analysis/core/TestCoreFactories.java    |  76 ++++++
 .../core/TestDecimalDigitFilterFactory.java        |   2 +-
 .../apache/lucene/analysis/core/TestFactories.java |  10 +-
 .../analysis/core/TestStopFilterFactory.java       |   6 +-
 .../analysis/core/TestTypeTokenFilterFactory.java  |   4 +-
 .../lucene/analysis/custom/TestCustomAnalyzer.java |   8 +-
 .../analysis/cz/TestCzechStemFilterFactory.java    |   2 +-
 .../de/TestGermanLightStemFilterFactory.java       |   2 +-
 .../de/TestGermanMinimalStemFilterFactory.java     |   2 +-
 .../de/TestGermanNormalizationFilterFactory.java   |   2 +-
 .../analysis/de/TestGermanStemFilterFactory.java   |   2 +-
 .../el/TestGreekLowerCaseFilterFactory.java        |   2 +-
 .../analysis/el/TestGreekStemFilterFactory.java    |   2 +-
 .../LuceneResourcesWikiPage.html                   |   0
 .../LuceneResourcesWikiPageURLs.txt                |   0
 .../TestUAX29URLEmailAnalyzer.java                 |   2 +-
 .../TestUAX29URLEmailTokenizer.java                |   4 +-
 .../TestUAX29URLEmailTokenizerFactory.java         |   4 +-
 ...esses.from.random.text.with.email.addresses.txt |   0
 .../random.text.with.email.addresses.txt           |   0
 .../{standard => email}/random.text.with.urls.txt  |   0
 .../urls.from.random.text.with.urls.txt            |   0
 .../en/TestEnglishMinimalStemFilterFactory.java    |   2 +-
 .../lucene/analysis/en/TestKStemFilterFactory.java |   2 +-
 .../analysis/en/TestPorterStemFilterFactory.java   |   2 +-
 .../es/TestSpanishLightStemFilterFactory.java      |   2 +-
 .../es/TestSpanishMinimalStemFilterFactory.java    |   2 +-
 .../fa/TestPersianNormalizationFilterFactory.java  |   2 +-
 .../fi/TestFinnishLightStemFilterFactory.java      |   2 +-
 .../fr/TestFrenchLightStemFilterFactory.java       |   2 +-
 .../fr/TestFrenchMinimalStemFilterFactory.java     |   2 +-
 .../ga/TestIrishLowerCaseFilterFactory.java        |   2 +-
 .../gl/TestGalicianMinimalStemFilterFactory.java   |   2 +-
 .../analysis/gl/TestGalicianStemFilterFactory.java |   2 +-
 .../lucene/analysis/hi/TestHindiFilters.java       |   2 +-
 .../hu/TestHungarianLightStemFilterFactory.java    |   2 +-
 .../hunspell/TestHunspellStemFilterFactory.java    |   2 +-
 .../id/TestIndonesianStemFilterFactory.java        |   2 +-
 .../it/TestItalianLightStemFilterFactory.java      |   2 +-
 .../analysis/lv/TestLatvianStemFilterFactory.java  |   2 +-
 .../TestAsciiFoldingFilterFactory.java             |   4 +-
 .../TestCapitalizationFilterFactory.java           |   2 +-
 .../TestCodepointCountFilterFactory.java           |   2 +-
 .../TestConcatenateGraphFilterFactory.java         |   2 +-
 .../miscellaneous/TestConditionalTokenFilter.java  |   2 +-
 .../TestFingerprintFilterFactory.java              |   2 +-
 .../miscellaneous/TestKeepFilterFactory.java       |   6 +-
 .../TestKeywordMarkerFilterFactory.java            |   2 +-
 .../miscellaneous/TestLengthFilterFactory.java     |   2 +-
 .../TestLimitTokenCountFilterFactory.java          |   2 +-
 .../TestLimitTokenOffsetFilterFactory.java         |   2 +-
 .../TestLimitTokenPositionFilterFactory.java       |   2 +-
 ...actory.java => TestMiscellaneousFactories.java} |  29 ++-
 .../TestProtectedTermFilterFactory.java            |   2 +-
 .../TestRemoveDuplicatesTokenFilterFactory.java    |   2 +-
 .../TestScandinavianFoldingFilterFactory.java      |   2 +-
 ...TestScandinavianNormalizationFilterFactory.java |   2 +-
 .../TestStemmerOverrideFilterFactory.java          |   2 +-
 .../miscellaneous/TestTrimFilterFactory.java       |   2 +-
 .../TestTruncateTokenFilterFactory.java            |   2 +-
 .../TestTypeAsSynonymFilterFactory.java            |   2 +-
 .../lucene/analysis/ngram/TestNGramFilters.java    |   2 +-
 .../no/TestNorwegianLightStemFilterFactory.java    |   2 +-
 .../no/TestNorwegianMinimalStemFilterFactory.java  |   2 +-
 .../TestPatternReplaceCharFilterFactory.java       |   2 +-
 .../pattern/TestPatternReplaceFilterFactory.java   |   2 +-
 .../pattern/TestPatternTokenizerFactory.java       |   2 +-
 .../TestDelimitedPayloadTokenFilterFactory.java    |   2 +-
 .../pt/TestPortugueseLightStemFilterFactory.java   |   2 +-
 .../pt/TestPortugueseMinimalStemFilterFactory.java |   2 +-
 .../pt/TestPortugueseStemFilterFactory.java        |   2 +-
 .../reverse/TestReverseStringFilterFactory.java    |   2 +-
 .../ru/TestRussianLightStemFilterFactory.java      |   2 +-
 .../analysis/shingle/TestShingleFilterFactory.java |   2 +-
 .../snowball/TestSnowballPorterFilterFactory.java  |   2 +-
 .../sr/TestSerbianNormalizationFilterFactory.java  |   2 +-
 .../analysis/standard/TestStandardFactories.java   | 170 --------------
 .../sv/TestSwedishLightStemFilterFactory.java      |   2 +-
 .../analysis/synonym/TestMultiWordSynonyms.java    |   2 +-
 .../analysis/synonym/TestSynonymFilterFactory.java |   4 +-
 .../analysis/th/TestThaiTokenizerFactory.java      |   2 +-
 .../analysis/tr/TestApostropheFilterFactory.java   |   2 +-
 .../tr/TestTurkishLowerCaseFilterFactory.java      |   2 +-
 .../analysis/util/StringMockResourceLoader.java    |   2 +
 .../analysis/util/TestElisionFilterFactory.java    |   1 +
 .../util/TestFilesystemResourceLoader.java         |   2 +
 .../wikipedia/TestWikipediaTokenizerFactory.java   |   2 +-
 .../analysis/icu/ICUFoldingFilterFactory.java      |   2 +-
 .../icu/ICUNormalizer2CharFilterFactory.java       |   2 +-
 .../analysis/icu/ICUNormalizer2FilterFactory.java  |   2 +-
 .../analysis/icu/ICUTransformFilterFactory.java    |   2 +-
 .../icu/segmentation/ICUTokenizerFactory.java      |   6 +-
 ...> org.apache.lucene.analysis.CharFilterFactory} |   0
 ... org.apache.lucene.analysis.TokenFilterFactory} |   0
 ...=> org.apache.lucene.analysis.TokenizerFactory} |   0
 .../icu/segmentation/TestICUTokenizerFactory.java  |   2 +-
 .../analysis/ja/JapaneseBaseFormFilterFactory.java |   2 +-
 .../ja/JapaneseIterationMarkCharFilterFactory.java |   2 +-
 .../ja/JapaneseKatakanaStemFilterFactory.java      |   2 +-
 .../analysis/ja/JapaneseNumberFilterFactory.java   |   2 +-
 .../ja/JapanesePartOfSpeechStopFilterFactory.java  |   6 +-
 .../ja/JapaneseReadingFormFilterFactory.java       |   2 +-
 .../analysis/ja/JapaneseTokenizerFactory.java      |   6 +-
 ...> org.apache.lucene.analysis.CharFilterFactory} |   0
 ... org.apache.lucene.analysis.TokenFilterFactory} |   0
 ...=> org.apache.lucene.analysis.TokenizerFactory} |   0
 .../analysis/ja/StringMockResourceLoader.java      |   2 +-
 .../apache/lucene/analysis/ja/TestFactories.java   |  10 +-
 .../morfologik/MorfologikFilterFactory.java        |   6 +-
 ... org.apache.lucene.analysis.TokenFilterFactory} |   0
 .../morfologik/TestMorfologikFilterFactory.java    |   4 +-
 .../analysis/ko/KoreanNumberFilterFactory.java     |   2 +-
 .../ko/KoreanPartOfSpeechStopFilterFactory.java    |   2 +-
 .../ko/KoreanReadingFormFilterFactory.java         |   2 +-
 .../lucene/analysis/ko/KoreanTokenizerFactory.java |   6 +-
 ... org.apache.lucene.analysis.TokenFilterFactory} |   0
 ...=> org.apache.lucene.analysis.TokenizerFactory} |   0
 .../analysis/ko/StringMockResourceLoader.java      |   2 +-
 .../opennlp/OpenNLPChunkerFilterFactory.java       |   6 +-
 .../opennlp/OpenNLPLemmatizerFilterFactory.java    |   6 +-
 .../analysis/opennlp/OpenNLPPOSFilterFactory.java  |   6 +-
 .../analysis/opennlp/OpenNLPTokenizerFactory.java  |   6 +-
 .../analysis/opennlp/tools/OpenNLPOpsFactory.java  |   2 +-
 ... org.apache.lucene.analysis.TokenFilterFactory} |   0
 ...=> org.apache.lucene.analysis.TokenizerFactory} |   0
 .../opennlp/TestOpenNLPChunkerFilterFactory.java   |   2 +-
 .../TestOpenNLPLemmatizerFilterFactory.java        |   2 +-
 .../opennlp/TestOpenNLPPOSFilterFactory.java       |   2 +-
 .../opennlp/TestOpenNLPSentenceBreakIterator.java  |   2 +-
 .../opennlp/TestOpenNLPTokenizerFactory.java       |   2 +-
 .../phonetic/BeiderMorseFilterFactory.java         |   2 +-
 .../DaitchMokotoffSoundexFilterFactory.java        |   2 +-
 .../phonetic/DoubleMetaphoneFilterFactory.java     |   2 +-
 .../analysis/phonetic/PhoneticFilterFactory.java   |   6 +-
 ... org.apache.lucene.analysis.TokenFilterFactory} |   0
 .../phonetic/TestPhoneticFilterFactory.java        |   2 +-
 .../cn/smart/HMMChineseTokenizerFactory.java       |   2 +-
 ...=> org.apache.lucene.analysis.TokenizerFactory} |   0
 .../cn/smart/TestHMMChineseTokenizerFactory.java   |   2 +-
 .../stempel/StempelPolishStemFilterFactory.java    |   2 +-
 ... org.apache.lucene.analysis.TokenFilterFactory} |   0
 .../byTask/tasks/AnalyzerFactoryTask.java          |  10 +-
 .../benchmark/byTask/utils/AnalyzerFactory.java    |   6 +-
 .../lucene/benchmark/quality/TestQualityRun.java   |   2 +-
 .../lucene/analysis}/AbstractAnalysisFactory.java  |   7 +-
 .../apache/lucene/analysis}/AnalysisSPILoader.java |   2 +-
 .../apache/lucene/analysis}/CharFilterFactory.java |   4 +-
 .../lucene/analysis}/TokenFilterFactory.java       |   4 +-
 .../apache/lucene/analysis}/TokenizerFactory.java  |   4 +-
 .../standard/StandardTokenizerFactory.java         |   2 +-
 .../lucene87/LZ4WithPresetDictCompressionMode.java |   4 +-
 .../lucene87/Lucene87StoredFieldsFormat.java       |   6 +-
 .../apache/lucene/store/ByteBuffersDataOutput.java |  15 +-
 .../lucene}/util/ClasspathResourceLoader.java      |   4 +-
 .../org/apache/lucene}/util/ResourceLoader.java    |   2 +-
 .../apache/lucene}/util/ResourceLoaderAware.java   |   2 +-
 .../org.apache.lucene.analysis.TokenizerFactory}   |   2 +-
 .../org.apache.lucene.analysis.CharFilterFactory}  |   2 +-
 .../org.apache.lucene.analysis.TokenFilterFactory} |   2 +-
 .../lucene/analysis/FakeCharFilterFactory.java     |  27 ++-
 .../lucene/analysis/FakeTokenFilterFactory.java}   |  26 +--
 .../analysis}/TestAbstractAnalysisFactory.java     |  18 +-
 .../lucene/analysis}/TestAnalysisSPILoader.java    |  58 ++---
 .../analysis/standard/TestStandardFactories.java   |  63 +++++
 .../lucene/store/TestByteBuffersDataOutput.java    |  42 ++++
 .../lucene/facet/taxonomy/TaxonomyFacetLabels.java | 195 ++++++++++++++++
 .../org/apache/lucene/facet/FacetTestCase.java     |  42 +++-
 .../facet/taxonomy/TestTaxonomyFacetCounts.java    |  44 +++-
 .../facet/taxonomy/TestTaxonomyFacetLabels.java    | 194 ++++++++++++++++
 lucene/luke/build.gradle                           |   2 -
 .../analysis/AnalysisChainDialogFactory.java       |   6 +-
 .../lucene/luke/models/analysis/Analysis.java      |   6 +-
 .../lucene/luke/models/analysis/AnalysisImpl.java  |   6 +-
 .../luke/models/util/twentynewsgroups/Message.java |   2 +-
 .../analyzing/SuggestStopFilterFactory.java        |   6 +-
 ... org.apache.lucene.analysis.TokenFilterFactory} |   0
 .../analyzing/TestSuggestStopFilterFactory.java    |   4 +-
 .../analysis}/BaseTokenStreamFactoryTestCase.java  |  10 +-
 solr/CHANGES.txt                                   |  20 +-
 solr/bin/solr                                      |   9 +-
 solr/bin/solr.cmd                                  |   4 +
 solr/bin/solr.in.sh                                |  10 +-
 .../org/apache/solr/schema/ICUCollationField.java  |   2 +-
 .../apache/solr/schema/TestICUCollationField.java  |   2 +-
 .../SolrStopwordsCarrot2LexicalDataFactory.java    |   2 +-
 .../apache/solr/ltr/search/LTRQParserPlugin.java   |   4 +-
 .../solr/analysis/LowerCaseTokenizerFactory.java   |   2 +-
 .../analysis/ReversedWildcardFilterFactory.java    |   2 +-
 .../org/apache/solr/analysis/TokenizerChain.java   |   6 +-
 .../apache/solr/api/CustomContainerPlugins.java    |   2 +-
 .../src/java/org/apache/solr/core/ConfigSet.java   |   2 +-
 .../java/org/apache/solr/core/CoreContainer.java   |   8 +-
 .../src/java/org/apache/solr/core/PluginBag.java   |   4 +-
 .../org/apache/solr/core/RateLimiterConfig.java    |  53 +++++
 .../src/java/org/apache/solr/core/SolrCore.java    |   4 +-
 .../org/apache/solr/core/SolrResourceLoader.java   |  10 +-
 .../solr/handler/AnalysisRequestHandlerBase.java   |   6 +-
 .../java/org/apache/solr/handler/ClusterAPI.java   |  19 +-
 .../org/apache/solr/handler/SolrConfigHandler.java |   2 +-
 .../solr/handler/admin/LukeRequestHandler.java     |   6 +-
 .../component/PhrasesIdentificationComponent.java  |   2 +-
 .../solr/handler/component/TermsComponent.java     |  46 ----
 .../solr/handler/tagger/TaggerRequestHandler.java  |   2 +-
 .../apache/solr/parser/SolrQueryParserBase.java    |   2 +-
 .../solr/pkg/PackageListeningClassLoader.java      |   2 +-
 .../org/apache/solr/pkg/PackagePluginHolder.java   |   2 +-
 .../analysis/BaseManagedTokenFilterFactory.java    |   6 +-
 .../analysis/ManagedSynonymFilterFactory.java      |   2 +-
 .../analysis/ManagedSynonymGraphFilterFactory.java |   2 +-
 .../org/apache/solr/schema/CollationField.java     |   2 +-
 .../java/org/apache/solr/schema/CurrencyField.java |   2 +-
 .../org/apache/solr/schema/CurrencyFieldType.java  |   4 +-
 .../apache/solr/schema/ExchangeRateProvider.java   |   2 +-
 .../src/java/org/apache/solr/schema/FieldType.java |   8 +-
 .../apache/solr/schema/FieldTypePluginLoader.java  |   6 +-
 .../solr/schema/FileExchangeRateProvider.java      |   2 +-
 .../org/apache/solr/schema/ManagedIndexSchema.java |   8 +-
 .../solr/schema/OpenExchangeRatesOrgProvider.java  |   2 +-
 .../java/org/apache/solr/schema/SchemaManager.java |   4 +-
 .../apache/solr/search/ExtendedDismaxQParser.java  |   2 +-
 .../apache/solr/search/stats/ExactStatsCache.java  |   6 +
 .../solr/security/MultiDestinationAuditLogger.java |   4 +-
 .../org/apache/solr/servlet/QueryRateLimiter.java  | 107 +++++++--
 .../org/apache/solr/servlet/RateLimitManager.java  |  31 ++-
 .../apache/solr/servlet/RequestRateLimiter.java    |  55 +----
 .../apache/solr/servlet/SolrDispatchFilter.java    |  18 +-
 .../java/org/apache/solr/util/PayloadUtils.java    |   2 +-
 .../java/org/apache/solr/util/SafeXMLParsing.java  |   2 +-
 .../org/apache/solr/util/SystemIdResolver.java     |   2 +-
 .../apache/solr/util/xslt/TransformerProvider.java |   2 +-
 solr/core/src/resources/ImplicitPlugins.json       |   3 +-
 ... org.apache.lucene.analysis.TokenFilterFactory} |   0
 .../MyPatternReplaceCharFilterFactory.java}        |  15 +-
 .../runtimecode/MyTextField.java}                  |  11 +-
 .../runtimecode/MyWhitespaceTokenizerFactory.java} |  14 +-
 .../test-files/runtimecode/schema-plugins.jar.bin  | Bin 6814 -> 1461 bytes
 .../analysis/ProtectedTermFilterFactoryTest.java   |   2 +-
 .../analysis/TestWordDelimiterFilterFactory.java   |   2 +-
 .../analysis/ThrowingMockTokenFilterFactory.java   |   2 +-
 .../apache/solr/analysis/TokenizerChainTest.java   |   2 +-
 .../test/org/apache/solr/cloud/ZkFailoverTest.java |  35 ++-
 .../org/apache/solr/core/ResourceLoaderTest.java   |   6 +-
 .../handler/FieldAnalysisRequestHandlerTest.java   |   4 +-
 .../apache/solr/handler/TestContainerPlugin.java   |   4 +-
 .../component/CustomTermsComponentTest.java        | 257 ---------------------
 .../component/DistributedTermsComponentTest.java   |  32 +--
 .../tagger/WordLengthTaggingFilterFactory.java     |   2 +-
 .../src/test/org/apache/solr/pkg/TestPackages.java | 197 ++++++++++------
 .../apache/solr/rest/schema/TestBulkSchemaAPI.java |   2 +-
 .../apache/solr/schema/CustomAnalyzerStrField.java |   4 +-
 .../solr/schema/MockExchangeRateProvider.java      |   2 +-
 .../schema/OpenExchangeRatesOrgProviderTest.java   |   2 +-
 .../solr/search/stats/TestExactStatsCache.java     |  74 +++++-
 .../solr/servlet/TestRequestRateLimiter.java       |  21 +-
 .../org/apache/solr/util/TestSafeXMLParsing.java   |   2 +-
 .../org/apache/solr/util/TestSystemIdResolver.java |   2 +-
 solr/solr-ref-guide/src/filter-descriptions.adoc   |   2 +-
 .../src/major-changes-in-solr-9.adoc               |   7 +
 solr/solr-ref-guide/src/rate-limiters.adoc         |  64 ++---
 solr/solr-ref-guide/src/the-terms-component.adoc   |   1 -
 solr/solr-ref-guide/src/tokenizers.adoc            |   2 +-
 .../client/solrj/impl/BaseCloudSolrClient.java     |   8 +-
 .../client/solrj/io/stream/ScoreNodesStream.java   |   4 -
 .../solrj/request/beans/RateLimiterMeta.java       |  73 ++++++
 .../solr/analysis/MockCharFilterFactory.java       |   2 +-
 .../solr/analysis/MockTokenFilterFactory.java      |   2 +-
 .../apache/solr/analysis/MockTokenizerFactory.java |   2 +-
 .../analysis/StringMockSolrResourceLoader.java     |   2 +-
 430 files changed, 2188 insertions(+), 1504 deletions(-)

diff --cc solr/core/src/java/org/apache/solr/api/CustomContainerPlugins.java
index 63db89c,93de2e3..c6bfca6
--- a/solr/core/src/java/org/apache/solr/api/CustomContainerPlugins.java
+++ b/solr/core/src/java/org/apache/solr/api/CustomContainerPlugins.java
@@@ -30,12 -30,9 +30,12 @@@ import java.util.Objects
  import java.util.Optional;
  
  import com.fasterxml.jackson.databind.ObjectMapper;
- import org.apache.lucene.analysis.util.ResourceLoaderAware;
+ import org.apache.lucene.util.ResourceLoaderAware;
  import org.apache.solr.client.solrj.SolrRequest;
  import org.apache.solr.client.solrj.request.beans.PluginMeta;
 +import org.apache.solr.cloud.ClusterSingleton;
 +import org.apache.solr.cluster.events.ClusterEvent;
 +import org.apache.solr.cluster.events.ClusterEventListener;
  import org.apache.solr.common.MapWriter;
  import org.apache.solr.common.SolrException;
  import org.apache.solr.common.annotation.JsonProperty;