diff --git a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreService.java b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreService.java index e77388d9488..45484fc1f89 100644 --- a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreService.java +++ b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreService.java @@ -42,6 +42,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.function.Predicate; @@ -660,29 +661,8 @@ protected void deactivate() { journalPropertyHandlerFactory.stop(); } - if (prefetchFeature != null) { - prefetchFeature.close(); - } - - if (docStoreThrottlingFeature != null) { - docStoreThrottlingFeature.close(); - } - - if (cancelInvalidationFeature != null) { - cancelInvalidationFeature.close(); - } - - if (docStoreFullGCFeature != null) { - docStoreFullGCFeature.close(); - } - - if (docStoreEmbeddedVerificationFeature != null) { - docStoreEmbeddedVerificationFeature.close(); - } - - if (prevNoPropCacheFeature != null) { - prevNoPropCacheFeature.close(); - } + closeFeatures(prefetchFeature, docStoreThrottlingFeature, cancelInvalidationFeature, docStoreFullGCFeature, + docStoreEmbeddedVerificationFeature, prevNoPropCacheFeature); unregisterNodeStore(); } @@ -788,6 +768,19 @@ protected void unbindNodeStateCache(DocumentNodeStateCache nodeStateCache) { } } + /** + * Closes the given varargs of features. + *
+ * This method iterates over the provided varargs of features and closes each one + * that is not null. + *
+ * + * @param features a varargs of {@link Feature} objects to be closed. + */ + private void closeFeatures(@NotNull final Feature... features) { + Arrays.stream(features).filter(Objects::nonNull).forEach(Feature::close); + } + private void unregisterNodeStore() { deactivationTimestamp = System.currentTimeMillis(); diff --git a/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreServiceTest.java b/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreServiceTest.java index c0fb2299efa..09af1fbdd0b 100644 --- a/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreServiceTest.java +++ b/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreServiceTest.java @@ -18,10 +18,12 @@ import java.io.File; import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Supplier; +import org.apache.commons.lang3.reflect.MethodUtils; import org.apache.jackrabbit.guava.common.collect.Maps; import com.mongodb.MongoClient; @@ -31,6 +33,7 @@ import org.apache.jackrabbit.oak.plugins.document.spi.JournalPropertyService; import org.apache.jackrabbit.oak.plugins.document.spi.lease.LeaseFailureHandler; import org.apache.jackrabbit.oak.spi.state.NodeStore; +import org.apache.jackrabbit.oak.spi.toggle.Feature; import org.apache.jackrabbit.oak.stats.StatisticsProvider; import org.apache.sling.testing.mock.osgi.MockOsgi; import org.apache.sling.testing.mock.osgi.junit.OsgiContext; @@ -45,6 +48,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.junit.Assume.assumeTrue; @@ -356,6 +360,19 @@ public void recoveryDelayMillisMinute() { doRecoveryDelayMillis(60000); } + @Test + public void closeFeatures() throws InvocationTargetException, IllegalAccessException, NoSuchMethodException { + Feature feature1 = mock(Feature.class); + Feature feature2 = mock(Feature.class); + Feature feature3 = mock(Feature.class); + Feature feature4 = mock(Feature.class); + + // successful invocation would return null + assertNull(MethodUtils.invokeMethod(service, true, "closeFeatures", + new Object[]{feature1, feature2, null, feature3, feature4}, + new Class[]{Feature[].class})); + } + private void doRecoveryDelayMillis(long recoveryDelayMillis) { Map