From 9e5f108daae80e699253ae3b0367f5fa38872712 Mon Sep 17 00:00:00 2001 From: Uwe Schindler Date: Wed, 25 Mar 2026 21:03:39 +0100 Subject: [PATCH] Use IllegalCallerException to signal wrong caller in internal classes (VectorizationProvider, TestSecrets) + cleanup code a bit --- lucene/CHANGES.txt | 3 ++ .../lucene/internal/tests/TestSecrets.java | 34 ++++++------------- .../vectorization/VectorizationProvider.java | 5 ++- .../internal/tests/TestTestSecrets.java | 15 ++++---- .../TestVectorizationProvider.java | 2 +- 5 files changed, 23 insertions(+), 36 deletions(-) diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt index e18ae082486e..1dc39e016cd2 100644 --- a/lucene/CHANGES.txt +++ b/lucene/CHANGES.txt @@ -285,6 +285,9 @@ Bug Fixes * GITHUB#12419, GITHUB#15119, GITHUB#15864: Fix circular dependency deadlock in TestSecrets initialization (Namgyu Kim, Uwe Schindler) +* GITHUB#15867: Use IllegalCallerException to signal wrong caller in internal classes + (VectorizationProvider, TestSecrets). (Uwe Schindler) + Other --------------------- * GITHUB#15586: Document that scoring and ranking may change across major Lucene versions, and that applications requiring stable ranking should explicitly configure Similarity. (Parveen Saini) diff --git a/lucene/core/src/java/org/apache/lucene/internal/tests/TestSecrets.java b/lucene/core/src/java/org/apache/lucene/internal/tests/TestSecrets.java index 59a6221bbeab..74bb4ee9e548 100644 --- a/lucene/core/src/java/org/apache/lucene/internal/tests/TestSecrets.java +++ b/lucene/core/src/java/org/apache/lucene/internal/tests/TestSecrets.java @@ -106,47 +106,35 @@ public static FilterIndexInputAccess getFilterInputIndexAccess() { /** For internal initialization only. */ public static void setIndexWriterAccess(IndexWriterAccess indexWriterAccess) { - ensureCallerForSetter(IndexWriter.class); - ensureNull(TestSecrets.indexWriterAccess); + ensureCallerForSetter(IndexWriter.class, TestSecrets.indexWriterAccess); TestSecrets.indexWriterAccess = indexWriterAccess; } /** For internal initialization only. */ public static void setIndexPackageAccess(IndexPackageAccess indexPackageAccess) { - ensureCallerForSetter(IndexWriter.class); - ensureNull(TestSecrets.indexPackageAccess); + ensureCallerForSetter(IndexWriter.class, TestSecrets.indexPackageAccess); TestSecrets.indexPackageAccess = indexPackageAccess; } /** For internal initialization only. */ public static void setConcurrentMergeSchedulerAccess(ConcurrentMergeSchedulerAccess cmsAccess) { - ensureCallerForSetter(ConcurrentMergeScheduler.class); - ensureNull(TestSecrets.cmsAccess); + ensureCallerForSetter(ConcurrentMergeScheduler.class, TestSecrets.cmsAccess); TestSecrets.cmsAccess = cmsAccess; } /** For internal initialization only. */ public static void setSegmentReaderAccess(SegmentReaderAccess segmentReaderAccess) { - ensureCallerForSetter(SegmentReader.class); - ensureNull(TestSecrets.segmentReaderAccess); + ensureCallerForSetter(SegmentReader.class, TestSecrets.segmentReaderAccess); TestSecrets.segmentReaderAccess = segmentReaderAccess; } /** For internal initialization only. */ public static void setFilterInputIndexAccess(FilterIndexInputAccess filterIndexInputAccess) { - ensureCallerForSetter(FilterIndexInput.class); - ensureNull(TestSecrets.filterIndexInputAccess); + ensureCallerForSetter(FilterIndexInput.class, TestSecrets.filterIndexInputAccess); TestSecrets.filterIndexInputAccess = filterIndexInputAccess; } - private static void ensureNull(Object ob) { - if (ob != null) { - throw new UnsupportedOperationException( - "The accessor is already set. It can only be called from inside Lucene Core."); - } - } - - private static void ensureCallerForSetter(Class allowedCaller) { + private static void ensureCallerForSetter(Class allowedCaller, Object needsNull) { final boolean validCaller = StackWalker.getInstance() .walk( @@ -154,10 +142,10 @@ private static void ensureCallerForSetter(Class allowedCaller) { s.skip(2) .limit(1) .map(StackFrame::getClassName) - .allMatch(c -> Objects.equals(c, allowedCaller.getName()))); - if (!validCaller) { - throw new UnsupportedOperationException( - "The accessor can only be set by " + allowedCaller.getName() + "."); + .allMatch(allowedCaller.getName()::equals)); + if (!validCaller || needsNull != null) { + throw new IllegalCallerException( + "The accessor can only be set once by " + allowedCaller.getName() + "."); } } @@ -175,7 +163,7 @@ private static void ensureCallerForGetter() { || c.equals( "org.apache.lucene.index.TestClassloadingDeadlock"))); if (!validCaller) { - throw new UnsupportedOperationException( + throw new IllegalCallerException( "Lucene TestSecrets can only be used by the test-framework."); } } diff --git a/lucene/core/src/java/org/apache/lucene/internal/vectorization/VectorizationProvider.java b/lucene/core/src/java/org/apache/lucene/internal/vectorization/VectorizationProvider.java index 1e429475af4c..60195ad55b29 100644 --- a/lucene/core/src/java/org/apache/lucene/internal/vectorization/VectorizationProvider.java +++ b/lucene/core/src/java/org/apache/lucene/internal/vectorization/VectorizationProvider.java @@ -87,8 +87,7 @@ private static int getUpperJavaFeatureVersion() { * Returns the default instance of the provider matching vectorization possibilities of actual * runtime. * - * @throws UnsupportedOperationException if the singleton getter is not called from known Lucene - * classes. + * @throws IllegalCallerException if the singleton getter is not called from known Lucene classes. */ public static VectorizationProvider getInstance() { ensureCaller(); @@ -225,7 +224,7 @@ private static void ensureCaller() { .map(StackFrame::getClassName) .allMatch(VALID_CALLERS::contains)); if (!validCaller) { - throw new UnsupportedOperationException( + throw new IllegalCallerException( "VectorizationProvider is internal and can only be used by known Lucene classes."); } } diff --git a/lucene/core/src/test/org/apache/lucene/internal/tests/TestTestSecrets.java b/lucene/core/src/test/org/apache/lucene/internal/tests/TestTestSecrets.java index a3655444a894..fd7bd38eee15 100644 --- a/lucene/core/src/test/org/apache/lucene/internal/tests/TestTestSecrets.java +++ b/lucene/core/src/test/org/apache/lucene/internal/tests/TestTestSecrets.java @@ -21,8 +21,8 @@ public class TestTestSecrets extends LuceneTestCase { public void testCallerOfGetter() { - final UnsupportedOperationException expected = - expectThrows(UnsupportedOperationException.class, TestTestSecrets::illegalCaller); + final IllegalCallerException expected = + expectThrows(IllegalCallerException.class, TestTestSecrets::illegalCaller); assertEquals( "Lucene TestSecrets can only be used by the test-framework.", expected.getMessage()); } @@ -32,13 +32,10 @@ private static void illegalCaller() { } public void testCannotSet() { - expectThrows(UnsupportedOperationException.class, () -> TestSecrets.setIndexWriterAccess(null)); + expectThrows(IllegalCallerException.class, () -> TestSecrets.setIndexWriterAccess(null)); expectThrows( - UnsupportedOperationException.class, - () -> TestSecrets.setConcurrentMergeSchedulerAccess(null)); - expectThrows( - UnsupportedOperationException.class, () -> TestSecrets.setIndexPackageAccess(null)); - expectThrows( - UnsupportedOperationException.class, () -> TestSecrets.setSegmentReaderAccess(null)); + IllegalCallerException.class, () -> TestSecrets.setConcurrentMergeSchedulerAccess(null)); + expectThrows(IllegalCallerException.class, () -> TestSecrets.setIndexPackageAccess(null)); + expectThrows(IllegalCallerException.class, () -> TestSecrets.setSegmentReaderAccess(null)); } } diff --git a/lucene/core/src/test/org/apache/lucene/internal/vectorization/TestVectorizationProvider.java b/lucene/core/src/test/org/apache/lucene/internal/vectorization/TestVectorizationProvider.java index 7c7a3453e43e..7772fd456322 100644 --- a/lucene/core/src/test/org/apache/lucene/internal/vectorization/TestVectorizationProvider.java +++ b/lucene/core/src/test/org/apache/lucene/internal/vectorization/TestVectorizationProvider.java @@ -21,7 +21,7 @@ public class TestVectorizationProvider extends LuceneTestCase { public void testCallerOfGetter() { - expectThrows(UnsupportedOperationException.class, TestVectorizationProvider::illegalCaller); + expectThrows(IllegalCallerException.class, TestVectorizationProvider::illegalCaller); } private static void illegalCaller() {