Author: jukka
Date: Tue Jan 28 21:14:06 2014
New Revision: 1562233
URL: http://svn.apache.org/r1562233
Log:
OAK-1133: Observation listener PLUS
Extract JCR-specific bits away from EventGenerator
Added:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/EventQueue.java
(with props)
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/QueueingHandler.java
(with props)
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/ChangeProcessor.java
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
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/ChangeProcessor.java?rev=1562233&r1=1562232&r2=1562233&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 Jan 28 21:14:06 2014
@@ -157,7 +157,7 @@ public class ChangeProcessor implements
String basePath = provider.getPath();
EventFilter userFilter = provider.getFilter(previousRoot,
root);
EventFilter acFilter = new ACFilter(previousRoot, root,
permissionProvider, basePath);
- EventGenerator events = new EventGenerator(
+ EventQueue events = new EventQueue(
namePathMapper, info, previousRoot, root, basePath,
Filters.all(userFilter, acFilter));
if (events.hasNext() && runningMonitor.enterIf(running)) {
Modified:
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=1562233&r1=1562232&r2=1562233&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/EventGenerator.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/EventGenerator.java
Tue Jan 28 21:14:06 2014
@@ -18,15 +18,8 @@
*/
package org.apache.jackrabbit.oak.plugins.observation;
-import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Lists.newLinkedList;
-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_CHANGED;
-import static javax.jcr.observation.Event.PROPERTY_REMOVED;
import static org.apache.jackrabbit.oak.api.Type.NAMES;
import static org.apache.jackrabbit.oak.api.Type.STRING;
import static org.apache.jackrabbit.oak.core.AbstractTree.OAK_CHILD_ORDER;
@@ -35,63 +28,47 @@ import static org.apache.jackrabbit.oak.
import java.util.LinkedList;
import java.util.List;
-import java.util.Map;
-import java.util.NoSuchElementException;
import javax.annotation.Nonnull;
-import javax.jcr.observation.Event;
-import javax.jcr.observation.EventIterator;
import org.apache.jackrabbit.oak.api.PropertyState;
-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.plugins.observation.filter.EventFilter;
-import org.apache.jackrabbit.oak.plugins.observation.filter.Filters;
-import org.apache.jackrabbit.oak.plugins.observation.filter.VisibleFilter;
import org.apache.jackrabbit.oak.plugins.observation.handler.ChangeHandler;
-import org.apache.jackrabbit.oak.plugins.observation.handler.FilteredHandler;
-import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
import org.apache.jackrabbit.oak.spi.state.NodeState;
import org.apache.jackrabbit.oak.spi.state.NodeStateDiff;
-import com.google.common.collect.ImmutableMap;
-
/**
* Generator of a traversable view of events.
*/
-public class EventGenerator implements EventIterator {
-
- private final EventContext context;
-
- private final LinkedList<Event> events = newLinkedList();
- private final LinkedList<Runnable> generators = newLinkedList();
+public class EventGenerator {
- private long position = 0;
+ private final LinkedList<Runnable> continuations = newLinkedList();
/**
* Create a new instance of a {@code EventGenerator} reporting events to
the
* passed {@code listener} after filtering with the passed {@code filter}.
- *
- * @param filter filter for filtering changes
*/
public EventGenerator(
- @Nonnull NamePathMapper namePathMapper, CommitInfo info,
@Nonnull NodeState before, @Nonnull NodeState after,
- @Nonnull String basePath, @Nonnull EventFilter filter) {
- this.context = new EventContext(namePathMapper, info);
+ @Nonnull ChangeHandler handler) {
+ continuations.add(new DiffContinuation(handler, before, after));
+ }
- filter = Filters.all(new VisibleFilter(), checkNotNull(filter));
+ public boolean isComplete() {
+ return continuations.isEmpty();
+ }
- new EventDiff(before, after, basePath, filter).run();
+ public void generate() {
+ if (!continuations.isEmpty()) {
+ continuations.removeFirst().run();
+ }
}
- private class EventDiff implements NodeStateDiff, Runnable {
+ private class DiffContinuation implements NodeStateDiff, Runnable {
/**
* The diff handler of the parent node, or {@code null} for the root.
*/
- private final EventDiff parent;
+ private final DiffContinuation parent;
/**
* The name of this node, or the empty string for the root.
@@ -113,27 +90,16 @@ public class EventGenerator implements E
*/
private final ChangeHandler handler;
- EventDiff(NodeState before, NodeState after, String path,
- EventFilter filter) {
- String name = null;
- ChangeHandler handler = new Handler(
- new ImmutableTree(before), new ImmutableTree(after));
- for (String element : PathUtils.elements(path)) {
- name = element;
- before = before.getChildNode(name);
- after = after.getChildNode(name);
- handler = handler.getChildHandler(name, before, after);
- }
-
+ DiffContinuation(ChangeHandler handler, NodeState before, NodeState
after) {
this.parent = null;
- this.name = name;
+ this.name = null;
this.before = before;
this.after = after;
- this.handler = new FilteredHandler(filter, handler);
+ this.handler = handler;
}
- private EventDiff(
- EventDiff parent, ChangeHandler handler,
+ private DiffContinuation(
+ DiffContinuation parent, ChangeHandler handler,
String name, NodeState before, NodeState after) {
this.parent = parent;
this.name = name;
@@ -148,9 +114,11 @@ public class EventGenerator implements E
public void run() {
if (parent != null) {
if (before == MISSING_NODE) {
- parent.handleAddedNode(name, after); // postponed handling
of added nodes
+ // postponed handling of added nodes
+ parent.handleAddedNode(name, after);
} else if (after == MISSING_NODE) {
- parent.handleDeletedNode(name, before); // postponed
handling of removed nodes
+ // postponed handling of removed nodes
+ parent.handleDeletedNode(name, before);
}
}
@@ -213,7 +181,7 @@ public class EventGenerator implements E
String name, NodeState before, NodeState after) {
ChangeHandler h = handler.getChildHandler(name, before, after);
if (h != null) {
- generators.add(new EventDiff(this, h, name, before, after));
+ continuations.add(new DiffContinuation(this, h, name, before,
after));
return true;
} else {
return false;
@@ -260,136 +228,4 @@ public class EventGenerator implements E
}
- private class Handler implements ChangeHandler {
-
- private final ImmutableTree before;
- private final ImmutableTree after;
-
- Handler(ImmutableTree before, ImmutableTree after) {
- this.before = before;
- this.after = after;
- }
-
- @Override
- public ChangeHandler getChildHandler(
- String name, NodeState before, NodeState after) {
- return new Handler(
- new ImmutableTree(this.before, name, before),
- new ImmutableTree(this.after, name, after));
- }
-
- @Override
- public void propertyAdded(PropertyState after) {
- events.add(new EventImpl(
- context, PROPERTY_ADDED, this.after, after.getName()));
- }
-
- @Override
- public void propertyChanged(PropertyState before, PropertyState after)
{
- events.add(new EventImpl(
- context, PROPERTY_CHANGED, this.after, after.getName()));
- }
-
- @Override
- public void propertyDeleted(PropertyState before) {
- events.add(new EventImpl(
- context, PROPERTY_REMOVED, this.before, before.getName()));
- }
-
- @Override
- public void nodeAdded(String name, NodeState after) {
- ImmutableTree tree = new ImmutableTree(this.after, name, after);
- events.add(new EventImpl(context, NODE_ADDED, tree));
- }
-
- @Override
- public void nodeDeleted(String name, NodeState before) {
- ImmutableTree tree = new ImmutableTree(this.before, name, before);
- events.add(new EventImpl(context, NODE_REMOVED, tree));
- }
-
- @Override
- public void nodeMoved(String sourcePath, String name, NodeState moved)
{
- ImmutableTree tree = new ImmutableTree(this.after, name, moved);
- Map<String, String> info = ImmutableMap.of(
- "srcAbsPath", context.getJcrPath(sourcePath),
- "destAbsPath", context.getJcrPath(tree.getPath()));
- events.add(new EventImpl(context, NODE_MOVED, tree, info));
- }
-
- @Override
- public void nodeReordered(
- String destName, String name, NodeState reordered) {
- Map<String, String> info = ImmutableMap.of(
- "srcChildRelPath", context.getJcrName(name),
- "destChildRelPath", context.getJcrName(destName));
- ImmutableTree tree = new ImmutableTree(after, name, reordered);
- events.add(new EventImpl(context, NODE_MOVED, tree, info));
- }
-
- }
-
- //-----------------------------------------------------< EventIterator >--
-
- @Override
- public long getSize() {
- if (generators.isEmpty()) {
- return position + events.size();
- } else {
- return -1;
- }
- }
-
- @Override
- public long getPosition() {
- return position;
- }
-
- @Override
- public boolean hasNext() {
- while (events.isEmpty()) {
- if (generators.isEmpty()) {
- return false;
- } else {
- generators.removeFirst().run();
- }
- }
- return true;
- }
-
- @Override
- public void skip(long skipNum) {
- while (skipNum > events.size()) {
- position += events.size();
- skipNum -= events.size();
- events.clear();
- // the remove below throws NoSuchElementException if there
- // are no more generators, which is correct as then we can't
- // skip over enough events
- generators.removeFirst().run();
- }
- position += skipNum;
- events.subList(0, (int) skipNum).clear();
- }
-
- @Override
- public Event nextEvent() {
- if (hasNext()) {
- position++;
- return events.removeFirst();
- } else {
- throw new NoSuchElementException();
- }
- }
-
- @Override
- public Event next() {
- return nextEvent();
- }
-
- @Override
- public void remove() {
- throw new UnsupportedOperationException();
- }
-
}
Added:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/EventQueue.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/EventQueue.java?rev=1562233&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/EventQueue.java
(added)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/EventQueue.java
Tue Jan 28 21:14:06 2014
@@ -0,0 +1,146 @@
+/*
+ * 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.Lists.newLinkedList;
+
+import java.util.LinkedList;
+import java.util.NoSuchElementException;
+
+import javax.annotation.Nonnull;
+import javax.jcr.observation.Event;
+import javax.jcr.observation.EventIterator;
+
+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.plugins.observation.filter.EventFilter;
+import org.apache.jackrabbit.oak.plugins.observation.filter.Filters;
+import org.apache.jackrabbit.oak.plugins.observation.filter.VisibleFilter;
+import org.apache.jackrabbit.oak.plugins.observation.handler.ChangeHandler;
+import org.apache.jackrabbit.oak.plugins.observation.handler.FilteredHandler;
+import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+
+/**
+ * Queue of JCR Events generated from a given content change
+ */
+class EventQueue implements EventIterator {
+
+ private final EventGenerator generator;
+
+ private final LinkedList<Event> queue = newLinkedList();
+
+ private long position = 0;
+
+ public EventQueue(
+ @Nonnull NamePathMapper namePathMapper, CommitInfo info,
+ @Nonnull NodeState before, @Nonnull NodeState after,
+ @Nonnull String basePath, @Nonnull EventFilter filter) {
+ ChangeHandler handler = new QueueingHandler(
+ queue, new EventContext(namePathMapper, info),
+ new ImmutableTree(before), new ImmutableTree(after));
+ for (String name : PathUtils.elements(basePath)) {
+ before = before.getChildNode(name);
+ after = after.getChildNode(name);
+ handler = handler.getChildHandler(name, before, after);
+ }
+ handler = new FilteredHandler(
+ Filters.all(new VisibleFilter(), filter),
+ handler);
+
+ this.generator = new EventGenerator(before, after, handler);
+ }
+
+ //-----------------------------------------------------< EventIterator >--
+
+ @Override
+ public long getSize() {
+ if (generator.isComplete()) {
+ // no more new events will be generated, so count just those
+ // that have already been iterated and those left in the queue
+ return position + queue.size();
+ } else {
+ // the generator is not yet done, so there's no way
+ // to know how many events may still be generated
+ return -1;
+ }
+ }
+
+ @Override
+ public long getPosition() {
+ return position;
+ }
+
+ @Override
+ public boolean hasNext() {
+ while (queue.isEmpty()) {
+ if (generator.isComplete()) {
+ return false;
+ } else {
+ generator.generate();
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public void skip(long skipNum) {
+ // generate events until all events to skip have been queued
+ while (skipNum > queue.size()) {
+ // drop all currently queued events as we're skipping them all
+ position += queue.size();
+ skipNum -= queue.size();
+ queue.clear();
+
+ // generate more events if possible, otherwise fail
+ if (!generator.isComplete()) {
+ generator.generate();
+ } else {
+ throw new NoSuchElementException("Not enough events to skip");
+ }
+ }
+
+ // the remaining events to skip are guaranteed to all be in the
+ // queue, so we can just drop those events and advance the position
+ queue.subList(0, (int) skipNum).clear();
+ position += skipNum;
+ }
+
+ @Override
+ public Event nextEvent() {
+ if (hasNext()) {
+ position++;
+ return queue.removeFirst();
+ } else {
+ throw new NoSuchElementException();
+ }
+ }
+
+ @Override
+ public Event next() {
+ return nextEvent();
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+
+}
Propchange:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/EventQueue.java
------------------------------------------------------------------------------
svn:eol-style = native
Added:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/QueueingHandler.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/QueueingHandler.java?rev=1562233&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/QueueingHandler.java
(added)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/QueueingHandler.java
Tue Jan 28 21:14:06 2014
@@ -0,0 +1,121 @@
+/*
+ * 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 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_CHANGED;
+import static javax.jcr.observation.Event.PROPERTY_REMOVED;
+
+import java.util.LinkedList;
+import java.util.Map;
+
+import javax.jcr.observation.Event;
+
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.core.ImmutableTree;
+import org.apache.jackrabbit.oak.plugins.observation.handler.ChangeHandler;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * Change handler that generates JCR Event instances and places them
+ * in an event queue.
+ */
+class QueueingHandler implements ChangeHandler {
+
+ private final LinkedList<Event> queue;
+
+ private final EventContext context;
+
+ private final ImmutableTree before;
+
+ private final ImmutableTree after;
+
+ QueueingHandler(
+ LinkedList<Event> queue, EventContext context,
+ ImmutableTree before, ImmutableTree after) {
+ this.queue = queue;
+ this.context = context;
+ this.before = before;
+ this.after = after;
+ }
+
+ @Override
+ public ChangeHandler getChildHandler(
+ String name, NodeState before, NodeState after) {
+ return new QueueingHandler(
+ queue, context,
+ new ImmutableTree(this.before, name, before),
+ new ImmutableTree(this.after, name, after));
+ }
+
+ @Override
+ public void propertyAdded(PropertyState after) {
+ queue.add(new EventImpl(
+ context, PROPERTY_ADDED, this.after, after.getName()));
+ }
+
+ @Override
+ public void propertyChanged(PropertyState before, PropertyState after) {
+ queue.add(new EventImpl(
+ context, PROPERTY_CHANGED, this.after, after.getName()));
+ }
+
+ @Override
+ public void propertyDeleted(PropertyState before) {
+ queue.add(new EventImpl(
+ context, PROPERTY_REMOVED, this.before, before.getName()));
+ }
+
+ @Override
+ public void nodeAdded(String name, NodeState after) {
+ ImmutableTree tree = new ImmutableTree(this.after, name, after);
+ queue.add(new EventImpl(context, NODE_ADDED, tree));
+ }
+
+ @Override
+ public void nodeDeleted(String name, NodeState before) {
+ ImmutableTree tree = new ImmutableTree(this.before, name, before);
+ queue.add(new EventImpl(context, NODE_REMOVED, tree));
+ }
+
+ @Override
+ public void nodeMoved(String sourcePath, String name, NodeState moved) {
+ ImmutableTree tree = new ImmutableTree(this.after, name, moved);
+ Map<String, String> info = ImmutableMap.of(
+ "srcAbsPath", context.getJcrPath(sourcePath),
+ "destAbsPath", context.getJcrPath(tree.getPath()));
+ queue.add(new EventImpl(context, NODE_MOVED, tree, info));
+ }
+
+ @Override
+ public void nodeReordered(
+ String destName, String name, NodeState reordered) {
+ Map<String, String> info = ImmutableMap.of(
+ "srcChildRelPath", context.getJcrName(name),
+ "destChildRelPath", context.getJcrName(destName));
+ ImmutableTree tree = new ImmutableTree(after, name, reordered);
+ queue.add(new EventImpl(context, NODE_MOVED, tree, info));
+ }
+
+}
Propchange:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/QueueingHandler.java
------------------------------------------------------------------------------
svn:eol-style = native