This is an automated email from the ASF dual-hosted git repository. joerghoh pushed a commit to branch SLING-8413 in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-event.git
commit 268313710ccca423bee8d6678e91b18823478f07 Author: Jörg Hoh <jo...@joerghoh.de> AuthorDate: Mon Jun 6 16:53:04 2022 +0200 SLING-8413 escape topic root in xpath query --- .../sling/event/impl/jobs/JobManagerImpl.java | 111 +++++++++++---------- .../sling/event/impl/jobs/JobManagerImplTest.java | 45 +++++++++ 2 files changed, 103 insertions(+), 53 deletions(-) diff --git a/src/main/java/org/apache/sling/event/impl/jobs/JobManagerImpl.java b/src/main/java/org/apache/sling/event/impl/jobs/JobManagerImpl.java index f419317..a396fc5 100644 --- a/src/main/java/org/apache/sling/event/impl/jobs/JobManagerImpl.java +++ b/src/main/java/org/apache/sling/event/impl/jobs/JobManagerImpl.java @@ -403,59 +403,7 @@ public class JobManagerImpl final ResourceResolver resolver = this.configuration.createResourceResolver(); final StringBuilder buf = new StringBuilder(64); try { - - buf.append("/jcr:root"); - buf.append(this.configuration.getJobsBasePathWithSlash()); - buf.append("/element(*,"); - buf.append(ResourceHelper.RESOURCE_TYPE_JOB); - buf.append(")[@"); - buf.append(ISO9075.encode(ResourceHelper.PROPERTY_JOB_TOPIC)); - if (topic != null) { - buf.append(" = '"); - buf.append(topic); - buf.append("'"); - } - - // restricting on the type - history or unfinished - if ( isHistoryQuery ) { - buf.append(" and @"); - buf.append(ISO9075.encode(JobImpl.PROPERTY_FINISHED_STATE)); - if ( type == QueryType.SUCCEEDED || type == QueryType.DROPPED || type == QueryType.ERROR || type == QueryType.GIVEN_UP || type == QueryType.STOPPED ) { - buf.append(" = '"); - buf.append(type.name()); - buf.append("'"); - } else if ( type == QueryType.CANCELLED ) { - buf.append(" and (@"); - buf.append(ISO9075.encode(JobImpl.PROPERTY_FINISHED_STATE)); - buf.append(" = '"); - buf.append(QueryType.DROPPED.name()); - buf.append("' or @"); - buf.append(ISO9075.encode(JobImpl.PROPERTY_FINISHED_STATE)); - buf.append(" = '"); - buf.append(QueryType.ERROR.name()); - buf.append("' or @"); - buf.append(ISO9075.encode(JobImpl.PROPERTY_FINISHED_STATE)); - buf.append(" = '"); - buf.append(QueryType.GIVEN_UP.name()); - buf.append("' or @"); - buf.append(ISO9075.encode(JobImpl.PROPERTY_FINISHED_STATE)); - buf.append(" = '"); - buf.append(QueryType.STOPPED.name()); - buf.append("')"); - } - } else { - buf.append(" and not(@"); - buf.append(ISO9075.encode(JobImpl.PROPERTY_FINISHED_STATE)); - buf.append(")"); - if ( type == QueryType.ACTIVE ) { - buf.append(" and @"); - buf.append(ISO9075.encode(Job.PROPERTY_JOB_STARTED_TIME)); - } else if ( type == QueryType.QUEUED ) { - buf.append(" and not(@"); - buf.append(ISO9075.encode(Job.PROPERTY_JOB_STARTED_TIME)); - buf.append(")"); - } - } + buf.append(buildBaseQuery(this.configuration.getJobsBasePathWithSlash(), topic, type, isHistoryQuery)); if ( templates != null && templates.length > 0 ) { int index = 0; @@ -560,6 +508,63 @@ public class JobManagerImpl return result; } + protected static String buildBaseQuery(final String queryRoot, final String topic, final QueryType type, final boolean isHistoryQuery) { + StringBuilder buf = new StringBuilder(); + buf.append("/jcr:root"); + buf.append(queryRoot); + buf.append("/element(*,"); + buf.append(ResourceHelper.RESOURCE_TYPE_JOB); + buf.append(")[@"); + buf.append(ISO9075.encode(ResourceHelper.PROPERTY_JOB_TOPIC)); + if (topic != null) { + buf.append(" = '"); + buf.append(topic.replace("'", "''")); + buf.append("'"); + } + + // restricting on the type - history or unfinished + if ( isHistoryQuery ) { + buf.append(" and @"); + buf.append(ISO9075.encode(JobImpl.PROPERTY_FINISHED_STATE)); + if ( type == QueryType.SUCCEEDED || type == QueryType.DROPPED || type == QueryType.ERROR || type == QueryType.GIVEN_UP || type == QueryType.STOPPED ) { + buf.append(" = '"); + buf.append(type.name()); + buf.append("'"); + } else if ( type == QueryType.CANCELLED ) { + buf.append(" and (@"); + buf.append(ISO9075.encode(JobImpl.PROPERTY_FINISHED_STATE)); + buf.append(" = '"); + buf.append(QueryType.DROPPED.name()); + buf.append("' or @"); + buf.append(ISO9075.encode(JobImpl.PROPERTY_FINISHED_STATE)); + buf.append(" = '"); + buf.append(QueryType.ERROR.name()); + buf.append("' or @"); + buf.append(ISO9075.encode(JobImpl.PROPERTY_FINISHED_STATE)); + buf.append(" = '"); + buf.append(QueryType.GIVEN_UP.name()); + buf.append("' or @"); + buf.append(ISO9075.encode(JobImpl.PROPERTY_FINISHED_STATE)); + buf.append(" = '"); + buf.append(QueryType.STOPPED.name()); + buf.append("')"); + } + } else { + buf.append(" and not(@"); + buf.append(ISO9075.encode(JobImpl.PROPERTY_FINISHED_STATE)); + buf.append(")"); + if ( type == QueryType.ACTIVE ) { + buf.append(" and @"); + buf.append(ISO9075.encode(Job.PROPERTY_JOB_STARTED_TIME)); + } else if ( type == QueryType.QUEUED ) { + buf.append(" and not(@"); + buf.append(ISO9075.encode(Job.PROPERTY_JOB_STARTED_TIME)); + buf.append(")"); + } + } + return buf.toString(); + } + /** * Persist the job in the resource tree * @param jobTopic The required job topic diff --git a/src/test/java/org/apache/sling/event/impl/jobs/JobManagerImplTest.java b/src/test/java/org/apache/sling/event/impl/jobs/JobManagerImplTest.java new file mode 100644 index 0000000..2ac24ea --- /dev/null +++ b/src/test/java/org/apache/sling/event/impl/jobs/JobManagerImplTest.java @@ -0,0 +1,45 @@ +/* + * 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.sling.event.impl.jobs; + +import static org.junit.Assert.assertEquals; + +import org.apache.sling.event.jobs.JobManager.QueryType; +import org.junit.Test; + +public class JobManagerImplTest { + + + private static final String QUERY_ROOT = "/var/eventing/foobar"; + private static final QueryType QUERY_TYPE = QueryType.ACTIVE; + + // SLING-8413 + @Test + public void testTopicEscaping() { + String baseQuery = JobManagerImpl.buildBaseQuery(QUERY_ROOT, "randomNonQuotedTopic", QUERY_TYPE, false); + assertEquals("/jcr:root/var/eventing/foobar/element(*,slingevent:Job)[@event.job.topic = " + + "'randomNonQuotedTopic' and not(@slingevent:finishedState) and @event.job.started.time",baseQuery); + + String baseQuery2 = JobManagerImpl.buildBaseQuery(QUERY_ROOT, "random'Topic", QUERY_TYPE, false); + assertEquals("/jcr:root/var/eventing/foobar/element(*,slingevent:Job)[@event.job.topic = " + + "'random''Topic' and not(@slingevent:finishedState) and @event.job.started.time",baseQuery2); + + } + +}