From 5f03742f54f26c36b885ffbf81d3109dc1dda41d Mon Sep 17 00:00:00 2001 From: Jakub Berlinski Date: Tue, 3 Mar 2026 16:03:17 +0100 Subject: [PATCH 1/3] make Repo.query use actual JCR Query (issue 295) --- .../java/dev/vml/es/acm/core/repo/Repo.java | 22 +++++++++++++++++-- .../dev/vml/es/acm/core/util/StreamUtils.java | 19 ++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/dev/vml/es/acm/core/repo/Repo.java b/core/src/main/java/dev/vml/es/acm/core/repo/Repo.java index 7b9a3d2f7..a6f75a125 100644 --- a/core/src/main/java/dev/vml/es/acm/core/repo/Repo.java +++ b/core/src/main/java/dev/vml/es/acm/core/repo/Repo.java @@ -3,8 +3,11 @@ import dev.vml.es.acm.core.util.StreamUtils; import java.util.stream.Stream; import javax.jcr.Node; +import javax.jcr.RepositoryException; import javax.jcr.Session; import javax.jcr.query.Query; +import javax.jcr.query.QueryManager; +import javax.jcr.query.QueryResult; import org.apache.commons.lang3.StringUtils; import org.apache.jackrabbit.JcrConstants; import org.apache.sling.api.resource.*; @@ -169,8 +172,23 @@ public Stream query(String path, String nodeType, String where, St } public Stream queryRaw(String sql) { - return StreamUtils.asStream(resourceResolver.findResources(sql, Query.JCR_SQL2)) - .map(r -> new RepoResource(this, r.getPath())); + try { + QueryManager queryManager = session.getWorkspace().getQueryManager(); + Query query = queryManager.createQuery(sql, Query.JCR_SQL2); + QueryResult result = query.execute(); + + return StreamUtils.asNodeStream(result.getNodes()).map(n -> { + try { + return new RepoResource(this, n.getPath()); + } catch (RepositoryException e) { + throw new RepoException("Cannot read node path from query result!", e); + } + }); + } catch (RepoException e) { + throw e; + } catch (Exception e) { + throw new RepoException(String.format("Cannot execute raw query '%s'!", sql), e); + } } public boolean isCompositeNodeStore() { diff --git a/core/src/main/java/dev/vml/es/acm/core/util/StreamUtils.java b/core/src/main/java/dev/vml/es/acm/core/util/StreamUtils.java index c316baabc..aecb20cc8 100644 --- a/core/src/main/java/dev/vml/es/acm/core/util/StreamUtils.java +++ b/core/src/main/java/dev/vml/es/acm/core/util/StreamUtils.java @@ -4,6 +4,8 @@ import java.util.Iterator; import java.util.stream.Stream; import java.util.stream.StreamSupport; +import javax.jcr.Node; +import javax.jcr.NodeIterator; public class StreamUtils { @@ -32,4 +34,21 @@ public T next() { } }); } + + public static Stream asNodeStream(NodeIterator nodeIterator) { + if (nodeIterator == null) { + return Stream.empty(); + } + return asStream(new Iterator() { + @Override + public boolean hasNext() { + return nodeIterator.hasNext(); + } + + @Override + public Node next() { + return nodeIterator.nextNode(); + } + }); + } } From 4098c3a14404bf85e3c4dc2938dbe39e8b297f63 Mon Sep 17 00:00:00 2001 From: Krystian Panek Date: Mon, 9 Mar 2026 15:05:29 +0100 Subject: [PATCH 2/3] Hardened jcr query traversal limit --- .../java/dev/vml/es/acm/core/repo/Repo.java | 6 ++--- .../dev/vml/es/acm/core/util/JcrUtils.java | 26 +++++++++++++++++++ .../dev/vml/es/acm/core/util/StreamUtils.java | 22 +++------------- 3 files changed, 31 insertions(+), 23 deletions(-) create mode 100644 core/src/main/java/dev/vml/es/acm/core/util/JcrUtils.java diff --git a/core/src/main/java/dev/vml/es/acm/core/repo/Repo.java b/core/src/main/java/dev/vml/es/acm/core/repo/Repo.java index a6f75a125..2d05108d7 100644 --- a/core/src/main/java/dev/vml/es/acm/core/repo/Repo.java +++ b/core/src/main/java/dev/vml/es/acm/core/repo/Repo.java @@ -1,6 +1,6 @@ package dev.vml.es.acm.core.repo; -import dev.vml.es.acm.core.util.StreamUtils; +import dev.vml.es.acm.core.util.JcrUtils; import java.util.stream.Stream; import javax.jcr.Node; import javax.jcr.RepositoryException; @@ -177,15 +177,13 @@ public Stream queryRaw(String sql) { Query query = queryManager.createQuery(sql, Query.JCR_SQL2); QueryResult result = query.execute(); - return StreamUtils.asNodeStream(result.getNodes()).map(n -> { + return JcrUtils.asNodeStream(result.getNodes()).map(n -> { try { return new RepoResource(this, n.getPath()); } catch (RepositoryException e) { throw new RepoException("Cannot read node path from query result!", e); } }); - } catch (RepoException e) { - throw e; } catch (Exception e) { throw new RepoException(String.format("Cannot execute raw query '%s'!", sql), e); } diff --git a/core/src/main/java/dev/vml/es/acm/core/util/JcrUtils.java b/core/src/main/java/dev/vml/es/acm/core/util/JcrUtils.java new file mode 100644 index 000000000..b91ee7afe --- /dev/null +++ b/core/src/main/java/dev/vml/es/acm/core/util/JcrUtils.java @@ -0,0 +1,26 @@ +package dev.vml.es.acm.core.util; + +import java.util.Iterator; +import java.util.stream.Stream; +import javax.jcr.Node; +import javax.jcr.NodeIterator; + +public class JcrUtils { + + public static Stream asNodeStream(NodeIterator nodeIterator) { + if (nodeIterator == null) { + return Stream.empty(); + } + return StreamUtils.asStream(new Iterator() { + @Override + public boolean hasNext() { + return nodeIterator.hasNext(); + } + + @Override + public Node next() { + return nodeIterator.nextNode(); + } + }); + } +} diff --git a/core/src/main/java/dev/vml/es/acm/core/util/StreamUtils.java b/core/src/main/java/dev/vml/es/acm/core/util/StreamUtils.java index aecb20cc8..d2efee24e 100644 --- a/core/src/main/java/dev/vml/es/acm/core/util/StreamUtils.java +++ b/core/src/main/java/dev/vml/es/acm/core/util/StreamUtils.java @@ -4,8 +4,6 @@ import java.util.Iterator; import java.util.stream.Stream; import java.util.stream.StreamSupport; -import javax.jcr.Node; -import javax.jcr.NodeIterator; public class StreamUtils { @@ -14,6 +12,9 @@ public static Stream asStream(Iterator sourceIterator) { } public static Stream asStream(Iterator sourceIterator, boolean parallel) { + if (sourceIterator == null) { + return Stream.empty(); + } Iterable iterable = () -> sourceIterator; return StreamSupport.stream(iterable.spliterator(), parallel); } @@ -34,21 +35,4 @@ public T next() { } }); } - - public static Stream asNodeStream(NodeIterator nodeIterator) { - if (nodeIterator == null) { - return Stream.empty(); - } - return asStream(new Iterator() { - @Override - public boolean hasNext() { - return nodeIterator.hasNext(); - } - - @Override - public Node next() { - return nodeIterator.nextNode(); - } - }); - } } From 7579d5e6d93e24d1ed616a15151c725ce6f18fb7 Mon Sep 17 00:00:00 2001 From: Krystian Panek Date: Mon, 9 Mar 2026 16:12:58 +0100 Subject: [PATCH 3/3] Repo fix --- core/src/main/java/dev/vml/es/acm/core/repo/Repo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/dev/vml/es/acm/core/repo/Repo.java b/core/src/main/java/dev/vml/es/acm/core/repo/Repo.java index 2d05108d7..d5ee350d9 100644 --- a/core/src/main/java/dev/vml/es/acm/core/repo/Repo.java +++ b/core/src/main/java/dev/vml/es/acm/core/repo/Repo.java @@ -181,7 +181,7 @@ public Stream queryRaw(String sql) { try { return new RepoResource(this, n.getPath()); } catch (RepositoryException e) { - throw new RepoException("Cannot read node path from query result!", e); + throw new RepoException(String.format("Cannot read node path from query result '%s'!", sql), e); } }); } catch (Exception e) {