diff --git a/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/principal/PrincipalProvider.java b/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/principal/PrincipalProvider.java index 5291275d6c..69182f233a 100644 --- a/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/principal/PrincipalProvider.java +++ b/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/principal/PrincipalProvider.java @@ -21,6 +21,11 @@ import java.security.acl.Group; import java.util.Collections; import java.util.Iterator; import java.util.Set; +import java.util.Spliterator; +import java.util.Spliterators; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.osgi.annotation.versioning.ProviderType; @@ -116,6 +121,36 @@ public interface PrincipalProvider { @NotNull Iterator findPrincipals(@Nullable String nameHint, int searchType); + /** + * Find the principals that match the specified nameHint and search type. + * + * @param nameHint A name hint to use for non-exact matching. + * @param searchType Limit the search to certain types of principals. Valid + * values are any of + * + * + * + * @param offset Offset from where to start returning results. 0 for no offset. + * @param limit Maximal number of results to return. -1 for no limit. + * @return An iterator of principals. + * @throws IllegalArgumentException if {@code offset} is negative + */ + @NotNull + default Iterator findPrincipals(@Nullable String nameHint, int searchType, long offset, long limit) { + if (offset < 0) { + throw new IllegalArgumentException(Long.toString(offset)); + } + Iterator principals = findPrincipals(nameHint, searchType); + Spliterator spliterator = Spliterators.spliteratorUnknownSize(principals, 0); + Stream stream = StreamSupport.stream(spliterator, false); + if (offset > 0) { + stream = stream.skip(offset); + } + if (limit >= 0) { + stream = stream.limit(limit); + } + return stream.iterator(); + } /** * Find all principals that match the search type. @@ -129,4 +164,34 @@ public interface PrincipalProvider { */ @NotNull Iterator findPrincipals(int searchType); + + /** + * Find all principals that match the search type. + * + * @param searchType Limit the search to certain types of principals. Valid + * values are any of + * + * + * + * @param offset Offset from where to start returning results. {@code 0} for no offset. + * @param limit Maximal number of results to return. {@code -1} for no limit. + * @return An iterator of principals. + * @throws IllegalArgumentException if {@code offset} is negative + */ + @NotNull + default Iterator findPrincipals(int searchType, long offset, long limit) { + if (offset < 0) { + throw new IllegalArgumentException(Long.toString(offset)); + } + Iterator principals = findPrincipals(searchType); + Spliterator spliterator = Spliterators.spliteratorUnknownSize(principals, 0); + Stream stream = StreamSupport.stream(spliterator, false); + if (offset > 0) { + stream = stream.skip(offset); + } + if (limit >= 0) { + stream = stream.limit(limit); + } + return stream.iterator(); + } } diff --git a/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/principal/package-info.java b/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/principal/package-info.java index ee57ad99b6..014ab7aabe 100644 --- a/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/principal/package-info.java +++ b/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/principal/package-info.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -@Version("1.6.0") +@Version("1.7.0") package org.apache.jackrabbit.oak.spi.security.principal; import org.osgi.annotation.versioning.Version; diff --git a/oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/principal/CompositePrincipalProviderTest.java b/oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/principal/CompositePrincipalProviderTest.java index f8eac01219..0ced3724e2 100644 --- a/oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/principal/CompositePrincipalProviderTest.java +++ b/oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/principal/CompositePrincipalProviderTest.java @@ -17,7 +17,9 @@ package org.apache.jackrabbit.oak.spi.security.principal; import java.security.Principal; +import java.util.ArrayList; import java.util.Iterator; +import java.util.List; import com.google.common.base.Predicate; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; @@ -135,4 +137,31 @@ public class CompositePrincipalProviderTest { Iterator result = cpp.findPrincipals(PrincipalManager.SEARCH_TYPE_ALL); assertIterator(Iterables.concat(ImmutableSet.of(EveryonePrincipal.getInstance()), testPrincipals()), result); } + + @Test + public void testRangeDefault() { + String[] pps = new String[] { "p0", "p1", "p2" }; + PrincipalProvider p = new TestPrincipalProvider(pps); + PrincipalProvider cpp = CompositePrincipalProvider.of(ImmutableList.of(p)); + List expected = ImmutableList.of("p0", "p1", "p2", "everyone"); + for (int offset = 0; offset < expected.size() + 1; offset++) { + for (int limit = -1; limit < expected.size() + 2; limit++) { + int to = expected.size(); + if (limit >= 0) { + to = Math.min(offset + limit, to); + } + List sub = expected.subList(offset, to); + Iterator i = cpp.findPrincipals(PrincipalManager.SEARCH_TYPE_ALL, offset, limit); + assertEquals(sub, getNames(i)); + } + } + } + + private static List getNames(Iterator i) { + List l = new ArrayList<>(); + while (i.hasNext()) { + l.add(i.next().getName()); + } + return l; + } }