This is an automated email from the ASF dual-hosted git repository. daim pushed a commit to branch DetailedGC/OAK-10199 in repository https://gitbox.apache.org/repos/asf/jackrabbit-oak.git
commit c8e95876347639332d4d46082a232fd5e7859cc8 Author: Mark Adamcin <[email protected]> AuthorDate: Wed Jan 10 08:36:38 2024 -0800 OAK-10424 : Allow Fast Query Size and Insecure Facets to be selectively enabled with query options for permitted principals --- .../query/SessionQuerySettingsProviderService.java | 89 +++++++ .../oak/jcr/repository/RepositoryImpl.java | 34 ++- .../jackrabbit/oak/jcr/session/SessionContext.java | 14 +- .../oak/jcr/OakSegmentTarRepositoryStub.java | 20 +- .../oak/jcr/query/WhiteboardResultSizeTest.java | 264 +++++++++++++++++++++ .../oak/spi/query/SessionQuerySettings.java | 37 +++ .../spi/query/SessionQuerySettingsProvider.java | 41 ++++ .../jackrabbit/oak/spi/query/package-info.java | 2 +- 8 files changed, 489 insertions(+), 12 deletions(-) diff --git a/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SessionQuerySettingsProviderService.java b/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SessionQuerySettingsProviderService.java new file mode 100644 index 0000000000..5d2a068acf --- /dev/null +++ b/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SessionQuerySettingsProviderService.java @@ -0,0 +1,89 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.jackrabbit.oak.query; + +import org.apache.jackrabbit.oak.api.ContentSession; +import org.apache.jackrabbit.oak.spi.query.SessionQuerySettings; +import org.apache.jackrabbit.oak.spi.query.SessionQuerySettingsProvider; +import org.jetbrains.annotations.NotNull; +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.ConfigurationPolicy; +import org.osgi.service.component.annotations.Modified; +import org.osgi.service.metatype.annotations.AttributeDefinition; +import org.osgi.service.metatype.annotations.Designate; +import org.osgi.service.metatype.annotations.ObjectClassDefinition; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Optional; +import java.util.Set; + +/** + * Overrides oak.fastQuerySize system property when available. + */ +@Component(configurationPolicy = ConfigurationPolicy.REQUIRE, immediate = true) +@Designate(ocd = SessionQuerySettingsProviderService.Configuration.class) +public class SessionQuerySettingsProviderService implements SessionQuerySettingsProvider { + + @ObjectClassDefinition( + name = "Apache Jackrabbit Session Query Settings Provider Service", + description = "Provides Session-specific query settings exposed by Oak QueryEngine." + ) + @Retention(RetentionPolicy.RUNTIME) + public @interface Configuration { + @AttributeDefinition(name = "Direct Counts Principals", description = "Principal names for which executed query result counts directly reflect the index estimate.") + String[] directCountsPrincipals() default {}; + } + + void configure(Configuration config) { + this.directCountsAllowedPrincipals = Optional.ofNullable(config) + .map(cfg -> (Set<String>) new HashSet<>(Arrays.asList(cfg.directCountsPrincipals()))) + .orElse(Collections.emptySet()); + } + + @Activate + protected void activate(Configuration config) { + configure(config); + } + + @Modified + protected void modified(Configuration config) { + configure(config); + } + + private Set<String> directCountsAllowedPrincipals = Collections.emptySet(); + + @Override + public SessionQuerySettings getQuerySettings(@NotNull ContentSession session) { + final Set<String> principals = directCountsAllowedPrincipals; + final boolean directCountsAllowed = session.getAuthInfo().getPrincipals().stream() + .anyMatch(principal -> principals.contains(principal.getName())); + return new SessionQuerySettings() { + @Override + public boolean useDirectResultCount() { + return directCountsAllowed; + } + }; + } +} diff --git a/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/repository/RepositoryImpl.java b/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/repository/RepositoryImpl.java index dd77a88ca1..12ad5f7f87 100644 --- a/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/repository/RepositoryImpl.java +++ b/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/repository/RepositoryImpl.java @@ -23,6 +23,7 @@ import static org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardUtils.registerM import java.io.Closeable; import java.util.Map; +import java.util.Optional; import java.util.concurrent.Callable; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; @@ -61,6 +62,8 @@ import org.apache.jackrabbit.oak.plugins.observation.CommitRateLimiter; import org.apache.jackrabbit.oak.spi.gc.DelegatingGCMonitor; import org.apache.jackrabbit.oak.spi.gc.GCMonitor; import org.apache.jackrabbit.oak.spi.mount.MountInfoProvider; +import org.apache.jackrabbit.oak.spi.query.SessionQuerySettings; +import org.apache.jackrabbit.oak.spi.query.SessionQuerySettingsProvider; import org.apache.jackrabbit.oak.spi.security.SecurityProvider; import org.apache.jackrabbit.oak.spi.whiteboard.Registration; import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard; @@ -118,6 +121,7 @@ public class RepositoryImpl implements JackrabbitRepository { private final Registration gcMonitorRegistration; private final MountInfoProvider mountInfoProvider; private final BlobAccessProvider blobAccessProvider; + private final SessionQuerySettingsProvider sessionQuerySettingsProvider; /** * {@link ThreadLocal} counter that keeps track of the save operations @@ -172,6 +176,8 @@ public class RepositoryImpl implements JackrabbitRepository { this.mountInfoProvider = WhiteboardUtils.getService(whiteboard, MountInfoProvider.class); this.blobAccessProvider = WhiteboardUtils.getService(whiteboard, BlobAccessProvider.class); this.frozenNodeLogger = new FrozenNodeLogger(clock, whiteboard); + this.sessionQuerySettingsProvider = Optional.ofNullable(WhiteboardUtils.getService(whiteboard, SessionQuerySettingsProvider.class)) + .orElseGet(() -> new FastQuerySizeSettingsProvider(fastQueryResultSize)); } //---------------------------------------------------------< Repository >--- @@ -371,7 +377,8 @@ public class RepositoryImpl implements JackrabbitRepository { Map<String, Object> attributes, SessionDelegate delegate, int observationQueueLength, CommitRateLimiter commitRateLimiter) { return new SessionContext(this, statisticManager, securityProvider, whiteboard, attributes, - delegate, observationQueueLength, commitRateLimiter, mountInfoProvider, blobAccessProvider, fastQueryResultSize); + delegate, observationQueueLength, commitRateLimiter, mountInfoProvider, blobAccessProvider, + sessionQuerySettingsProvider.getQuerySettings(delegate.getContentSession())); } /** @@ -564,4 +571,29 @@ public class RepositoryImpl implements JackrabbitRepository { } } } + + /** + * This is a fallback implementation of {@link org.apache.jackrabbit.oak.spi.query.SessionQuerySettingsProvider} that + * unifies and replaces the previous handling of {@code fastQueryResultSize} and {@code oak.fastQuerySize} here + * and in the {@link org.apache.jackrabbit.oak.jcr.session.SessionContext}. + */ + private static class FastQuerySizeSettingsProvider implements SessionQuerySettingsProvider { + private final boolean fastQueryResultSize; + + public FastQuerySizeSettingsProvider(boolean fastQueryResultSize) { + this.fastQueryResultSize = fastQueryResultSize; + } + + @Override + public @NotNull SessionQuerySettings getQuerySettings(@NotNull ContentSession session) { + return new SessionQuerySettings() { + @Override + public boolean useDirectResultCount() { + return Optional.ofNullable(System.getProperty("oak.fastQuerySize")) + .map(Boolean::valueOf) + .orElse(FastQuerySizeSettingsProvider.this.fastQueryResultSize); + } + }; + } + } } diff --git a/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/SessionContext.java b/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/SessionContext.java index fd1d4cdfba..5221ef41c9 100644 --- a/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/SessionContext.java +++ b/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/SessionContext.java @@ -57,6 +57,7 @@ import org.apache.jackrabbit.oak.plugins.nodetype.ReadOnlyNodeTypeManager; import org.apache.jackrabbit.oak.plugins.observation.CommitRateLimiter; import org.apache.jackrabbit.oak.plugins.value.jcr.ValueFactoryImpl; import org.apache.jackrabbit.oak.spi.mount.MountInfoProvider; +import org.apache.jackrabbit.oak.spi.query.SessionQuerySettings; import org.apache.jackrabbit.oak.spi.security.SecurityConfiguration; import org.apache.jackrabbit.oak.spi.security.SecurityProvider; import org.apache.jackrabbit.oak.spi.security.authorization.AuthorizationConfiguration; @@ -114,7 +115,7 @@ public class SessionContext implements NamePathMapper { /** Paths of all session scoped locks held by this session. */ private final Set<String> sessionScopedLocks = newHashSet(); - private final boolean fastQueryResultSize; + private final SessionQuerySettings sessionQuerySettings; public SessionContext( @NotNull Repository repository, @NotNull StatisticManager statisticManager, @@ -123,7 +124,7 @@ public class SessionContext implements NamePathMapper { int observationQueueLength, CommitRateLimiter commitRateLimiter) { this(repository, statisticManager, securityProvider, whiteboard, attributes, delegate, - observationQueueLength, commitRateLimiter, null, null, false); + observationQueueLength, commitRateLimiter, null, null, null); } public SessionContext( @@ -132,7 +133,7 @@ public class SessionContext implements NamePathMapper { @NotNull Map<String, Object> attributes, @NotNull final SessionDelegate delegate, int observationQueueLength, CommitRateLimiter commitRateLimiter, MountInfoProvider mountInfoProvider, @Nullable BlobAccessProvider blobAccessProvider, - boolean fastQueryResultSize) { + @Nullable SessionQuerySettings sessionQuerySettings) { this.repository = checkNotNull(repository); this.statisticManager = statisticManager; this.securityProvider = checkNotNull(securityProvider); @@ -150,7 +151,7 @@ public class SessionContext implements NamePathMapper { delegate.getNamespaces(), delegate.getIdManager()); this.valueFactory = new ValueFactoryImpl( delegate.getRoot(), namePathMapper, this.blobAccessProvider); - this.fastQueryResultSize = fastQueryResultSize; + this.sessionQuerySettings = sessionQuerySettings; } public final Map<String, Object> getAttributes() { @@ -324,10 +325,7 @@ public class SessionContext implements NamePathMapper { } public boolean getFastQueryResultSize() { - if (System.getProperty("oak.fastQuerySize") != null) { - return Boolean.getBoolean("oak.fastQuerySize"); - } - return fastQueryResultSize; + return this.sessionQuerySettings != null && this.sessionQuerySettings.useDirectResultCount(); } @Nullable diff --git a/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/OakSegmentTarRepositoryStub.java b/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/OakSegmentTarRepositoryStub.java index 45ecbdd58e..093f70a9c2 100644 --- a/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/OakSegmentTarRepositoryStub.java +++ b/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/OakSegmentTarRepositoryStub.java @@ -27,6 +27,7 @@ import org.apache.jackrabbit.oak.Oak; import org.apache.jackrabbit.oak.segment.SegmentNodeStoreBuilders; import org.apache.jackrabbit.oak.segment.file.FileStore; import org.apache.jackrabbit.oak.segment.file.FileStoreBuilder; +import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard; /** * A repository stub implementation for Oak Segment Tar @@ -49,8 +50,9 @@ public class OakSegmentTarRepositoryStub extends BaseRepositoryStub { try { File directory = new File("target", "segment-tar-" + System.currentTimeMillis()); this.store = FileStoreBuilder.fileStoreBuilder(directory).withMaxFileSize(1).build(); - Jcr jcr = new Jcr(new Oak(SegmentNodeStoreBuilders.builder(store).build())); - preCreateRepository(jcr); + Oak oak = new Oak(SegmentNodeStoreBuilders.builder(store).build()); + Jcr jcr = new Jcr(oak); + preCreateRepository(jcr, oak.getWhiteboard()); this.repository = jcr.createRepository(); loadTestContent(repository); } catch (Exception e) { @@ -64,6 +66,20 @@ public class OakSegmentTarRepositoryStub extends BaseRepositoryStub { })); } + /** + * Override in subclass and perform additional configuration on the + * {@link Jcr} builder before the repository is created. This default + * implementation set query engine settings as returned by + * {@link #getQueryEngineSettings()} and adds a + * {@link org.apache.jackrabbit.oak.plugins.document.bundlor.BundlingConfigInitializer}. + * + * @param jcr the builder. + * @param whiteboard the oak whiteboard + */ + protected void preCreateRepository(Jcr jcr, Whiteboard whiteboard) { + this.preCreateRepository(jcr); + } + /** * Returns the configured repository instance. * diff --git a/oak-lucene/src/test/java/org/apache/jackrabbit/oak/jcr/query/WhiteboardResultSizeTest.java b/oak-lucene/src/test/java/org/apache/jackrabbit/oak/jcr/query/WhiteboardResultSizeTest.java new file mode 100644 index 0000000000..de5fbae473 --- /dev/null +++ b/oak-lucene/src/test/java/org/apache/jackrabbit/oak/jcr/query/WhiteboardResultSizeTest.java @@ -0,0 +1,264 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.jackrabbit.oak.jcr.query; + +import org.apache.jackrabbit.api.JackrabbitRepository; +import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils; +import org.apache.jackrabbit.oak.jcr.Jcr; +import org.apache.jackrabbit.oak.jcr.LuceneOakRepositoryStub; +import org.apache.jackrabbit.oak.spi.query.SessionQuerySettingsProvider; +import org.apache.jackrabbit.oak.query.SessionQuerySettingsProviderService; +import org.apache.jackrabbit.oak.spi.security.principal.EveryonePrincipal; +import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard; +import org.apache.jackrabbit.test.RepositoryStub; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import javax.jcr.Credentials; +import javax.jcr.Node; +import javax.jcr.NodeIterator; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.query.Query; +import javax.jcr.query.QueryManager; +import javax.jcr.security.Privilege; +import java.io.InputStream; +import java.lang.reflect.Method; +import java.util.Collections; +import java.util.Properties; +import java.util.concurrent.CompletableFuture; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +/** + * Performs the same queries as {@link ResultSizeTest#testResultSize()} and expects the same results, with the only + * differences being the registration of a {@link org.apache.jackrabbit.oak.spi.query.SessionQuerySettingsProvider} service + * in the whiteboard, and the runtime reconfiguration of the service before each login, in place of the calls to + * {@code System.setProperty("oak.fastQuerySize", true/false)}. + */ +public class WhiteboardResultSizeTest { + + /** + * Non-static inner class extending RepositoryStub which is intended to be created directly by a test + * and not by the TCK RepositoryHelper, purely so that it can mirror the behavior of + * {@link org.apache.jackrabbit.oak.jcr.query.ResultSizeTest} with the only differences being the registration of + * a {@link org.apache.jackrabbit.oak.spi.query.SessionQuerySettingsProvider} service in the whiteboard, and the + * runtime reconfiguration of the service before each login, in place of the calls to + * {@code System.setProperty("oak.fastQuerySize", true/false)}. + */ + public class OakResultSizeStub extends LuceneOakRepositoryStub { + public OakResultSizeStub(Properties settings) throws RepositoryException { + super(settings); + } + + @Override + protected void preCreateRepository(Jcr jcr, Whiteboard whiteboard) { + // register the SessionQuerySettingsProvider service before creation of the repository. + whiteboard.register(SessionQuerySettingsProvider.class, + settingsProviderService, + Collections.emptyMap()); + super.preCreateRepository(jcr, whiteboard); + } + } + + @SessionQuerySettingsProviderService.Configuration(directCountsPrincipals = {"admin"}) + static class AdminAllowed { + /* class which hosts a config annotation for reflection */ + } + + @SessionQuerySettingsProviderService.Configuration + static class NoneAllowed { + /* class which hosts a config annotation for reflection */ + } + + private SessionQuerySettingsProviderService settingsProviderService = + new SessionQuerySettingsProviderService(); + private RepositoryStub stub; + private volatile Repository repository; + private volatile Session adminSession; + + /** + * Reconfigures the singleton {@link org.apache.jackrabbit.oak.query.SessionQuerySettingsProviderService} instance between queries. + * + * @param config a config annotation + * @throws Exception for reflection errors + */ + private void reconfigure(SessionQuerySettingsProviderService.Configuration config) throws Exception { + Method method = SessionQuerySettingsProviderService.class.getDeclaredMethod("configure", + SessionQuerySettingsProviderService.Configuration.class); + method.setAccessible(true); + method.invoke(settingsProviderService, config); + } + + protected Session getAdminSession() throws Exception { + if (adminSession == null) { + adminSession = createAdminSession(); + AccessControlUtils.addAccessControlEntry(adminSession, "/", EveryonePrincipal.getInstance(), + new String[]{Privilege.JCR_READ}, true); + adminSession.save(); + } + return adminSession; + } + + private void createData() throws Exception { + Session session = getAdminSession(); + Node testRootNode = session.getRootNode().addNode("testroot", "nt:unstructured"); + for (int i = 0; i < 200; i++) { + Node n = testRootNode.addNode("node" + i); + n.setProperty("text", "Hello World"); + } + session.save(); + } + + @Test + public void testResultSize() throws Exception { + doTestResultSize(false); + } + + private void doTestResultSize(boolean aggregateAtQueryTime) throws Exception { + createData(); + int expectedForUnion = 400; + int expectedForTwoConditions = aggregateAtQueryTime ? 400 : 200; + doTestResultSize(false, expectedForTwoConditions); + doTestResultSize(true, expectedForUnion); + } + + /** + * Compare with {@code org.apache.jackrabbit.oak.jcr.query.ResultSizeTest#doTestResultSize(boolean, int)}. + */ + private void doTestResultSize(boolean union, int expected) throws Exception { + Session session = null; + QueryManager qm; + Query q; + long result; + NodeIterator it; + StringBuilder buff; + + String xpath; + if (union) { + xpath = "/jcr:root//*[jcr:contains(@text, 'Hello') or jcr:contains(@text, 'World')]"; + } else { + xpath = "/jcr:root//*[jcr:contains(@text, 'Hello World')]"; + } + + final CompletableFuture<String> fastSizeResult = new CompletableFuture<>(); + + reconfigure(AdminAllowed.class.getAnnotation(SessionQuerySettingsProviderService.Configuration.class)); + try { + session = this.createAdminSession(); + assertEquals("nt:unstructured", + session.getNode("/testroot").getPrimaryNodeType().getName()); + qm = session.getWorkspace().getQueryManager(); + q = qm.createQuery(xpath, "xpath"); + it = q.execute().getNodes(); + result = it.getSize(); + assertTrue("size: " + result + " expected around " + expected, + result > expected - 50 && + result < expected + 50); + buff = new StringBuilder(); + while (it.hasNext()) { + Node n = it.nextNode(); + buff.append(n.getPath()).append('\n'); + } + fastSizeResult.complete(buff.toString()); + q = qm.createQuery(xpath, "xpath"); + q.setLimit(90); + it = q.execute().getNodes(); + assertEquals(90, it.getSize()); + } finally { + if (session != null) { + session.logout(); + } + } + + reconfigure(NoneAllowed.class.getAnnotation(SessionQuerySettingsProviderService.Configuration.class)); + try { + session = this.createAdminSession(); + qm = session.getWorkspace().getQueryManager(); + q = qm.createQuery(xpath, "xpath"); + it = q.execute().getNodes(); + result = it.getSize(); + assertEquals(-1, result); + buff = new StringBuilder(); + while (it.hasNext()) { + Node n = it.nextNode(); + buff.append(n.getPath()).append('\n'); + } + String regularResult = buff.toString(); + assertEquals(regularResult, fastSizeResult.get()); + } finally { + if (session != null) { + session.logout(); + } + } + } + + // ----< repository initialization methods >-------- + + @Before + public void setUp() throws Exception { + getAdminSession(); + } + + @After + public void logout() { + if (adminSession != null) { + adminSession.logout(); + adminSession = null; + } + // release repository field + if (repository instanceof JackrabbitRepository) { + ((JackrabbitRepository) repository).shutdown(); + } + repository = null; + stub = null; + } + + protected RepositoryStub getStub() throws Exception { + if (stub == null) { + Properties properties = new Properties(); + try (InputStream is = RepositoryStub.class.getClassLoader().getResourceAsStream(RepositoryStub.STUB_IMPL_PROPS)) { + if (is != null) { + properties.load(is); + } + } + stub = new OakResultSizeStub(properties); + } + return stub; + } + + protected Repository getRepository() throws Exception { + if (repository == null) { + repository = getStub().getRepository(); + } + return repository; + } + + protected Session createAdminSession() throws Exception { + return getRepository().login(getAdminCredentials()); + } + + protected Credentials getAdminCredentials() { + return stub.getSuperuserCredentials(); + } + +} diff --git a/oak-query-spi/src/main/java/org/apache/jackrabbit/oak/spi/query/SessionQuerySettings.java b/oak-query-spi/src/main/java/org/apache/jackrabbit/oak/spi/query/SessionQuerySettings.java new file mode 100644 index 0000000000..80b58b6167 --- /dev/null +++ b/oak-query-spi/src/main/java/org/apache/jackrabbit/oak/spi/query/SessionQuerySettings.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.jackrabbit.oak.spi.query; + +import org.osgi.annotation.versioning.ProviderType; + +/** + * User-specific settings which may be passed by the query engine to index providers during query planning and iteration + * of results. + */ +@ProviderType +public interface SessionQuerySettings { + + /** + * Return true to use the index provider's query result count. + * + * @return true to use the index provider's query result count + */ + boolean useDirectResultCount(); +} diff --git a/oak-query-spi/src/main/java/org/apache/jackrabbit/oak/spi/query/SessionQuerySettingsProvider.java b/oak-query-spi/src/main/java/org/apache/jackrabbit/oak/spi/query/SessionQuerySettingsProvider.java new file mode 100644 index 0000000000..67d994f715 --- /dev/null +++ b/oak-query-spi/src/main/java/org/apache/jackrabbit/oak/spi/query/SessionQuerySettingsProvider.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.jackrabbit.oak.spi.query; + +import org.apache.jackrabbit.oak.api.ContentSession; +import org.jetbrains.annotations.NotNull; +import org.osgi.annotation.versioning.ProviderType; + +/** + * Provides {@link SessionQuerySettings} for principals with access to the content + * repository. + */ +@ProviderType +@FunctionalInterface +public interface SessionQuerySettingsProvider { + + /** + * Return the applicable {@link SessionQuerySettings} for the given session. + * + * @param session the subject principal's content session + * @return the applicable query settings + */ + SessionQuerySettings getQuerySettings(@NotNull ContentSession session); +} diff --git a/oak-query-spi/src/main/java/org/apache/jackrabbit/oak/spi/query/package-info.java b/oak-query-spi/src/main/java/org/apache/jackrabbit/oak/spi/query/package-info.java index 0f958cf31a..1287024c94 100644 --- a/oak-query-spi/src/main/java/org/apache/jackrabbit/oak/spi/query/package-info.java +++ b/oak-query-spi/src/main/java/org/apache/jackrabbit/oak/spi/query/package-info.java @@ -18,7 +18,7 @@ /** * This package contains oak query index related classes. */ -@Version("1.7.0") +@Version("1.8.0") package org.apache.jackrabbit.oak.spi.query; import org.osgi.annotation.versioning.Version;
