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);
+ }
+
+}