You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by re...@apache.org on 2011/12/09 16:16:45 UTC
svn commit: r1212472 - in /jackrabbit/trunk:
jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/
jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/api/observation/
jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr...
Author: reschke
Date: Fri Dec 9 15:16:44 2011
New Revision: 1212472
URL: http://svn.apache.org/viewvc?rev=1212472&view=rev
Log:
JCR-3172: implement PERSIST events for the EventJournal
Add PERSIST events to EventJournal, add a minimal test case
Modified:
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventConsumer.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventFilter.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventImpl.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventJournalImpl.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventState.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/FilteredEventIterator.java
jackrabbit/trunk/jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/api/observation/EventJournalTest.java
jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/EventImpl.java
jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/EventFilterImpl.java
jackrabbit/trunk/jackrabbit-spi2jcr/src/main/java/org/apache/jackrabbit/spi2jcr/EventFactory.java
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventConsumer.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventConsumer.java?rev=1212472&r1=1212471&r2=1212472&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventConsumer.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventConsumer.java Fri Dec 9 15:16:44 2011
@@ -242,7 +242,7 @@ class EventConsumer {
// check if filtered iterator has at least one event
EventIterator it = new FilteredEventIterator(
session, events.iterator(), events.getTimestamp(),
- events.getUserData(), filter, denied);
+ events.getUserData(), filter, denied, false);
if (it.hasNext()) {
long time = System.currentTimeMillis();
listener.onEvent(it);
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventFilter.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventFilter.java?rev=1212472&r1=1212471&r2=1212472&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventFilter.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventFilter.java Fri Dec 9 15:16:44 2011
@@ -25,6 +25,7 @@ import org.apache.jackrabbit.spi.Path;
import javax.jcr.RepositoryException;
import javax.jcr.nodetype.NodeType;
+import javax.jcr.observation.Event;
/**
* The <code>EventFilter</code> class implements the filter logic based
@@ -132,6 +133,11 @@ public class EventFilter {
return true;
}
+ // UUIDs, types, and paths do not need to match for persist
+ if (eventState.getType() == Event.PERSIST) {
+ return false;
+ }
+
// check UUIDs
NodeId parentId = eventState.getParentId();
if (ids != null) {
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventImpl.java?rev=1212472&r1=1212471&r2=1212472&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventImpl.java Fri Dec 9 15:16:44 2011
@@ -104,7 +104,8 @@ public final class EventImpl implements
* {@inheritDoc}
*/
public String getPath() throws RepositoryException {
- return session.getJCRPath(getQPath());
+ Path p = getQPath();
+ return p != null ? session.getJCRPath(getQPath()) : null;
}
/**
@@ -132,12 +133,20 @@ public final class EventImpl implements
* {@inheritDoc}
*/
public String getIdentifier() throws RepositoryException {
- NodeId id = eventState.getChildId();
- if (id == null) {
- // property event
- id = eventState.getParentId();
+ if (eventState.getType() == Event.PERSIST) {
+ return null;
+ }
+ else {
+ NodeId id = eventState.getChildId();
+
+ if (id != null) {
+ return id.toString();
+ }
+ else {
+ // property event
+ return eventState.getParentId().toString();
+ }
}
- return id.toString();
}
/**
@@ -161,18 +170,25 @@ public final class EventImpl implements
/**
* Returns the <code>Path</code> of this event.
*
- * @return path
+ * @return path or <code>null</code> when no path is associated with the event
* @throws RepositoryException if the path can't be constructed
*/
public Path getQPath() throws RepositoryException {
try {
Path parent = eventState.getParentPath();
Path child = eventState.getChildRelPath();
- int index = child.getIndex();
- if (index > 0) {
- return PathFactoryImpl.getInstance().create(parent, child.getName(), index, false);
- } else {
- return PathFactoryImpl.getInstance().create(parent, child.getName(), false);
+
+ if (parent == null || child == null) {
+ // an event without associated path information
+ return null;
+ }
+ else {
+ int index = child.getIndex();
+ if (index > 0) {
+ return PathFactoryImpl.getInstance().create(parent, child.getName(), index, false);
+ } else {
+ return PathFactoryImpl.getInstance().create(parent, child.getName(), false);
+ }
}
} catch (MalformedPathException e) {
String msg = "internal error: malformed path for event";
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventJournalImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventJournalImpl.java?rev=1212472&r1=1212471&r2=1212472&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventJournalImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventJournalImpl.java Fri Dec 9 15:16:44 2011
@@ -415,7 +415,7 @@ public class EventJournalImpl implements
List<EventState> eventStates, long timestamp, String userData) {
this.events = new FilteredEventIterator(
session, eventStates.iterator(),
- timestamp, userData, filter, Collections.emptySet());
+ timestamp, userData, filter, Collections.emptySet(), true);
this.timestamp = timestamp;
}
}
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventState.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventState.java?rev=1212472&r1=1212471&r2=1212472&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventState.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventState.java Fri Dec 9 15:16:44 2011
@@ -177,7 +177,7 @@ public class EventState {
throw new IllegalArgumentException("childId only allowed for Node events.");
}
} else {
- if (childId == null) {
+ if (childId == null && type != Event.PERSIST) {
throw new IllegalArgumentException("childId must not be null for Node events.");
}
}
@@ -580,6 +580,20 @@ public class EventState {
}
/**
+ * Creates a new {@link javax.jcr.observation.Event} of type
+ * {@link javax.jcr.observation.Event#PERSIST}.
+ *
+ * @param session the session that changed the property.
+ * @param external flag indicating whether this is an external event
+ * @return an <code>EventState</code> instance.
+ */
+ public static EventState persist(Session session, boolean external) {
+
+ return new EventState(Event.PERSIST, null, null, null, null,
+ null, null, session, external);
+ }
+
+ /**
* {@inheritDoc}
*/
public int getType() {
@@ -695,10 +709,12 @@ public class EventState {
/**
* Returns the id of the associated item of this <code>EventState</code>.
*
- * @return the <code>ItemId</code>.
+ * @return the <code>ItemId</code> or <code>null</code> for {@link Event#PERSIST} events
*/
ItemId getTargetId() {
- if (childId == null) {
+ if (type == Event.PERSIST) {
+ return null;
+ } else if (childId == null) {
// property event
return new PropertyId(parentId, childRelPath.getName());
} else {
@@ -782,8 +798,8 @@ public class EventState {
if (h == 0) {
h = 37;
h = 37 * h + type;
- h = 37 * h + parentId.hashCode();
- h = 37 * h + childRelPath.hashCode();
+ h = 37 * h + (parentId != null ? parentId.hashCode() : 0);
+ h = 37 * h + (childRelPath != null ? childRelPath.hashCode() : 0);
h = 37 * h + session.hashCode();
h = 37 * h + info.hashCode();
hashCode = h;
@@ -833,6 +849,8 @@ public class EventState {
return "PropertyChanged";
} else if (eventType == Event.PROPERTY_REMOVED) {
return "PropertyRemoved";
+ } else if (eventType == Event.PERSIST) {
+ return "Persist";
} else {
return "UnknownEventType";
}
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/FilteredEventIterator.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/FilteredEventIterator.java?rev=1212472&r1=1212471&r2=1212472&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/FilteredEventIterator.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/FilteredEventIterator.java Fri Dec 9 15:16:44 2011
@@ -17,9 +17,11 @@
package org.apache.jackrabbit.core.observation;
import java.util.Iterator;
+import java.util.NoSuchElementException;
import java.util.Set;
import javax.jcr.RepositoryException;
+import javax.jcr.observation.Event;
import org.apache.jackrabbit.commons.iterator.EventIteratorAdapter;
import org.apache.jackrabbit.commons.iterator.FilteredRangeIterator;
@@ -64,12 +66,13 @@ class FilteredEventIterator extends Even
* event listener.
* @param denied <code>Set</code> of <code>ItemId</code>s of denied <code>ItemState</code>s
* rejected by the <code>AccessManager</code>
+ * @param includePersistEvent whether or not to include the {@link Event#PERSIST} event
*/
public FilteredEventIterator(
- SessionImpl session, Iterator<?> eventStates,
+ SessionImpl session, Iterator<EventState> eventStates,
long timestamp, String userData,
- final EventFilter filter, final Set<?> denied) {
- super(new FilteredRangeIterator(eventStates, new Predicate() {
+ final EventFilter filter, final Set<?> denied, boolean includePersistEvent) {
+ super(new FilteredRangeIterator(wrapAndAddPersist(eventStates, includePersistEvent), new Predicate() {
public boolean evaluate(Object object) {
try {
EventState state = (EventState) object;
@@ -92,4 +95,58 @@ class FilteredEventIterator extends Even
session, (EventState) super.next(), timestamp, userData);
}
+ /**
+ * Optionally wrap the iterator into one that adds PERSIST events
+ */
+ private static Iterator<EventState> wrapAndAddPersist(final Iterator<EventState> states,
+ boolean includePersistEvents) {
+ if (includePersistEvents) {
+ return new PersistEventAddingWrapper(states);
+ }
+ else {
+ return states;
+ }
+ }
+
+ /**
+ * A wrapper around {@link Iterator} that adds a "PERSIST" event at the end.
+ */
+ private static class PersistEventAddingWrapper implements Iterator<EventState> {
+
+ private Iterator<EventState> states;
+ private boolean persistSent = false;
+ private EventState previous = null;
+
+ public PersistEventAddingWrapper(Iterator<EventState> states) {
+ this.states = states;
+ }
+
+ public boolean hasNext() {
+ if (states.hasNext()) {
+ return true;
+ } else {
+ return !persistSent;
+ }
+ }
+
+ public EventState next() {
+ if (states.hasNext()) {
+ previous = states.next();
+ return previous;
+ }
+ else if (persistSent || previous == null) {
+ // we are at the end; either because we already sent
+ // PERSIST, or because the iterator was empty anyway
+ throw new NoSuchElementException();
+ }
+ else {
+ persistSent = true;
+ return EventState.persist(previous.getSession(), previous.isExternal());
+ }
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ }
}
Modified: jackrabbit/trunk/jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/api/observation/EventJournalTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/api/observation/EventJournalTest.java?rev=1212472&r1=1212471&r2=1212472&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/api/observation/EventJournalTest.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/api/observation/EventJournalTest.java Fri Dec 9 15:16:44 2011
@@ -185,7 +185,52 @@ public class EventJournalTest extends Ab
checkJournal(new String[]{n2.getPath()}, new String[]{n1.getPath()});
}
-
+
+ public void testPersist() throws RepositoryException, NotExecutableException {
+ Node n1 = testRootNode.addNode(nodeName1);
+
+ journal = getEventJournal(Event.PERSIST, testRoot, true, null, null);
+ skipToNow();
+
+ superuser.save();
+
+ boolean hasPersistEvents = journal.hasNext();
+ if (! hasPersistEvents) {
+ throw new NotExecutableException("repository does not appear to provide PERSIST events");
+ }
+
+ journal = getEventJournal(ALL_TYPES | Event.PERSIST, testRoot, true, null, null);
+ skipToNow();
+
+ // add another child node
+ Node n3 = testRootNode.addNode(nodeName2);
+ String target = n1.getPath();
+ n1.remove();
+ superuser.save();
+
+ // move it
+ superuser.getWorkspace().move(n3.getPath(), target);
+
+ // remove it again
+ n3 = superuser.getNode(target);
+ n3.remove();
+ superuser.save();
+
+ int persistCount = 0;
+ Event e = null;
+ while (journal.hasNext()) {
+ e = journal.nextEvent();
+ if (e.getType() == Event.PERSIST) {
+ persistCount += 1;
+ }
+ }
+
+ assertEquals(3, persistCount);
+
+ // last event should be persist
+ assertEquals(Event.PERSIST, e.getType());
+ }
+
//-------------------------------< internal >-------------------------------
private void skipToNow() {
Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/EventImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/EventImpl.java?rev=1212472&r1=1212471&r2=1212472&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/EventImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/EventImpl.java Fri Dec 9 15:16:44 2011
@@ -91,7 +91,7 @@ final class EventImpl implements Event {
* {@inheritDoc}
*/
public String getPath() throws RepositoryException {
- return resolver.getJCRPath(event.getPath());
+ return event.getPath() != null ? resolver.getJCRPath(event.getPath()) : null;
}
/**
Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/EventFilterImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/EventFilterImpl.java?rev=1212472&r1=1212471&r2=1212472&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/EventFilterImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/EventFilterImpl.java Fri Dec 9 15:16:44 2011
@@ -88,6 +88,11 @@ public class EventFilterImpl implements
return false;
}
+ // UUIDs, types, and paths do not need to match for persist
+ if (event.getType() == Event.PERSIST) {
+ return true;
+ }
+
// check UUIDs
NodeId parentId = event.getParentId();
if (uuids != null) {
Modified: jackrabbit/trunk/jackrabbit-spi2jcr/src/main/java/org/apache/jackrabbit/spi2jcr/EventFactory.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi2jcr/src/main/java/org/apache/jackrabbit/spi2jcr/EventFactory.java?rev=1212472&r1=1212471&r2=1212472&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi2jcr/src/main/java/org/apache/jackrabbit/spi2jcr/EventFactory.java (original)
+++ jackrabbit/trunk/jackrabbit-spi2jcr/src/main/java/org/apache/jackrabbit/spi2jcr/EventFactory.java Fri Dec 9 15:16:44 2011
@@ -66,11 +66,11 @@ class EventFactory {
public Event fromJCREvent(javax.jcr.observation.Event e)
throws RepositoryException {
- Path p = resolver.getQPath(e.getPath());
- Path parent = p.getAncestor(1);
+ Path p = e.getPath() != null ? resolver.getQPath(e.getPath()) : null;
+ Path parent = p != null ? p.getAncestor(1) : null;
int type = e.getType();
- NodeId parentId = idFactory.createNodeId((String) null, parent);
+ NodeId parentId = parent != null ?idFactory.createNodeId((String) null, parent) : null;
String identifier = e.getIdentifier();
ItemId itemId;
Node node = null;