You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by st...@apache.org on 2016/10/31 14:26:15 UTC
svn commit: r1767287 - in /jackrabbit/oak/trunk/oak-jcr/src:
main/java/org/apache/jackrabbit/oak/jcr/observation/
main/java/org/apache/jackrabbit/oak/jcr/observation/filter/
test/java/org/apache/jackrabbit/oak/jcr/observation/
Author: stefanegli
Date: Mon Oct 31 14:26:15 2016
New Revision: 1767287
URL: http://svn.apache.org/viewvc?rev=1767287&view=rev
Log:
OAK-5020 : adding withIncludeAncestorsRemove support to the OakEventFilter: includes NODE_REMOVED events for all parents
Modified:
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/OakEventFilterImpl.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/ObservationManagerImpl.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/filter/OakEventFilter.java
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/observation/ObservationTest.java
Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/OakEventFilterImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/OakEventFilterImpl.java?rev=1767287&r1=1767286&r2=1767287&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/OakEventFilterImpl.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/OakEventFilterImpl.java Mon Oct 31 14:26:15 2016
@@ -20,10 +20,22 @@ package org.apache.jackrabbit.oak.jcr.ob
import static com.google.common.base.Preconditions.checkNotNull;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import static javax.jcr.observation.Event.NODE_REMOVED;
+
import javax.annotation.Nonnull;
import org.apache.jackrabbit.api.observation.JackrabbitEventFilter;
+import org.apache.jackrabbit.oak.commons.PathUtils;
import org.apache.jackrabbit.oak.jcr.observation.filter.OakEventFilter;
+import org.apache.jackrabbit.oak.plugins.observation.filter.FilterBuilder;
+import org.apache.jackrabbit.oak.plugins.observation.filter.PermissionProviderFactory;
+import org.apache.jackrabbit.oak.plugins.observation.filter.FilterBuilder.Condition;
/**
* Implements OakEventFilter which is an extension to the JackrabbitEventFilter
@@ -36,6 +48,9 @@ public class OakEventFilterImpl extends
/** whether or not applyNodeTypeOnSelf feature is enabled */
private boolean applyNodeTypeOnSelf;
+ /** whether or not includeAncestorsRemove feature is enabled */
+ private boolean includeAncestorRemove;
+
public OakEventFilterImpl(@Nonnull JackrabbitEventFilter delegate) {
checkNotNull(delegate);
this.delegate = delegate;
@@ -161,4 +176,77 @@ public class OakEventFilterImpl extends
return applyNodeTypeOnSelf;
}
+ @Override
+ public OakEventFilter withIncludeAncestorsRemove() {
+ this.includeAncestorRemove = true;
+ return this;
+ }
+
+ boolean getIncludeAncestorsRemove() {
+ return includeAncestorRemove;
+ }
+
+ private void addAncestorsRemoveCondition(Set<String> parentPaths, String globPath) {
+ if (globPath == null || !globPath.contains("/")) {
+ return;
+ }
+ // from /a/b/c => add /a and /a/b
+ // from /a/b/** => add /a
+ // from /a => add nothing
+ // from / => add nothing
+ // from /a/b/**/*.html => add /a
+ // from /a/b/*/*.html => add /a
+
+ Iterator<String> it = PathUtils.elements(globPath).iterator();
+ StringBuffer sb = new StringBuffer();
+ while(it.hasNext()) {
+ String element = it.next();
+ if (element.contains("*")) {
+ if (parentPaths.size() > 0) {
+ parentPaths.remove(parentPaths.size()-1);
+ }
+ break;
+ } else if (!it.hasNext()) {
+ break;
+ }
+ sb.append("/");
+ sb.append(element);
+ parentPaths.add(sb.toString() + "/*");
+ }
+ }
+
+ public Condition wrapMainCondition(Condition mainCondition, FilterBuilder filterBuilder, PermissionProviderFactory permissionProviderFactory) {
+ if (!includeAncestorRemove || (getEventTypes() & NODE_REMOVED) != NODE_REMOVED) {
+ return mainCondition;
+ }
+ Set<String> parentPaths = new HashSet<String>();
+ addAncestorsRemoveCondition(parentPaths, getAbsPath());
+ if (getAdditionalPaths() != null) {
+ for (String absPath : getAdditionalPaths()) {
+ addAncestorsRemoveCondition(parentPaths, absPath);
+ }
+ }
+// if (globPaths != null) {
+// for (String globPath : globPaths) {
+// addAncestorsRemoveCondition(parentPaths, globPath);
+// }
+// }
+ if (parentPaths.size() == 0) {
+ return mainCondition;
+ }
+ List<Condition> ancestorsRemoveConditions = new LinkedList<Condition>();
+ for (String aParentPath : parentPaths) {
+ ancestorsRemoveConditions.add(filterBuilder.path(aParentPath));
+ }
+ return filterBuilder.any(
+ mainCondition,
+ filterBuilder.all(
+ filterBuilder.eventType(NODE_REMOVED),
+ filterBuilder.any(ancestorsRemoveConditions),
+ filterBuilder.deleteSubtree(),
+ filterBuilder.accessControl(permissionProviderFactory)
+ )
+ );
+ }
+
}
Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/ObservationManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/ObservationManagerImpl.java?rev=1767287&r1=1767286&r2=1767287&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/ObservationManagerImpl.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/ObservationManagerImpl.java Mon Oct 31 14:26:15 2016
@@ -238,6 +238,13 @@ public class ObservationManagerImpl impl
List<Condition> includeConditions = newArrayList();
for (String path : includePaths) {
includeConditions.add(filterBuilder.path(concat(path, depthPattern)));
+ if (oakEventFilter != null && oakEventFilter.getIncludeAncestorsRemove()) {
+ // with the 'includeAncestorsRemove' extension we need
+ // to register '/' as the base path - done in wrapMainCondition
+ // - in order to catch any node removal. So we have to skip adding
+ // the subtree here as a result.
+ continue;
+ }
filterBuilder.addSubTree(path);
}
@@ -250,11 +257,7 @@ public class ObservationManagerImpl impl
}
}
- filterBuilder
- .includeSessionLocal(!noLocal)
- .includeClusterExternal(!noExternal)
- .includeClusterLocal(!noInternal)
- .condition(filterBuilder.all(
+ Condition condition = filterBuilder.all(
filterBuilder.all(excludeConditions),
filterBuilder.any(includeConditions),
filterBuilder.deleteSubtree(),
@@ -262,7 +265,15 @@ public class ObservationManagerImpl impl
filterBuilder.eventType(eventTypes),
filterBuilder.uuid(Selectors.PARENT, uuids),
filterBuilder.nodeType(nodeTypeSelector, validateNodeTypeNames(nodeTypeName)),
- filterBuilder.accessControl(permissionProviderFactory)));
+ filterBuilder.accessControl(permissionProviderFactory));
+ if (oakEventFilter != null) {
+ condition = oakEventFilter.wrapMainCondition(condition, filterBuilder, permissionProviderFactory);
+ }
+ filterBuilder
+ .includeSessionLocal(!noLocal)
+ .includeClusterExternal(!noExternal)
+ .includeClusterLocal(!noInternal)
+ .condition(condition);
// FIXME support multiple path in ListenerTracker
ListenerTracker tracker = new WarningListenerTracker(
Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/filter/OakEventFilter.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/filter/OakEventFilter.java?rev=1767287&r1=1767286&r2=1767287&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/filter/OakEventFilter.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/filter/OakEventFilter.java Mon Oct 31 14:26:15 2016
@@ -46,4 +46,24 @@ public abstract class OakEventFilter ext
*/
public abstract OakEventFilter withApplyNodeTypeOnSelf();
+ /**
+ * This causes the registration of !deep NODE_REMOVED registrations
+ * of all parents of the include paths (both normal and glob).
+ * <ul>
+ * <li>include path /a/b/c/d results in additional !deep NODE_REMOVED
+ * filters on /a/b/c, on /a/b and on /a</li>
+ * <li>include path /a/b/** results in additional !deep NODE_REMOVED
+ * filter on /a</li>
+ * </ul>
+ * <p>
+ * Note that unlike 'normal' include and exclude paths, this variant
+ * doesn't apply Oak's NamePathMapper on the ancestors of the
+ * registers paths.
+ * <p>
+ * Also note that this might disable 'observation prefiltering based on paths'
+ * (OAK-4796) on this listener.
+ * @return this filter with the filter change applied
+ */
+ public abstract OakEventFilter withIncludeAncestorsRemove();
+
}
Modified: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/observation/ObservationTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/observation/ObservationTest.java?rev=1767287&r1=1767286&r2=1767287&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/observation/ObservationTest.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/observation/ObservationTest.java Mon Oct 31 14:26:15 2016
@@ -1276,6 +1276,75 @@ public class ObservationTest extends Abs
}
+ @Test
+ public void includeAncestorsRemove() throws Exception {
+ assumeTrue(observationManager instanceof ObservationManagerImpl);
+
+ Node testNode = getNode(TEST_PATH);
+ testNode.addNode("a").addNode("b").addNode("c").addNode("d").setProperty("e", 42);
+ testNode.getSession().save();
+
+ ObservationManagerImpl oManager = (ObservationManagerImpl) observationManager;
+ ExpectationListener listener = new ExpectationListener();
+
+ JackrabbitEventFilter filter = new JackrabbitEventFilter();
+ filter.setEventTypes(ALL_EVENTS);
+ filter.setAbsPath(TEST_PATH + "/a/b/c/d");
+ filter.setIsDeep(true);
+ filter = FilterFactory.wrap(filter).withIncludeAncestorsRemove();
+
+ oManager.addEventListener(listener, filter);
+
+ Node d = testNode.getNode("a").getNode("b").getNode("c").getNode("d");
+ Property e = d.getProperty("e");
+ listener.expectRemove(e);
+// listener.expectRemove(d.getProperty("jcr:primaryType"));
+// d.remove();
+ listener.expectRemove(d).remove();
+ testNode.getSession().save();
+
+ Thread.sleep(1000);
+ List<Expectation> missing = listener.getMissing(TIME_OUT, TimeUnit.SECONDS);
+ List<Event> unexpected = listener.getUnexpected();
+ assertTrue("Unexpected events: " + unexpected, unexpected.isEmpty());
+ assertTrue("Missing events: " + missing, missing.isEmpty());
+
+ oManager.addEventListener(new EventListener() {
+
+ @Override
+ public void onEvent(EventIterator events) {
+ while(events.hasNext()) {
+ System.out.println("GOT: "+events.next());
+ }
+
+ }
+ }, NODE_REMOVED, TEST_PATH + "/a", false, null, null, false);
+ System.out.println("REGISTERED");
+
+ testNode = getNode(TEST_PATH);
+ Node b = testNode.getNode("a").getNode("b");
+ listener.expect(b.getPath(), NODE_REMOVED);
+ b.remove();
+ // but not the jcr:primaryType
+ testNode.getSession().save();
+
+ Thread.sleep(1000);
+ missing = listener.getMissing(TIME_OUT, TimeUnit.SECONDS);
+ unexpected = listener.getUnexpected();
+ assertTrue("Missing events: " + missing, missing.isEmpty());
+ assertTrue("Unexpected events: " + unexpected, unexpected.isEmpty());
+
+ Node a = testNode.getNode("a");
+ listener.expect(a.getPath(), NODE_REMOVED);
+ a.remove();
+ // but not the jcr:primaryType
+ testNode.getSession().save();
+
+ missing = listener.getMissing(TIME_OUT, TimeUnit.SECONDS);
+ unexpected = listener.getUnexpected();
+ assertTrue("Unexpected events: " + unexpected, unexpected.isEmpty());
+ assertTrue("Missing events: " + missing, missing.isEmpty());
+ }
}