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 md...@apache.org on 2013/10/29 16:31:14 UTC

svn commit: r1536757 - in /jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation: ChangeProcessor.java EventGenerator.java

Author: mduerig
Date: Tue Oct 29 15:31:14 2013
New Revision: 1536757

URL: http://svn.apache.org/r1536757
Log:
OAK-144 Implement observation
- Use event filter from the time of the call to onEvent instead of from the time the events are iterated
- Move EventGeneratingValidator to stand alone class and rename to EventGenerator

Added:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/EventGenerator.java
Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/ChangeProcessor.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/ChangeProcessor.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/ChangeProcessor.java?rev=1536757&r1=1536756&r2=1536757&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/ChangeProcessor.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/ChangeProcessor.java Tue Oct 29 15:31:14 2013
@@ -20,45 +20,20 @@ package org.apache.jackrabbit.oak.plugin
 
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkState;
-import static com.google.common.collect.Iterators.concat;
-import static com.google.common.collect.Lists.newArrayList;
-import static java.util.Collections.emptyMap;
-import static javax.jcr.observation.Event.NODE_ADDED;
-import static javax.jcr.observation.Event.NODE_MOVED;
-import static javax.jcr.observation.Event.NODE_REMOVED;
-import static javax.jcr.observation.Event.PROPERTY_ADDED;
-import static javax.jcr.observation.Event.PROPERTY_REMOVED;
-import static org.apache.jackrabbit.oak.commons.PathUtils.getName;
-import static org.apache.jackrabbit.oak.plugins.identifier.IdentifierManager.getIdentifier;
-
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
+
 import java.util.concurrent.atomic.AtomicReference;
 
-import javax.jcr.observation.Event;
 import javax.jcr.observation.EventListener;
 
-import com.google.common.collect.ForwardingIterator;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Iterators;
 import org.apache.jackrabbit.api.jmx.EventListenerMBean;
 import org.apache.jackrabbit.commons.iterator.EventIteratorAdapter;
 import org.apache.jackrabbit.commons.observation.ListenerTracker;
-import org.apache.jackrabbit.oak.api.CommitFailedException;
 import org.apache.jackrabbit.oak.api.ContentSession;
-import org.apache.jackrabbit.oak.api.PropertyState;
-import org.apache.jackrabbit.oak.api.Tree;
-import org.apache.jackrabbit.oak.commons.PathUtils;
 import org.apache.jackrabbit.oak.core.ImmutableRoot;
 import org.apache.jackrabbit.oak.core.ImmutableTree;
 import org.apache.jackrabbit.oak.namepath.NamePathMapper;
 import org.apache.jackrabbit.oak.plugins.observation.ChangeDispatcher.ChangeSet;
 import org.apache.jackrabbit.oak.plugins.observation.ChangeDispatcher.Listener;
-import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
-import org.apache.jackrabbit.oak.spi.commit.VisibleValidator;
-import org.apache.jackrabbit.oak.spi.state.MoveDetector;
-import org.apache.jackrabbit.oak.spi.state.MoveValidator;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
 import org.apache.jackrabbit.oak.spi.whiteboard.Registration;
 import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard;
@@ -75,9 +50,7 @@ import org.slf4j.LoggerFactory;
  * executed and stopped in order to not execute its run method anymore.
  */
 public class ChangeProcessor {
-
-    private static final Logger log =
-            LoggerFactory.getLogger(ChangeProcessor.class);
+    private static final Logger log = LoggerFactory.getLogger(ChangeProcessor.class);
 
     private final ContentSession contentSession;
     private final NamePathMapper namePathMapper;
@@ -167,8 +140,8 @@ public class ChangeProcessor {
                         String path = namePathMapper.getOakPath(filter.getPath());
                         ImmutableTree beforeTree = getTree(changes.getBeforeState(), path);
                         ImmutableTree afterTree = getTree(changes.getAfterState(), path);
-                        EventGeneratingValidator events = new EventGeneratingValidator(
-                                changes.getCommitInfo(), beforeTree, afterTree);
+                        EventGenerator events = new EventGenerator(changes.getCommitInfo(),
+                                beforeTree, afterTree, filter, namePathMapper);
                         if (events.hasNext()) {
                             listener.onEvent(new EventIteratorAdapter(events));
                         }
@@ -188,159 +161,4 @@ public class ChangeProcessor {
         }
     }
 
-    private class EventGeneratingValidator extends ForwardingIterator<Event> implements MoveValidator {
-        private final String userId;
-        private final String message;
-        private final long timestamp;
-        private final boolean external;
-
-        private final ImmutableTree beforeTree;
-        private final ImmutableTree afterTree;
-        private final List<Event> events = newArrayList();
-        private final List<Iterator<Event>> childEvents = newArrayList();
-
-        private Iterator<Event> eventIterator;
-
-        EventGeneratingValidator(CommitInfo info, ImmutableTree beforeTree, ImmutableTree afterTree) {
-            if (info != null) {
-                this.userId = info.getUserId();
-                this.message = info.getMessage();
-                this.timestamp = info.getDate();
-                this.external = false;
-            } else {
-                this.userId = CommitInfo.OAK_UNKNOWN;
-                this.message = null;
-                // we can't tell exactly when external changes were committed,
-                // so we just use a rough estimate like this
-                this.timestamp = System.currentTimeMillis();
-                this.external = true;
-            }
-            this.beforeTree = beforeTree;
-            this.afterTree = afterTree;
-        }
-
-        private EventGeneratingValidator(EventGeneratingValidator parent, String name) {
-            this.userId = parent.userId;
-            this.message = parent.message;
-            this.timestamp = parent.timestamp;
-            this.external = parent.external;
-            this.beforeTree = parent.beforeTree.getChild(name);
-            this.afterTree = parent.afterTree.getChild(name);
-        }
-
-        //------------------------------------------------------------< ForwardingIterator >---
-
-        @Override
-        protected Iterator<Event> delegate() {
-            try {
-                if (eventIterator == null) {
-                    SecureValidator.compare(beforeTree, afterTree,
-                            new VisibleValidator(
-                                    new MoveDetector(this, afterTree.getPath()), true, true));
-                    eventIterator = concat(events.iterator(), concat(childEvents.iterator()));
-                }
-                return eventIterator;
-            } catch (CommitFailedException e) {
-                log.error("Error while extracting observation events", e);
-                return Iterators.emptyIterator();
-            }
-        }
-
-        //------------------------------------------------------------< Validator >---
-
-        @Override
-        public void enter(NodeState before, NodeState after) throws CommitFailedException {
-        }
-
-        @Override
-        public void leave(NodeState before, NodeState after) throws CommitFailedException {
-        }
-
-        @Override
-        public void propertyAdded(PropertyState after) {
-            if (filterRef.get().include(PROPERTY_ADDED, afterTree)) {
-                events.add(createEvent(PROPERTY_ADDED, afterTree, after));
-            }
-        }
-
-        @Override
-        public void propertyChanged(PropertyState before, PropertyState after) {
-            if (filterRef.get().include(Event.PROPERTY_CHANGED, afterTree)) {
-                events.add(createEvent(Event.PROPERTY_CHANGED, afterTree, after));
-            }
-        }
-
-        @Override
-        public void propertyDeleted(PropertyState before) {
-            if (filterRef.get().include(PROPERTY_REMOVED, afterTree)) {
-                events.add(createEvent(PROPERTY_REMOVED, beforeTree, before));
-            }
-        }
-
-        @Override
-        public MoveValidator childNodeAdded(String name, NodeState after) {
-            EventFilter eventFilter = filterRef.get();
-            if (eventFilter.include(NODE_ADDED, afterTree)) {
-                events.add(createEvent(NODE_ADDED, afterTree.getChild(name)));
-            }
-            if (eventFilter.includeChildren(afterTree.getPath())) {
-                childEvents.add(new EventGeneratingValidator(this, name));
-            }
-            return null;
-        }
-
-        @Override
-        public MoveValidator childNodeDeleted(String name, NodeState before) {
-            EventFilter eventFilter = filterRef.get();
-            if (eventFilter.include(NODE_REMOVED, beforeTree)) {
-                events.add(createEvent(NODE_REMOVED, beforeTree.getChild(name)));
-            }
-            if (eventFilter.includeChildren(beforeTree.getPath())) {
-                childEvents.add(new EventGeneratingValidator(this, name));
-            }
-            return null;
-        }
-
-        @Override
-        public MoveValidator childNodeChanged(String name, NodeState before, NodeState after) {
-            if (filterRef.get().includeChildren(afterTree.getPath())) {
-                childEvents.add(new EventGeneratingValidator(this, name));
-            }
-            return null;
-        }
-
-        @Override
-        public void move(String sourcePath, String destPath, NodeState moved)
-                throws CommitFailedException {
-            if (filterRef.get().include(NODE_MOVED, afterTree)) {
-                events.add(createEvent(NODE_MOVED, afterTree.getChild(getName(destPath)),
-                        ImmutableMap.of(
-                            "srcAbsPath", namePathMapper.getJcrPath(sourcePath),
-                            "destAbsPath", namePathMapper.getJcrPath(destPath))));
-            }
-        }
-
-        //------------------------------------------------------------< internal >---
-
-        private Event createEvent(int eventType, Tree tree) {
-            return createEvent(eventType, tree.getPath(), getIdentifier(tree), emptyMap());
-        }
-
-        private Event createEvent(int eventType, Tree tree, Map<?, ?> info) {
-            return createEvent(eventType, tree.getPath(), getIdentifier(tree), info);
-        }
-
-        private Event createEvent(int eventType, Tree parent, PropertyState property) {
-            String path = PathUtils.concat(parent.getPath(), property.getName());
-            return createEvent(eventType, path, getIdentifier(parent), emptyMap());
-        }
-
-        private Event createEvent(int eventType, String path, String id, Map<?, ?> info) {
-            return new EventImpl(
-                    eventType, namePathMapper.getJcrPath(path), userId, id,
-                    info, timestamp, message, external);
-        }
-
-    }
-
 }

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/EventGenerator.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/EventGenerator.java?rev=1536757&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/EventGenerator.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/EventGenerator.java Tue Oct 29 15:31:14 2013
@@ -0,0 +1,219 @@
+/*
+ * 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.plugins.observation;
+
+import static com.google.common.collect.Iterators.concat;
+import static com.google.common.collect.Lists.newArrayList;
+import static java.util.Collections.emptyMap;
+import static javax.jcr.observation.Event.NODE_ADDED;
+import static javax.jcr.observation.Event.NODE_MOVED;
+import static javax.jcr.observation.Event.NODE_REMOVED;
+import static javax.jcr.observation.Event.PROPERTY_ADDED;
+import static javax.jcr.observation.Event.PROPERTY_REMOVED;
+import static org.apache.jackrabbit.oak.commons.PathUtils.getName;
+import static org.apache.jackrabbit.oak.plugins.identifier.IdentifierManager.getIdentifier;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import javax.jcr.observation.Event;
+
+import com.google.common.collect.ForwardingIterator;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterators;
+import org.apache.jackrabbit.oak.api.CommitFailedException;
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.core.ImmutableTree;
+import org.apache.jackrabbit.oak.namepath.NamePathMapper;
+import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
+import org.apache.jackrabbit.oak.spi.commit.VisibleValidator;
+import org.apache.jackrabbit.oak.spi.state.MoveDetector;
+import org.apache.jackrabbit.oak.spi.state.MoveValidator;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * TODO document
+ */
+class EventGenerator extends ForwardingIterator<Event> implements MoveValidator {
+    private static final Logger log = LoggerFactory.getLogger(EventGenerator.class);
+
+    private final String userId;
+    private final String message;
+    private final long timestamp;
+    private final boolean external;
+
+    private final ImmutableTree beforeTree;
+    private final ImmutableTree afterTree;
+    private final EventFilter filter;
+    private final NamePathMapper namePathMapper;
+
+    private final List<Event> events = newArrayList();
+    private final List<Iterator<Event>> childEvents = newArrayList();
+
+    private Iterator<Event> eventIterator;
+
+    EventGenerator(CommitInfo info, ImmutableTree beforeTree, ImmutableTree afterTree,
+            EventFilter filter, NamePathMapper namePathMapper) {
+        if (info != null) {
+            this.userId = info.getUserId();
+            this.message = info.getMessage();
+            this.timestamp = info.getDate();
+            this.external = false;
+        } else {
+            this.userId = CommitInfo.OAK_UNKNOWN;
+            this.message = null;
+            // we can't tell exactly when external changes were committed,
+            // so we just use a rough estimate like this
+            this.timestamp = System.currentTimeMillis();
+            this.external = true;
+        }
+        this.beforeTree = beforeTree;
+        this.afterTree = afterTree;
+        this.filter = filter;
+        this.namePathMapper = namePathMapper;
+    }
+
+    EventGenerator(EventGenerator parent, String name) {
+        this.userId = parent.userId;
+        this.message = parent.message;
+        this.timestamp = parent.timestamp;
+        this.external = parent.external;
+        this.beforeTree = parent.beforeTree.getChild(name);
+        this.afterTree = parent.afterTree.getChild(name);
+        this.filter = parent.filter;
+        this.namePathMapper = parent.namePathMapper;
+    }
+
+    //------------------------------------------------------------< ForwardingIterator >---
+
+    @Override
+    protected Iterator<Event> delegate() {
+        try {
+            if (eventIterator == null) {
+                SecureValidator.compare(beforeTree, afterTree,
+                        new VisibleValidator(
+                                new MoveDetector(this, afterTree.getPath()), true, true));
+                eventIterator = concat(events.iterator(), concat(childEvents.iterator()));
+            }
+            return eventIterator;
+        } catch (CommitFailedException e) {
+            log.error("Error while extracting observation events", e);
+            return Iterators.emptyIterator();
+        }
+    }
+
+    //------------------------------------------------------------< Validator >---
+
+    @Override
+    public void enter(NodeState before, NodeState after) throws CommitFailedException {
+    }
+
+    @Override
+    public void leave(NodeState before, NodeState after) throws CommitFailedException {
+    }
+
+    @Override
+    public void propertyAdded(PropertyState after) {
+        if (filter.include(PROPERTY_ADDED, afterTree)) {
+            events.add(createEvent(PROPERTY_ADDED, afterTree, after));
+        }
+    }
+
+    @Override
+    public void propertyChanged(PropertyState before, PropertyState after) {
+        if (filter.include(Event.PROPERTY_CHANGED, afterTree)) {
+            events.add(createEvent(Event.PROPERTY_CHANGED, afterTree, after));
+        }
+    }
+
+    @Override
+    public void propertyDeleted(PropertyState before) {
+        if (filter.include(PROPERTY_REMOVED, afterTree)) {
+            events.add(createEvent(PROPERTY_REMOVED, beforeTree, before));
+        }
+    }
+
+    @Override
+    public MoveValidator childNodeAdded(String name, NodeState after) {
+        if (filter.include(NODE_ADDED, afterTree)) {
+            events.add(createEvent(NODE_ADDED, afterTree.getChild(name)));
+        }
+        if (filter.includeChildren(afterTree.getPath())) {
+            childEvents.add(new EventGenerator(this, name));
+        }
+        return null;
+    }
+
+    @Override
+    public MoveValidator childNodeDeleted(String name, NodeState before) {
+        if (filter.include(NODE_REMOVED, beforeTree)) {
+            events.add(createEvent(NODE_REMOVED, beforeTree.getChild(name)));
+        }
+        if (filter.includeChildren(beforeTree.getPath())) {
+            childEvents.add(new EventGenerator(this, name));
+        }
+        return null;
+    }
+
+    @Override
+    public MoveValidator childNodeChanged(String name, NodeState before, NodeState after) {
+        if (filter.includeChildren(afterTree.getPath())) {
+            childEvents.add(new EventGenerator(this, name));
+        }
+        return null;
+    }
+
+    @Override
+    public void move(String sourcePath, String destPath, NodeState moved)
+            throws CommitFailedException {
+        if (filter.include(NODE_MOVED, afterTree)) {
+            events.add(createEvent(NODE_MOVED, afterTree.getChild(getName(destPath)),
+                    ImmutableMap.of(
+                            "srcAbsPath", namePathMapper.getJcrPath(sourcePath),
+                            "destAbsPath", namePathMapper.getJcrPath(destPath))));
+        }
+    }
+
+    //------------------------------------------------------------< internal >---
+
+    private Event createEvent(int eventType, Tree tree) {
+        return createEvent(eventType, tree.getPath(), getIdentifier(tree), emptyMap());
+    }
+
+    private Event createEvent(int eventType, Tree tree, Map<?, ?> info) {
+        return createEvent(eventType, tree.getPath(), getIdentifier(tree), info);
+    }
+
+    private Event createEvent(int eventType, Tree parent, PropertyState property) {
+        String path = PathUtils.concat(parent.getPath(), property.getName());
+        return createEvent(eventType, path, getIdentifier(parent), emptyMap());
+    }
+
+    private Event createEvent(int eventType, String path, String id, Map<?, ?> info) {
+        return new EventImpl(
+                eventType, namePathMapper.getJcrPath(path), userId, id,
+                info, timestamp, message, external);
+    }
+
+}