You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by mr...@apache.org on 2006/11/09 14:12:23 UTC
svn commit: r472888 [1/2] - in /jackrabbit/trunk/contrib/spi: client/
jcr2spi/ jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/
jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/lock/
jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observatio...
Author: mreutegg
Date: Thu Nov 9 05:12:21 2006
New Revision: 472888
URL: http://svn.apache.org/viewvc?view=rev&rev=472888
Log:
- add commons-codec dependency to client project.xml
- add concurrent dependency to jcr2spi project.xml
- remove events again from operation methods on RepositoryService.
Added:
jackrabbit/trunk/contrib/spi/spi/src/main/java/org/apache/jackrabbit/spi/EventFilter.java (with props)
jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/EventFilterImpl.java (with props)
Removed:
jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/EventFilter.java
Modified:
jackrabbit/trunk/contrib/spi/client/project.xml
jackrabbit/trunk/contrib/spi/jcr2spi/project.xml
jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceImpl.java
jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceManager.java
jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/lock/LockManagerImpl.java
jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/FilteredEventIterator.java
jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/InternalEventListener.java
jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/ObservationManagerImpl.java
jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ChangeLog.java
jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemState.java
jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/NodeState.java
jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/PathResolver.java
jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/PropertyState.java
jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/WorkspaceItemStateManager.java
jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/version/VersionManagerImpl.java
jackrabbit/trunk/contrib/spi/spi/src/main/java/org/apache/jackrabbit/spi/RepositoryService.java
jackrabbit/trunk/contrib/spi/spi/src/main/java/org/apache/jackrabbit/spi/SessionInfo.java
jackrabbit/trunk/contrib/spi/spi/src/main/java/org/apache/jackrabbit/spi/package.html
jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/IdFactoryImpl.java
jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/RepositoryServiceImpl.java
jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/URIResolverImpl.java
Modified: jackrabbit/trunk/contrib/spi/client/project.xml
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/client/project.xml?view=diff&rev=472888&r1=472887&r2=472888
==============================================================================
--- jackrabbit/trunk/contrib/spi/client/project.xml (original)
+++ jackrabbit/trunk/contrib/spi/client/project.xml Thu Nov 9 05:12:21 2006
@@ -101,6 +101,15 @@
<version>3.1</version>
</dependency>
<dependency>
+ <groupId>commons-codec</groupId>
+ <artifactId>commons-codec</artifactId>
+ <version>1.2</version>
+ <url>http://jakarta.apache.org/commons/codec/</url>
+ <properties>
+ <scope>runtime</scope>
+ </properties>
+ </dependency>
+ <dependency>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
<version>2.6.2</version>
Modified: jackrabbit/trunk/contrib/spi/jcr2spi/project.xml
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/project.xml?view=diff&rev=472888&r1=472887&r2=472888
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/project.xml (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/project.xml Thu Nov 9 05:12:21 2006
@@ -63,6 +63,12 @@
<version>3.1</version>
<url>http://jakarta.apache.org/commons/collections/</url>
</dependency>
+ <dependency>
+ <groupId>concurrent</groupId>
+ <artifactId>concurrent</artifactId>
+ <version>1.3.4</version>
+ <url>http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html</url>
+ </dependency>
<!-- test only -->
<dependency>
<groupId>junit</groupId>
Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceImpl.java?view=diff&rev=472888&r1=472887&r2=472888
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceImpl.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceImpl.java Thu Nov 9 05:12:21 2006
@@ -496,8 +496,6 @@
* @return a new <code>ObservationManager</code> instance
*/
protected ObservationManager createObservationManager(NamespaceResolver nsResolver, NodeTypeRegistry ntRegistry) {
- ObservationManagerImpl obsMgr = new ObservationManagerImpl(nsResolver, ntRegistry);
- wspManager.addEventListener(obsMgr);
- return obsMgr;
+ return new ObservationManagerImpl(wspManager, nsResolver, ntRegistry);
}
}
Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceManager.java?view=diff&rev=472888&r1=472887&r2=472888
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceManager.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceManager.java Thu Nov 9 05:12:21 2006
@@ -72,6 +72,7 @@
import org.apache.jackrabbit.spi.PropertyId;
import org.apache.jackrabbit.spi.Batch;
import org.apache.jackrabbit.spi.EventBundle;
+import org.apache.jackrabbit.spi.EventFilter;
import org.apache.jackrabbit.value.QValue;
import org.slf4j.LoggerFactory;
import org.slf4j.Logger;
@@ -102,8 +103,14 @@
import java.util.HashSet;
import java.util.Collection;
import java.util.Map;
+import java.util.Collections;
import java.io.InputStream;
+import EDU.oswego.cs.dl.util.concurrent.Channel;
+import EDU.oswego.cs.dl.util.concurrent.Sync;
+import EDU.oswego.cs.dl.util.concurrent.Latch;
+import EDU.oswego.cs.dl.util.concurrent.LinkedQueue;
+
/**
* <code>WorkspaceManager</code>...
*/
@@ -132,6 +139,13 @@
private final Object updateMonitor = new Object();
/**
+ * A producer for this channel can request an immediate poll for events
+ * by placing a Sync into the channel. The Sync is released when the event
+ * poll finished.
+ */
+ private final Channel immediateEventRequests = new LinkedQueue();
+
+ /**
* This is the event polling for external changes. If <code>null</code>
* then the underlying repository service does not support observation.
*/
@@ -141,7 +155,7 @@
* List of event listener that are set on this WorkspaceManager to get
* notifications about local and external changes.
*/
- private Set listeners = new HashSet();
+ private final Set listeners = Collections.synchronizedSet(new HashSet());
public WorkspaceManager(RepositoryService service, SessionInfo sessionInfo) throws RepositoryException {
this.service = service;
@@ -249,10 +263,35 @@
listeners.remove(listener);
}
+ /**
+ * Creates an event filter based on the parameters available in {@link
+ * javax.jcr.observation.ObservationManager#addEventListener}.
+ *
+ * @param eventTypes A combination of one or more event type constants
+ * encoded as a bitmask.
+ * @param path an absolute path.
+ * @param isDeep a <code>boolean</code>.
+ * @param uuids array of UUIDs.
+ * @param nodeTypes array of node type names.
+ * @param noLocal a <code>boolean</code>.
+ * @return the event filter instance with the given parameters.
+ * @throws UnsupportedRepositoryOperationException
+ * if this implementation does not support observation.
+ */
+ public EventFilter createEventFilter(int eventTypes,
+ Path path,
+ boolean isDeep,
+ String[] uuids,
+ QName[] nodeTypes,
+ boolean noLocal)
+ throws UnsupportedRepositoryOperationException {
+ return service.createEventFilter(eventTypes, path, isDeep, uuids, nodeTypes, noLocal);
+ }
+
//--------------------------------------------------------------------------
private ItemStateManager createItemStateManager() {
ItemStateFactory isf = new WorkspaceItemStateFactory(service, sessionInfo, this);
- WorkspaceItemStateManager ism = new WorkspaceItemStateManager(isf, service.getIdFactory());
+ WorkspaceItemStateManager ism = new WorkspaceItemStateManager(this, isf, service.getIdFactory());
addEventListener(ism);
return ism;
}
@@ -368,8 +407,16 @@
* @see UpdatableItemStateManager#execute(Operation)
*/
public void execute(Operation operation) throws RepositoryException {
+ Sync eventSignal;
synchronized (updateMonitor) {
new OperationVisitorImpl(sessionInfo).execute(operation);
+ eventSignal = getEventPollingRequest();
+ }
+ try {
+ eventSignal.acquire();
+ } catch (InterruptedException e) {
+ Thread.interrupted();
+ log.warn("Interrupted while waiting for events from RepositoryService");
}
}
@@ -380,8 +427,17 @@
* @throws RepositoryException
*/
public void execute(ChangeLog changes) throws RepositoryException {
+ Sync eventSignal;
synchronized (updateMonitor) {
new OperationVisitorImpl(sessionInfo).execute(changes);
+ changes.persisted();
+ eventSignal = getEventPollingRequest();
+ }
+ try {
+ eventSignal.acquire();
+ } catch (InterruptedException e) {
+ Thread.interrupted();
+ log.warn("Interrupted while waiting for events from RepositoryService");
}
}
@@ -532,42 +588,17 @@
/**
* Called when local or external events occured. This method is called after
- * changes have been applied to the repository. Depending on <code>changeLog</code>
- * this method is called as a result of:
- * <ul>
- * <li>a local <code>save</code> of transient changes. In this case
- * <code>changeLog</code> is non-<code>null</code>.</li>
- * <li>an execution of a workspace operation. In this case
- * <code>changeLog</code> is <code>null</code></li>
- * <li>an external change to the workspace (another session modified the
- * workspace). In this case <code>changeLog</code> is <code>null</code></li>
- * </ul>
- *
- * @param events the events generated by the repository service as a
- * response to the executed operation(s).
- * @param changeLog the local <code>ChangeLog</code> which contains the
- * affected transient <code>ItemState</code>s and the
- * relevant {@link Operation}s that lead to the
- * modifications. If <code>null</code> this method is
- * called as a consequence of an external change or a call
- * of a workspace operation. In that case there are no
- * local transient changes.
+ * changes have been applied to the repository.
+ *
+ * @param events the events generated by the repository service as the
+ * effect of a change.
*/
- private void onEventReceived(EventBundle[] events, ChangeLog changeLog) {
+ private void onEventReceived(EventBundle[] events) {
// notify listener
InternalEventListener[] lstnrs = (InternalEventListener[]) listeners.toArray(new InternalEventListener[listeners.size()]);
for (int i = 0; i < events.length; i++) {
- EventBundle bundle = events[i];
- if (bundle.isLocal() && changeLog != null) {
- // local change from batch operation
- for (int j = 0; j < lstnrs.length; j++) {
- lstnrs[j].onEvent(bundle, changeLog);
- }
- } else {
- // external change or workspace operation
- for (int j = 0; j < lstnrs.length; j++) {
- lstnrs[j].onEvent(bundle);
- }
+ for (int j = 0; j < lstnrs.length; j++) {
+ lstnrs[j].onEvent(events[i]);
}
}
}
@@ -584,7 +615,6 @@
private final SessionInfo sessionInfo;
private Batch batch;
- private EventBundle[] events;
private OperationVisitorImpl(SessionInfo sessionInfo) {
this.sessionInfo = sessionInfo;
@@ -605,8 +635,7 @@
}
} finally {
if (batch != null) {
- events = service.submit(batch);
- onEventReceived(events, changeLog);
+ service.submit(batch);
// reset batch field
batch = null;
}
@@ -617,19 +646,8 @@
* Executes the operations on the repository service.
*/
private void execute(Operation workspaceOperation) throws RepositoryException, ConstraintViolationException, AccessDeniedException, ItemExistsException, NoSuchNodeTypeException, UnsupportedRepositoryOperationException, VersionException {
- boolean success = false;
- try {
- log.info("executing: " + workspaceOperation);
- workspaceOperation.accept(this);
- success = true;
- } finally {
- if (success && events != null) {
- // a workspace operation is like an external change: there
- // is no changelog to persist. but still the events must
- // be reported as local changes.
- onEventReceived(events, null);
- }
- }
+ log.info("executing: " + workspaceOperation);
+ workspaceOperation.accept(this);
}
//-----------------------< OperationVisitor >---------------------------
// TODO: review retrival of ItemIds for transient modifications
@@ -671,20 +689,20 @@
public void visit(Clone operation) throws NoSuchWorkspaceException, LockException, ConstraintViolationException, AccessDeniedException, ItemExistsException, UnsupportedRepositoryOperationException, VersionException, RepositoryException {
NodeId nId = operation.getNodeState().getNodeId();
NodeId destParentId = operation.getDestinationParentState().getNodeId();
- events = service.clone(sessionInfo, operation.getWorkspaceName(), nId, destParentId, operation.getDestinationName(), operation.isRemoveExisting());
+ service.clone(sessionInfo, operation.getWorkspaceName(), nId, destParentId, operation.getDestinationName(), operation.isRemoveExisting());
}
public void visit(Copy operation) throws NoSuchWorkspaceException, LockException, ConstraintViolationException, AccessDeniedException, ItemExistsException, UnsupportedRepositoryOperationException, VersionException, RepositoryException {
NodeId nId = operation.getNodeState().getNodeId();
NodeId destParentId = operation.getDestinationParentState().getNodeId();
- events = service.copy(sessionInfo, operation.getWorkspaceName(), nId, destParentId, operation.getDestinationName());
+ service.copy(sessionInfo, operation.getWorkspaceName(), nId, destParentId, operation.getDestinationName());
}
public void visit(Move operation) throws LockException, ConstraintViolationException, AccessDeniedException, ItemExistsException, UnsupportedRepositoryOperationException, VersionException, RepositoryException {
NodeId moveId = operation.getSourceId();
NodeId destParentId = operation.getDestinationParentState().getNodeId();
if (batch == null) {
- events = service.move(sessionInfo, moveId, destParentId, operation.getDestinationName());
+ service.move(sessionInfo, moveId, destParentId, operation.getDestinationName());
} else {
batch.move(moveId, destParentId, operation.getDestinationName());
}
@@ -692,7 +710,7 @@
public void visit(Update operation) throws NoSuchWorkspaceException, AccessDeniedException, LockException, InvalidItemStateException, RepositoryException {
NodeId nId = operation.getNodeState().getNodeId();
- events = service.update(sessionInfo, nId, operation.getSourceWorkspaceName());
+ service.update(sessionInfo, nId, operation.getSourceWorkspaceName());
}
public void visit(Remove operation) throws RepositoryException {
@@ -744,11 +762,11 @@
}
public void visit(Checkout operation) throws UnsupportedRepositoryOperationException, LockException, RepositoryException {
- events = service.checkout(sessionInfo, operation.getNodeState().getNodeId());
+ service.checkout(sessionInfo, operation.getNodeState().getNodeId());
}
public void visit(Checkin operation) throws UnsupportedRepositoryOperationException, LockException, InvalidItemStateException, RepositoryException {
- events = service.checkin(sessionInfo, operation.getNodeState().getNodeId());
+ service.checkin(sessionInfo, operation.getNodeState().getNodeId());
}
public void visit(Restore operation) throws VersionException, PathNotFoundException, ItemExistsException, UnsupportedRepositoryOperationException, LockException, InvalidItemStateException, RepositoryException {
@@ -764,7 +782,7 @@
}
if (nState == null) {
- events = service.restore(sessionInfo, vIds, operation.removeExisting());
+ service.restore(sessionInfo, vIds, operation.removeExisting());
} else {
if (vIds.length > 1) {
throw new IllegalArgumentException("Restore from a single node must specify but one single Version.");
@@ -777,27 +795,14 @@
} else {
targetId = nState.getNodeId();
}
- events = service.restore(sessionInfo, targetId, vIds[0], operation.removeExisting());
+ service.restore(sessionInfo, targetId, vIds[0], operation.removeExisting());
}
}
public void visit(Merge operation) throws NoSuchWorkspaceException, AccessDeniedException, MergeException, LockException, InvalidItemStateException, RepositoryException {
NodeId nId = operation.getNodeState().getNodeId();
- events = service.merge(sessionInfo, nId, operation.getSourceWorkspaceName(), operation.bestEffort());
- List externalEventBundles = new ArrayList();
- for (int i = 0; i < events.length; i++) {
- if (events[i].isLocal()) {
- // todo: improve.... inform operation about modified items (build mergefailed iterator)
- operation.getEventListener().onEvent(events[i]);
- } else {
- // otherwise dispatch as external event
- externalEventBundles.add(events[i]);
- }
- }
- if (!externalEventBundles.isEmpty()) {
- EventBundle[] bundles = (EventBundle[]) externalEventBundles.toArray(new EventBundle[externalEventBundles.size()]);
- onEventReceived(bundles, null);
- }
+ // todo service should return ids of failed nodes
+ service.merge(sessionInfo, nId, operation.getSourceWorkspaceName(), operation.bestEffort());
}
public void visit(ResolveMergeConflict operation) throws VersionException, InvalidItemStateException, UnsupportedRepositoryOperationException, RepositoryException {
@@ -838,7 +843,7 @@
if (resolveDone) {
predecessorIds[i] = vId;
}
- events = service.resolveMergeConflict(sessionInfo, nId, mergeFailedIds, predecessorIds);
+ service.resolveMergeConflict(sessionInfo, nId, mergeFailedIds, predecessorIds);
} catch (ItemStateException e) {
// should not occur.
throw new RepositoryException(e);
@@ -847,30 +852,62 @@
public void visit(LockOperation operation) throws AccessDeniedException, InvalidItemStateException, UnsupportedRepositoryOperationException, LockException, RepositoryException {
NodeId nId = operation.getNodeState().getNodeId();
- events = service.lock(sessionInfo, nId, operation.isDeep(), operation.isSessionScoped());
+ service.lock(sessionInfo, nId, operation.isDeep(), operation.isSessionScoped());
}
public void visit(LockRefresh operation) throws AccessDeniedException, InvalidItemStateException, UnsupportedRepositoryOperationException, LockException, RepositoryException {
NodeId nId = operation.getNodeState().getNodeId();
- events = service.refreshLock(sessionInfo, nId);
+ service.refreshLock(sessionInfo, nId);
}
public void visit(LockRelease operation) throws AccessDeniedException, InvalidItemStateException, UnsupportedRepositoryOperationException, LockException, RepositoryException {
NodeId nId = operation.getNodeState().getNodeId();
- events = service.unlock(sessionInfo, nId);
+ service.unlock(sessionInfo, nId);
}
public void visit(AddLabel operation) throws VersionException, RepositoryException {
NodeId vhId = operation.getVersionHistoryState().getNodeId();
NodeId vId = operation.getVersionState().getNodeId();
- events = service.addVersionLabel(sessionInfo, vhId, vId, operation.getLabel(), operation.moveLabel());
+ service.addVersionLabel(sessionInfo, vhId, vId, operation.getLabel(), operation.moveLabel());
}
public void visit(RemoveLabel operation) throws VersionException, RepositoryException {
NodeId vhId = operation.getVersionHistoryState().getNodeId();
NodeId vId = operation.getVersionState().getNodeId();
- events = service.removeVersionLabel(sessionInfo, vhId, vId, operation.getLabel());
+ service.removeVersionLabel(sessionInfo, vhId, vId, operation.getLabel());
+ }
+ }
+
+ /**
+ * Requests an immediate poll for events. The returned Sync will be
+ * released by the event polling thread when events have been retrieved.
+ */
+ private Sync getEventPollingRequest() {
+ Sync signal;
+ if (externalChangeFeed != null) {
+ // observation supported
+ signal = new Latch();
+ try {
+ immediateEventRequests.put(signal);
+ } catch (InterruptedException e) {
+ log.warn("Unable to request immediate event poll: " + e);
+ }
+ } else {
+ // no observation, return a dummy sync which can be acquired immediately
+ signal = new Sync() {
+ public void acquire() {
+ }
+
+ public boolean attempt(long l) {
+ return true;
+ }
+
+ public void release() {
+ throw new UnsupportedOperationException();
+ }
+ };
}
+ return signal;
}
/**
@@ -895,21 +932,48 @@
public void run() {
while (!Thread.interrupted()) {
try {
- Thread.sleep(pollingInterval);
- } catch (InterruptedException e) {
- // terminate
- break;
- }
- try {
+ // wait for a signal to do an immediate poll but wait at
+ // most EXTERNAL_EVENT_POLLING_INTERVAL
+ Sync signal = (Sync) immediateEventRequests.poll(pollingInterval);
+
synchronized (updateMonitor) {
- EventBundle[] bundles = service.getEvents(sessionInfo, 0);
+ // if this thread was waiting for updateMonitor and now
+ // enters this synchronized block, then a user thread
+ // has just finished an operation and will probably
+ // request an immediate event poll. That's why we
+ // check here again for a sync signal
+ if (signal == null) {
+ signal = (Sync) immediateEventRequests.poll(0);
+ }
+
+ if (signal != null) {
+ log.debug("Request for immediate event poll");
+ }
+
+ // get filters from listeners
+ List filters = new ArrayList();
+ InternalEventListener[] iel = (InternalEventListener[]) listeners.toArray(new InternalEventListener[0]);
+ for (int i = 0; i < iel.length; i++) {
+ filters.addAll(iel[i].getEventFilters());
+ }
+ EventBundle[] bundles = service.getEvents(sessionInfo,
+ 0, (EventFilter[]) filters.toArray(
+ new EventFilter[filters.size()]));
if (bundles.length > 0) {
- onEventReceived(bundles, null);
+ onEventReceived(bundles);
+ }
+ if (signal != null) {
+ log.debug("About to signal that events have been delivered");
+ signal.release();
+ log.debug("Event delivery signaled");
}
}
} catch (RepositoryException e) {
log.warn("Exception while retrieving event bundles: " + e);
log.debug("Dump:", e);
+ } catch (InterruptedException e) {
+ // terminate
+ break;
}
}
}
Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/lock/LockManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/lock/LockManagerImpl.java?view=diff&rev=472888&r1=472887&r2=472888
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/lock/LockManagerImpl.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/lock/LockManagerImpl.java Thu Nov 9 05:12:21 2006
@@ -25,13 +25,12 @@
import org.apache.jackrabbit.jcr2spi.operation.LockRelease;
import org.apache.jackrabbit.jcr2spi.operation.LockRefresh;
import org.apache.jackrabbit.jcr2spi.state.NodeState;
-import org.apache.jackrabbit.jcr2spi.state.ChangeLog;
import org.apache.jackrabbit.jcr2spi.state.Status;
import org.apache.jackrabbit.name.QName;
-import org.apache.jackrabbit.spi.EventIterator;
import org.apache.jackrabbit.spi.Event;
import org.apache.jackrabbit.spi.LockInfo;
import org.apache.jackrabbit.spi.EventBundle;
+import org.apache.jackrabbit.spi.EventFilter;
import org.slf4j.LoggerFactory;
import org.slf4j.Logger;
@@ -45,6 +44,8 @@
import java.util.Iterator;
import java.util.Map;
import java.util.HashMap;
+import java.util.Collection;
+import java.util.Collections;
/**
* <code>LockManagerImpl</code>...
@@ -454,6 +455,7 @@
private final NodeState lockHoldingState;
private LockInfo lockInfo;
private boolean isLive = true;
+ private final EventFilter eventFilter;
private LockState(NodeState lockHoldingState) throws LockException, RepositoryException {
lockHoldingState.checkIsWorkspaceState();
@@ -466,6 +468,8 @@
// register as internal listener to the wsp manager in order to get
// informed if this lock ends his life.
+ eventFilter = wspManager.createEventFilter(Event.PROPERTY_REMOVED,
+ lockHoldingState.getQPath(), false, null, null, true);
wspManager.addEventListener(this);
}
@@ -532,6 +536,17 @@
}
//------------------------------------------< InternalEventListener >---
+
+ /**
+ * @see InternalEventListener#getEventFilters()
+ */
+ public Collection getEventFilters() {
+ return Collections.singletonList(eventFilter);
+ }
+
+ /**
+ * @see InternalEventListener#onEvent(EventBundle)
+ */
public void onEvent(EventBundle eventBundle) {
if (!isLive) {
// since we only monitor the removal of the lock (by means
@@ -540,26 +555,10 @@
return;
}
- for (EventIterator it = eventBundle.getEvents(); it.hasNext(); ) {
- Event ev = it.nextEvent();
- // if the jcr:lockIsDeep property related to this Lock got removed,
- // we assume that the lock has been released.
- // TODO: not correct to compare nodeIds
- if (ev.getType() == Event.PROPERTY_REMOVED
- && QName.JCR_LOCKISDEEP.equals(ev.getQPath().getNameElement().getName())
- && lockHoldingState.getNodeId().equals(ev.getParentId())) {
-
- // this lock has been release by someone else (and not by
- // a call to LockManager#unlock -> clean up and set isLive
- // flag to false.
- unlocked();
- break;
- }
- }
- }
-
- public void onEvent(EventBundle eventBundle, ChangeLog changeLog) {
- // nothing to do. not interested in transient modifications
+ // this lock has been release by someone else (and not by
+ // a call to LockManager#unlock -> clean up and set isLive
+ // flag to false.
+ unlocked();
}
}
Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/FilteredEventIterator.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/FilteredEventIterator.java?view=diff&rev=472888&r1=472887&r2=472888
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/FilteredEventIterator.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/FilteredEventIterator.java Thu Nov 9 05:12:21 2006
@@ -19,8 +19,9 @@
import org.slf4j.LoggerFactory;
import org.slf4j.Logger;
import org.apache.jackrabbit.spi.EventBundle;
+import org.apache.jackrabbit.spi.EventFilter;
+import org.apache.jackrabbit.name.NamespaceResolver;
-import javax.jcr.RepositoryException;
import javax.jcr.observation.Event;
import javax.jcr.observation.EventIterator;
@@ -53,6 +54,11 @@
private final boolean isLocal;
/**
+ * The namespace resolver of the session that created this event iterator.
+ */
+ private final NamespaceResolver nsResolver;
+
+ /**
* The next {@link javax.jcr.observation.Event} in this iterator
*/
private Event next;
@@ -65,15 +71,20 @@
/**
* Creates a new <code>FilteredEventIterator</code>.
*
- * @param events the {@link org.apache.jackrabbit.spi.Event}s as a bundle.
- * @param filter only event that pass the filter will be dispatched to the
- * event listener.
+ * @param events the {@link org.apache.jackrabbit.spi.Event}s as a
+ * bundle.
+ * @param filter only event that pass the filter will be dispatched to
+ * the event listener.
+ * @param nsResolver the namespace resolver of the session that created this
+ * <code>FilteredEventIterator</code>.
*/
public FilteredEventIterator(EventBundle events,
- EventFilter filter) {
- actualEvents = events.getEvents();
+ EventFilter filter,
+ NamespaceResolver nsResolver) {
+ this.actualEvents = events.getEvents();
this.filter = filter;
this.isLocal = events.isLocal();
+ this.nsResolver = nsResolver;
fetchNext();
}
@@ -151,11 +162,7 @@
next = null;
while (next == null && actualEvents.hasNext()) {
event = (org.apache.jackrabbit.spi.Event) actualEvents.next();
- try {
- next = filter.blocks(event, isLocal) ? null : new EventImpl(filter.getNamespaceResolver(), event);
- } catch (RepositoryException e) {
- log.error("Exception while applying filter.", e);
- }
+ next = filter.accept(event, isLocal) ? new EventImpl(nsResolver, event) : null;
}
}
}
Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/InternalEventListener.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/InternalEventListener.java?view=diff&rev=472888&r1=472887&r2=472888
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/InternalEventListener.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/InternalEventListener.java Thu Nov 9 05:12:21 2006
@@ -17,7 +17,8 @@
package org.apache.jackrabbit.jcr2spi.observation;
import org.apache.jackrabbit.spi.EventBundle;
-import org.apache.jackrabbit.jcr2spi.state.ChangeLog;
+
+import java.util.Collection;
/**
* <code>InternalEventListener</code> receives changes as a result of a local
@@ -32,5 +33,15 @@
*/
public void onEvent(EventBundle eventBundle);
- public void onEvent(EventBundle eventBundle, ChangeLog changeLog);
+ /**
+ * Returns a collection of event filters which is in use by this event
+ * listener. The event bundles delivered to {@link #onEvent} will be filtered
+ * using the collection returned by this method. An event is included
+ * in an event bundles if it is accepted by at least one of the filters
+ * returned by this method.
+ *
+ * @return an unmodifiable collection of {@link EventFilter}s currently
+ * in use by this event listener.
+ */
+ public Collection getEventFilters();
}
Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/ObservationManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/ObservationManagerImpl.java?view=diff&rev=472888&r1=472887&r2=472888
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/ObservationManagerImpl.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/ObservationManagerImpl.java Thu Nov 9 05:12:21 2006
@@ -17,7 +17,7 @@
package org.apache.jackrabbit.jcr2spi.observation;
import org.apache.jackrabbit.jcr2spi.nodetype.NodeTypeRegistry;
-import org.apache.jackrabbit.jcr2spi.state.ChangeLog;
+import org.apache.jackrabbit.jcr2spi.WorkspaceManager;
import org.apache.jackrabbit.name.MalformedPathException;
import org.apache.jackrabbit.name.NameException;
import org.apache.jackrabbit.name.NameFormat;
@@ -26,6 +26,7 @@
import org.apache.jackrabbit.name.PathFormat;
import org.apache.jackrabbit.name.QName;
import org.apache.jackrabbit.spi.EventBundle;
+import org.apache.jackrabbit.spi.EventFilter;
import org.apache.jackrabbit.util.IteratorHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -38,6 +39,8 @@
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
+import java.util.List;
+import java.util.ArrayList;
/**
* <code>ObservationManagerImpl</code>...
@@ -50,6 +53,11 @@
private static final Logger log = LoggerFactory.getLogger(ObservationManagerImpl.class);
/**
+ * The workspace manager.
+ */
+ private final WorkspaceManager wspManager;
+
+ /**
* The session this observation manager belongs to.
*/
private final NamespaceResolver nsResolver;
@@ -71,13 +79,16 @@
/**
* Creates a new observation manager for <code>session</code>.
+ * @param wspManager the WorkspaceManager.
* @param nsResolver NamespaceResolver to be used by this observation manager
* is based on.
* @param ntRegistry The <code>NodeTypeRegistry</code> of the session.
*/
- public ObservationManagerImpl(NamespaceResolver nsResolver, NodeTypeRegistry ntRegistry) {
+ public ObservationManagerImpl(WorkspaceManager wspManager, NamespaceResolver nsResolver, NodeTypeRegistry ntRegistry) {
+ this.wspManager = wspManager;
this.nsResolver = nsResolver;
this.ntRegistry = ntRegistry;
+ this.wspManager.addEventListener(this);
}
/**
@@ -87,8 +98,8 @@
int eventTypes,
String absPath,
boolean isDeep,
- String[] uuid,
- String[] nodeTypeName,
+ String[] uuids,
+ String[] nodeTypeNames,
boolean noLocal) throws RepositoryException {
Path path;
try {
@@ -98,18 +109,18 @@
}
// create NodeType instances from names
- QName[] nodeTypeNames;
- if (nodeTypeName == null) {
- nodeTypeNames = null;
+ QName[] nodeTypeQNames;
+ if (nodeTypeNames == null) {
+ nodeTypeQNames = null;
} else {
try {
- nodeTypeNames = new QName[nodeTypeName.length];
- for (int i = 0; i < nodeTypeName.length; i++) {
- QName ntName = NameFormat.parse(nodeTypeName[i], nsResolver);
+ nodeTypeQNames = new QName[nodeTypeNames.length];
+ for (int i = 0; i < nodeTypeNames.length; i++) {
+ QName ntName = NameFormat.parse(nodeTypeNames[i], nsResolver);
if (!ntRegistry.isRegistered(ntName)) {
- throw new RepositoryException("unknown node type: " + nodeTypeName[i]);
+ throw new RepositoryException("unknown node type: " + nodeTypeNames[i]);
}
- nodeTypeNames[i] = ntName;
+ nodeTypeQNames[i] = ntName;
}
} catch (NameException e) {
throw new RepositoryException(e.getMessage());
@@ -117,8 +128,7 @@
}
synchronized (subscriptions) {
- EventFilter filter = new EventFilter(nsResolver, ntRegistry,
- eventTypes, path, isDeep, uuid, nodeTypeNames, noLocal);
+ EventFilter filter = wspManager.createEventFilter(eventTypes, path, isDeep, uuids, nodeTypeQNames, noLocal);
subscriptions.put(listener, filter);
readOnlySubscriptions = null;
}
@@ -149,6 +159,15 @@
//-----------------------< InternalEventListener >--------------------------
+ public Collection getEventFilters() {
+ List filters = new ArrayList();
+ synchronized (subscriptions) {
+ ensureReadOnlyMap();
+ filters.addAll(readOnlySubscriptions.values());
+ }
+ return filters;
+ }
+
public void onEvent(EventBundle eventBundle) {
// get active listeners
Map activeListeners;
@@ -159,7 +178,7 @@
for (Iterator it = activeListeners.keySet().iterator(); it.hasNext(); ) {
EventListener listener = (EventListener) it.next();
EventFilter filter = (EventFilter) activeListeners.get(listener);
- FilteredEventIterator eventIter = new FilteredEventIterator(eventBundle, filter);
+ FilteredEventIterator eventIter = new FilteredEventIterator(eventBundle, filter, nsResolver);
if (eventIter.hasNext()) {
try {
listener.onEvent(eventIter);
@@ -170,17 +189,6 @@
}
}
}
- }
-
- /**
- * Same as {@link #onEvent(EventBundle)} but only used for local changes
- * with a <code>ChangeLog</code>.
- *
- * @param eventBundle
- * @param changeLog
- */
- public void onEvent(EventBundle eventBundle, ChangeLog changeLog) {
- onEvent(eventBundle);
}
//-------------------------< internal >-------------------------------------
Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ChangeLog.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ChangeLog.java?view=diff&rev=472888&r1=472887&r2=472888
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ChangeLog.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ChangeLog.java Thu Nov 9 05:12:21 2006
@@ -122,6 +122,15 @@
modifiedRefs.add(refs);
}
+ /**
+ * Call this method when this change log has been sucessfully persisted.
+ * This implementation will call {@link ItemState#refresh(ChangeLog)
+ * ItemState.refresh(this)} on the target item of this change log.
+ */
+ public void persisted() {
+ target.refresh(this);
+ }
+
//----------------------< Retrieve information present in the ChangeLog >---
/**
*
Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemState.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemState.java?view=diff&rev=472888&r1=472887&r2=472888
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemState.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ItemState.java Thu Nov 9 05:12:21 2006
@@ -447,11 +447,9 @@
* successfully submitted to the SPI..
*
* @param changeLog
- * @return a Set of <code>ItemId</code>s in order to allow the caller to
- * remove those events that have already been processed.
* @throws IllegalStateException if this state is a 'session' state.
*/
- abstract Set refresh(ChangeLog changeLog) throws IllegalStateException;
+ abstract void refresh(ChangeLog changeLog) throws IllegalStateException;
/**
* Copy all state information from overlayed state to this state
Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/NodeState.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/NodeState.java?view=diff&rev=472888&r1=472887&r2=472888
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/NodeState.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/NodeState.java Thu Nov 9 05:12:21 2006
@@ -141,7 +141,7 @@
super(overlayedState, parent, initialStatus, isf, idFactory);
if (overlayedState != null) {
synchronized (overlayedState) {
- NodeState wspState = (NodeState) overlayedState;
+ NodeState wspState = overlayedState;
name = wspState.name;
uuid = wspState.uuid;
nodeTypeName = wspState.nodeTypeName;
@@ -713,12 +713,11 @@
* {@inheritDoc}
* @see ItemState#refresh(ChangeLog)
*/
- Set refresh(ChangeLog changeLog) throws IllegalStateException {
+ void refresh(ChangeLog changeLog) throws IllegalStateException {
// remember parent states that have need to adjust their uuid/mixintypes
// or that got a new child entry added or existing entries removed.
Map modParents = new HashMap();
- Set processedIds = new HashSet();
// process deleted states from the changelog
for (Iterator it = changeLog.deletedStates(); it.hasNext();) {
@@ -737,9 +736,6 @@
}
modifiedParent(parent, state, modParents);
}
- // don't remove processed state from changelog, but from event list
- // state on changelog is used for check if parent is deleted as well.
- processedIds.add(state.getId());
}
// process added states from the changelog. since the changlog maintains
@@ -787,7 +783,6 @@
}
it.remove();
- processedIds.add(addedState.getId());
} catch (ItemStateException e) {
log.error("Internal error.", e);
}
@@ -802,7 +797,6 @@
// move overlayed state as well
NodeState newParent = (NodeState) modState.parent.overlayedState;
NodeState overlayed = (NodeState) modState.overlayedState;
- ItemId removedId = overlayed.getId();
try {
overlayed.parent.moveEntry(newParent, overlayed, modNodeState.getQName(), modNodeState.getDefinition());
} catch (RepositoryException e) {
@@ -813,8 +807,6 @@
modNodeState.setStatus(Status.EXISTING);
it.remove();
- processedIds.add(removedId);
- processedIds.add(modNodeState.getId());
} else {
modifiedParent((NodeState)modState, null, modParents);
}
@@ -832,8 +824,6 @@
modifiedParent(modState.getParent(), modState, modParents);
}
it.remove();
- // remove the property-modification event from the set
- processedIds.add(modState.getId());
}
}
@@ -858,8 +848,6 @@
// TODO: discard state and force reload of all data
}
}
-
- return processedIds;
}
/**
Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/PathResolver.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/PathResolver.java?view=diff&rev=472888&r1=472887&r2=472888
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/PathResolver.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/PathResolver.java Thu Nov 9 05:12:21 2006
@@ -143,6 +143,15 @@
NodeState state = start;
for (int i = 0; i < path.getLength(); i++) {
Path.PathElement elem = path.getElement(i);
+ // check for root element
+ if (elem.denotesRoot()) {
+ if (start.getParent() != null) {
+ throw new NoSuchItemStateException(path.toString());
+ } else {
+ continue;
+ }
+ }
+
// first try to resolve node
if (state.hasChildNodeEntry(elem.getName(), elem.getNormalizedIndex())) {
ChildNodeEntry cne = state.getChildNodeEntry(elem.getName(), elem.getNormalizedIndex());
Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/PropertyState.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/PropertyState.java?view=diff&rev=472888&r1=472887&r2=472888
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/PropertyState.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/PropertyState.java Thu Nov 9 05:12:21 2006
@@ -35,7 +35,6 @@
import java.util.Set;
import java.util.Collection;
import java.util.Iterator;
-import java.util.HashSet;
/**
* <code>PropertyState</code> represents the state of a <code>Property</code>.
@@ -262,8 +261,7 @@
* {@inheritDoc}
* @see ItemState#refresh(ChangeLog)
*/
- Set refresh(ChangeLog changeLog) throws IllegalStateException {
- Set processedIds = new HashSet(1);
+ void refresh(ChangeLog changeLog) throws IllegalStateException {
for (Iterator it = changeLog.modifiedStates(); it.hasNext();) {
ItemState modState = (ItemState) it.next();
if (modState == this) {
@@ -275,12 +273,8 @@
// push changes to overlayed state and reset status
((PropertyState) overlayedState).init(getType(), getValues());
setStatus(Status.EXISTING);
- // parent must not be informed, since all properties that
- // affect the parent state (uuid, mixins) are protected.
- processedIds.add(modState.getId());
}
}
- return processedIds;
}
/**
Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/WorkspaceItemStateManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/WorkspaceItemStateManager.java?view=diff&rev=472888&r1=472887&r2=472888
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/WorkspaceItemStateManager.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/WorkspaceItemStateManager.java Thu Nov 9 05:12:21 2006
@@ -17,20 +17,24 @@
package org.apache.jackrabbit.jcr2spi.state;
import org.apache.jackrabbit.jcr2spi.observation.InternalEventListener;
+import org.apache.jackrabbit.jcr2spi.WorkspaceManager;
import org.apache.jackrabbit.spi.IdFactory;
import org.apache.jackrabbit.spi.Event;
import org.apache.jackrabbit.spi.EventBundle;
import org.apache.jackrabbit.spi.EventIterator;
-import org.apache.jackrabbit.spi.ItemId;
+import org.apache.jackrabbit.spi.EventFilter;
+import org.apache.jackrabbit.name.Path;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import javax.jcr.UnsupportedRepositoryOperationException;
import java.util.Set;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Collection;
import java.util.List;
import java.util.ArrayList;
+import java.util.Collections;
/**
* <code>WorkspaceItemStateManager</code>
@@ -40,12 +44,26 @@
private static Logger log = LoggerFactory.getLogger(WorkspaceItemStateManager.class);
- public WorkspaceItemStateManager(ItemStateFactory isf, IdFactory idFactory) {
+ private final Collection eventFilter;
+
+ public WorkspaceItemStateManager(WorkspaceManager wspManager, ItemStateFactory isf, IdFactory idFactory) {
super(isf, idFactory);
+ EventFilter filter = null;
+ try {
+ // todo for now listen to everything
+ filter = wspManager.createEventFilter(Event.ALL_TYPES, Path.ROOT, true, null, null, false);
+ } catch (UnsupportedRepositoryOperationException e) {
+ // repository does not support observation
+ }
+ this.eventFilter = filter == null ? Collections.EMPTY_LIST : Collections.singletonList(filter);
}
//-------------------------------< InternalEventListener >------------------
+ public Collection getEventFilters() {
+ return eventFilter;
+ }
+
/**
* Processes <code>events</code> and invalidates cached <code>ItemState</code>s
* accordingly. Note that this performed for both local and non-local changes,
@@ -56,36 +74,6 @@
*/
public void onEvent(EventBundle eventBundle) {
pushEvents(getEventCollection(eventBundle));
- }
-
- /**
- *
- * @param eventBundle
- * @param changeLog
- */
- public void onEvent(EventBundle eventBundle, ChangeLog changeLog) {
- if (changeLog == null) {
- throw new IllegalArgumentException("ChangeLog must not be null.");
- }
- Collection evs = getEventCollection(eventBundle);
- // TODO: make sure, that events only contain events related to the modifications submitted with the changelog.
-
- // inform the changelog target state about the transient modifications
- // that have been persisted now: NEW-states will be connected to their
- // overlayed state, EXISTING_REMOVED states will be definitely removed,
- // EXISTING_MODIFIED states are merged with their workspace-state.
- Set processedIds = changeLog.getTarget().refresh(changeLog);
- for (Iterator it = evs.iterator(); it.hasNext();) {
- ItemId evId = ((Event)it.next()).getItemId();
- if (processedIds.contains(evId)) {
- it.remove();
- }
- }
-
- // all events not covered by the changelog must not be handled on the
- // session-states -> treat the same way as events returned by
- // workspace operations.
- pushEvents(evs);
}
private void pushEvents(Collection events) {
Modified: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/version/VersionManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/version/VersionManagerImpl.java?view=diff&rev=472888&r1=472887&r2=472888
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/version/VersionManagerImpl.java (original)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/version/VersionManagerImpl.java Thu Nov 9 05:12:21 2006
@@ -19,7 +19,6 @@
import org.apache.jackrabbit.jcr2spi.state.NodeState;
import org.apache.jackrabbit.jcr2spi.state.PropertyState;
import org.apache.jackrabbit.jcr2spi.state.ItemStateException;
-import org.apache.jackrabbit.jcr2spi.state.ChangeLog;
import org.apache.jackrabbit.jcr2spi.state.Status;
import org.apache.jackrabbit.jcr2spi.observation.InternalEventListener;
import org.apache.jackrabbit.jcr2spi.operation.Operation;
@@ -43,10 +42,12 @@
import org.apache.jackrabbit.spi.EventIterator;
import org.apache.jackrabbit.spi.Event;
import org.apache.jackrabbit.spi.EventBundle;
+import org.apache.jackrabbit.spi.EventFilter;
import java.util.Collection;
import java.util.List;
import java.util.ArrayList;
+import java.util.Collections;
/**
* <code>VersionManagerImpl</code>...
@@ -158,7 +159,14 @@
NodeState wspState = getWorkspaceState(nodeState);
// TODO find better solution to build the mergeFailed-collection
final List failedIds = new ArrayList();
+ final EventFilter eventFilter = workspaceManager.createEventFilter(
+ Event.ALL_TYPES, nodeState.getQPath(), true, null, null, false);
InternalEventListener mergeFailedCollector = new InternalEventListener() {
+
+ public Collection getEventFilters() {
+ return Collections.singletonList(eventFilter);
+ }
+
public void onEvent(EventBundle eventBundle) {
if (eventBundle.isLocal()) {
EventIterator it = eventBundle.getEvents();
@@ -169,9 +177,6 @@
}
}
}
- }
- public void onEvent(EventBundle eventBundle, ChangeLog changeLog) {
- // nothing to do. we are not interested in transient modifications
}
};
Added: jackrabbit/trunk/contrib/spi/spi/src/main/java/org/apache/jackrabbit/spi/EventFilter.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/spi/src/main/java/org/apache/jackrabbit/spi/EventFilter.java?view=auto&rev=472888
==============================================================================
--- jackrabbit/trunk/contrib/spi/spi/src/main/java/org/apache/jackrabbit/spi/EventFilter.java (added)
+++ jackrabbit/trunk/contrib/spi/spi/src/main/java/org/apache/jackrabbit/spi/EventFilter.java Thu Nov 9 05:12:21 2006
@@ -0,0 +1,44 @@
+/*
+ * 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.spi;
+
+import java.io.Serializable;
+
+/**
+ * An <code>EventFilter</code> is applied to the events as generated on the
+ * repository server. Event filter instances can be created with {@link
+ * RepositoryService#createEventFilter(int, org.apache.jackrabbit.name.Path,
+ * boolean, String[], org.apache.jackrabbit.name.QName[], boolean)
+ * RepositoryService.createEventFilter()}. Some repository implementation may
+ * also support event filters that are directly instanciated by the client.
+ */
+public interface EventFilter extends Serializable {
+
+ /**
+ * If an implementation returns <code>true</code> the <code>event</code>
+ * will be included in the event bundle returned by {@link
+ * RepositoryService#getEvents(SessionInfo, long, EventFilter[])}. A return
+ * value of <code>false</code> indicates that the client is not interested
+ * in the <code>event</code>.
+ *
+ * @param event the event in question.
+ * @param isLocal flag indicating whether this is a local event.
+ * @return <code>true</code> if the event is accepted by the filter;
+ * <code>false</code> otherwise.
+ */
+ public boolean accept(Event event, boolean isLocal);
+}
Propchange: jackrabbit/trunk/contrib/spi/spi/src/main/java/org/apache/jackrabbit/spi/EventFilter.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: jackrabbit/trunk/contrib/spi/spi/src/main/java/org/apache/jackrabbit/spi/RepositoryService.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/spi/src/main/java/org/apache/jackrabbit/spi/RepositoryService.java?view=diff&rev=472888&r1=472887&r2=472888
==============================================================================
--- jackrabbit/trunk/contrib/spi/spi/src/main/java/org/apache/jackrabbit/spi/RepositoryService.java (original)
+++ jackrabbit/trunk/contrib/spi/spi/src/main/java/org/apache/jackrabbit/spi/RepositoryService.java Thu Nov 9 05:12:21 2006
@@ -17,6 +17,7 @@
package org.apache.jackrabbit.spi;
import org.apache.jackrabbit.name.QName;
+import org.apache.jackrabbit.name.Path;
import javax.jcr.lock.LockException;
import javax.jcr.version.VersionException;
@@ -212,7 +213,6 @@
* Completes the this Batch or discard all the previous modifications.
*
* @param batch
- * @return EventBundle
* @throws PathNotFoundException
* @throws ItemNotFoundException
* @throws NoSuchNodeTypeException
@@ -224,7 +224,7 @@
* @throws UnsupportedRepositoryOperationException
* @throws RepositoryException
*/
- public EventBundle[] submit(Batch batch) throws PathNotFoundException, ItemNotFoundException, NoSuchNodeTypeException, ValueFormatException, VersionException, LockException, ConstraintViolationException, AccessDeniedException, UnsupportedRepositoryOperationException, RepositoryException;
+ public void submit(Batch batch) throws PathNotFoundException, ItemNotFoundException, NoSuchNodeTypeException, ValueFormatException, VersionException, LockException, ConstraintViolationException, AccessDeniedException, UnsupportedRepositoryOperationException, RepositoryException;
//-------------------------------------------------------------< Import >---
/**
@@ -233,7 +233,6 @@
* @param parentId
* @param xmlStream
* @param uuidBehaviour
- * @return
* @throws ItemExistsException
* @throws PathNotFoundException
* @throws VersionException
@@ -244,7 +243,7 @@
* @throws RepositoryException
* @see javax.jcr.Workspace#importXML(String, java.io.InputStream, int)
*/
- public EventBundle[] importXml(SessionInfo sessionInfo, NodeId parentId, InputStream xmlStream, int uuidBehaviour) throws ItemExistsException, PathNotFoundException, VersionException, ConstraintViolationException, LockException, AccessDeniedException, UnsupportedRepositoryOperationException, RepositoryException;
+ public void importXml(SessionInfo sessionInfo, NodeId parentId, InputStream xmlStream, int uuidBehaviour) throws ItemExistsException, PathNotFoundException, VersionException, ConstraintViolationException, LockException, AccessDeniedException, UnsupportedRepositoryOperationException, RepositoryException;
//---------------------------------------------------------< Copy, Move >---
/**
@@ -262,7 +261,7 @@
* @throws javax.jcr.RepositoryException
* @see javax.jcr.Workspace#move(String, String)
*/
- public EventBundle[] move(SessionInfo sessionInfo, NodeId srcNodeId, NodeId destParentNodeId, QName destName) throws ItemExistsException, PathNotFoundException, VersionException, ConstraintViolationException, LockException, AccessDeniedException, UnsupportedRepositoryOperationException, RepositoryException;
+ public void move(SessionInfo sessionInfo, NodeId srcNodeId, NodeId destParentNodeId, QName destName) throws ItemExistsException, PathNotFoundException, VersionException, ConstraintViolationException, LockException, AccessDeniedException, UnsupportedRepositoryOperationException, RepositoryException;
/**
* @param sessionInfo
@@ -282,7 +281,7 @@
* @see javax.jcr.Workspace#copy(String, String)
* @see javax.jcr.Workspace#copy(String, String, String)
*/
- public EventBundle[] copy(SessionInfo sessionInfo, String srcWorkspaceName, NodeId srcNodeId, NodeId destParentNodeId, QName destName) throws NoSuchWorkspaceException, ConstraintViolationException, VersionException, AccessDeniedException, PathNotFoundException, ItemExistsException, LockException, UnsupportedRepositoryOperationException, RepositoryException;
+ public void copy(SessionInfo sessionInfo, String srcWorkspaceName, NodeId srcNodeId, NodeId destParentNodeId, QName destName) throws NoSuchWorkspaceException, ConstraintViolationException, VersionException, AccessDeniedException, PathNotFoundException, ItemExistsException, LockException, UnsupportedRepositoryOperationException, RepositoryException;
//------------------------------------------------------< Update, Clone >---
/**
@@ -296,7 +295,7 @@
* @throws javax.jcr.RepositoryException
* @see javax.jcr.Node#update(String)
*/
- public EventBundle[] update(SessionInfo sessionInfo, NodeId nodeId, String srcWorkspaceName) throws NoSuchWorkspaceException, AccessDeniedException, LockException, InvalidItemStateException, RepositoryException;
+ public void update(SessionInfo sessionInfo, NodeId nodeId, String srcWorkspaceName) throws NoSuchWorkspaceException, AccessDeniedException, LockException, InvalidItemStateException, RepositoryException;
/**
* @param sessionInfo
@@ -316,7 +315,7 @@
* @throws javax.jcr.RepositoryException
* @see javax.jcr.Workspace#clone(String, String, String, boolean)
*/
- public EventBundle[] clone(SessionInfo sessionInfo, String srcWorkspaceName, NodeId srcNodeId, NodeId destParentNodeId, QName destName, boolean removeExisting) throws NoSuchWorkspaceException, ConstraintViolationException, VersionException, AccessDeniedException, PathNotFoundException, ItemExistsException, LockException, UnsupportedRepositoryOperationException, RepositoryException;
+ public void clone(SessionInfo sessionInfo, String srcWorkspaceName, NodeId srcNodeId, NodeId destParentNodeId, QName destName, boolean removeExisting) throws NoSuchWorkspaceException, ConstraintViolationException, VersionException, AccessDeniedException, PathNotFoundException, ItemExistsException, LockException, UnsupportedRepositoryOperationException, RepositoryException;
//------------------------------------------------------------< Locking >---
@@ -344,7 +343,7 @@
* @throws javax.jcr.RepositoryException
* @see javax.jcr.Node#lock(boolean, boolean)
*/
- public EventBundle[] lock(SessionInfo sessionInfo, NodeId nodeId, boolean deep, boolean sessionScoped) throws UnsupportedRepositoryOperationException, LockException, AccessDeniedException, InvalidItemStateException, RepositoryException;
+ public void lock(SessionInfo sessionInfo, NodeId nodeId, boolean deep, boolean sessionScoped) throws UnsupportedRepositoryOperationException, LockException, AccessDeniedException, InvalidItemStateException, RepositoryException;
/**
* Explicit refresh of an existing lock. Existing locks should be refreshed
@@ -356,7 +355,7 @@
* @throws javax.jcr.RepositoryException
* @see javax.jcr.lock.Lock#refresh()
*/
- public EventBundle[] refreshLock(SessionInfo sessionInfo, NodeId nodeId) throws LockException, RepositoryException;
+ public void refreshLock(SessionInfo sessionInfo, NodeId nodeId) throws LockException, RepositoryException;
/**
* Releases the lock on the given node.<p/>
@@ -372,7 +371,7 @@
* @throws javax.jcr.RepositoryException
* @see javax.jcr.Node#unlock()
*/
- public EventBundle[] unlock(SessionInfo sessionInfo, NodeId nodeId) throws UnsupportedRepositoryOperationException, LockException, AccessDeniedException, InvalidItemStateException, RepositoryException;
+ public void unlock(SessionInfo sessionInfo, NodeId nodeId) throws UnsupportedRepositoryOperationException, LockException, AccessDeniedException, InvalidItemStateException, RepositoryException;
//---------------------------------------------------------< Versioning >---
/**
@@ -385,7 +384,7 @@
* @throws javax.jcr.RepositoryException
* @see javax.jcr.Node#checkin()
*/
- public EventBundle[] checkin(SessionInfo sessionInfo, NodeId nodeId) throws VersionException, UnsupportedRepositoryOperationException, InvalidItemStateException, LockException, RepositoryException;
+ public void checkin(SessionInfo sessionInfo, NodeId nodeId) throws VersionException, UnsupportedRepositoryOperationException, InvalidItemStateException, LockException, RepositoryException;
/**
* @param sessionInfo
@@ -395,7 +394,7 @@
* @throws javax.jcr.RepositoryException
* @see javax.jcr.Node#checkout()
*/
- public EventBundle[] checkout(SessionInfo sessionInfo, NodeId nodeId) throws UnsupportedRepositoryOperationException, LockException, RepositoryException;
+ public void checkout(SessionInfo sessionInfo, NodeId nodeId) throws UnsupportedRepositoryOperationException, LockException, RepositoryException;
/**
* @param sessionInfo
@@ -414,7 +413,7 @@
* @see javax.jcr.Node#restore(javax.jcr.version.Version, String, boolean)
* @see javax.jcr.Node#restoreByLabel(String, boolean)
*/
- public EventBundle[] restore(SessionInfo sessionInfo, NodeId nodeId, NodeId versionId, boolean removeExisting) throws VersionException, PathNotFoundException, ItemExistsException, UnsupportedRepositoryOperationException, LockException, InvalidItemStateException, RepositoryException;
+ public void restore(SessionInfo sessionInfo, NodeId nodeId, NodeId versionId, boolean removeExisting) throws VersionException, PathNotFoundException, ItemExistsException, UnsupportedRepositoryOperationException, LockException, InvalidItemStateException, RepositoryException;
/**
* @param sessionInfo
@@ -428,13 +427,15 @@
* @throws javax.jcr.RepositoryException
* @see javax.jcr.Workspace#restore(javax.jcr.version.Version[], boolean)
*/
- public EventBundle[] restore(SessionInfo sessionInfo, NodeId[] versionIds, boolean removeExisting) throws ItemExistsException, UnsupportedRepositoryOperationException, VersionException, LockException, InvalidItemStateException, RepositoryException;
+ public void restore(SessionInfo sessionInfo, NodeId[] versionIds, boolean removeExisting) throws ItemExistsException, UnsupportedRepositoryOperationException, VersionException, LockException, InvalidItemStateException, RepositoryException;
/**
* @param sessionInfo
* @param nodeId
* @param srcWorkspaceName
* @param bestEffort
+ * @return an <code>IdIterator</code> over all nodes that received a merge
+ * result of "fail" in the course of this operation.
* @throws javax.jcr.NoSuchWorkspaceException
* @throws javax.jcr.AccessDeniedException
* @throws javax.jcr.MergeException
@@ -443,7 +444,7 @@
* @throws javax.jcr.RepositoryException
* @see javax.jcr.Node#merge(String, boolean)
*/
- public EventBundle[] merge(SessionInfo sessionInfo, NodeId nodeId, String srcWorkspaceName, boolean bestEffort) throws NoSuchWorkspaceException, AccessDeniedException, MergeException, LockException, InvalidItemStateException, RepositoryException;
+ public IdIterator merge(SessionInfo sessionInfo, NodeId nodeId, String srcWorkspaceName, boolean bestEffort) throws NoSuchWorkspaceException, AccessDeniedException, MergeException, LockException, InvalidItemStateException, RepositoryException;
/**
* @param sessionInfo
@@ -461,7 +462,7 @@
* @see javax.jcr.Node#cancelMerge(javax.jcr.version.Version)
* @see javax.jcr.Node#doneMerge(javax.jcr.version.Version)
*/
- public EventBundle[] resolveMergeConflict(SessionInfo sessionInfo, NodeId nodeId, NodeId[] mergeFailedIds, NodeId[] predecessorIds) throws VersionException, InvalidItemStateException, UnsupportedRepositoryOperationException, RepositoryException;
+ public void resolveMergeConflict(SessionInfo sessionInfo, NodeId nodeId, NodeId[] mergeFailedIds, NodeId[] predecessorIds) throws VersionException, InvalidItemStateException, UnsupportedRepositoryOperationException, RepositoryException;
/**
* @param sessionInfo
@@ -472,18 +473,17 @@
* @throws javax.jcr.RepositoryException
* @see javax.jcr.version.VersionHistory#addVersionLabel(String, String, boolean)
*/
- public EventBundle[] addVersionLabel(SessionInfo sessionInfo, NodeId versionHistoryId, NodeId versionId, QName label, boolean moveLabel) throws VersionException, RepositoryException;
+ public void addVersionLabel(SessionInfo sessionInfo, NodeId versionHistoryId, NodeId versionId, QName label, boolean moveLabel) throws VersionException, RepositoryException;
/**
* @param sessionInfo
* @param versionId
* @param label
- * @return
* @throws javax.jcr.version.VersionException
* @throws javax.jcr.RepositoryException
* @see javax.jcr.version.VersionHistory#removeVersionLabel(String)
*/
- public EventBundle[] removeVersionLabel(SessionInfo sessionInfo, NodeId versionHistoryId, NodeId versionId, QName label) throws VersionException, RepositoryException;
+ public void removeVersionLabel(SessionInfo sessionInfo, NodeId versionHistoryId, NodeId versionId, QName label) throws VersionException, RepositoryException;
//----------------------------------------------------------< Searching >---
/**
@@ -507,31 +507,76 @@
//--------------------------------------------------------< Observation >---
/**
+ * Creates an event filter based on the parameters available in {@link
+ * javax.jcr.observation.ObservationManager#addEventListener}.
+ *
+ * @param eventTypes A combination of one or more event type constants
+ * encoded as a bitmask.
+ * @param absPath an absolute path.
+ * @param isDeep a <code>boolean</code>.
+ * @param uuid array of UUIDs.
+ * @param nodeTypeName array of node type names.
+ * @param noLocal a <code>boolean</code>.
+ * @return the event filter instance with the given parameters.
+ * @throws UnsupportedRepositoryOperationException
+ * if this implementation does not support observation.
+ * @see javax.jcr.observation.ObservationManager#addEventListener(javax.jcr.observation.EventListener, int, String, boolean, String[], String[], boolean)
+ */
+ public EventFilter createEventFilter(int eventTypes,
+ Path absPath,
+ boolean isDeep,
+ String[] uuid,
+ QName[] nodeTypeName,
+ boolean noLocal)
+ throws UnsupportedRepositoryOperationException;
+
+ /**
* Retrieves the external events that occurred since the last call to this
- * method or any of the other methods of this interface that return {@link
- * EventBundle}s (e.g. {@link RepositoryService#submit(Batch)}). When
- * this method returns without an exception the bundle identfier in
- * <code>sessionInfo</code> will be updated to reference the most recent
- * event bundle returned by this call.
+ * method. When this method returns without an exception the bundle
+ * identfier in <code>sessionInfo</code> will be updated to reference the
+ * most recent event bundle returned by this call. In case an empty array is
+ * supplied as event filters it may also happen that the bundle identifier
+ * is updated even though no event bundle had been returned.
+ * <p/>
+ * An implementation is required to accept at least event filter instances
+ * created by {@link #createEventFilter}. Optionally an implementation may
+ * also support event filters instanciated by the client itself. An
+ * implementation may require special deployment in that case, e.g. to make
+ * the event filter implementation class available to the repository
+ * server.
*
* @param sessionInfo the session info.
* @param timeout a timeout in milliseconds to wait at most for an
* external event bundle. If <code>timeout</code> is up
* and no event occurred meanwhile an empty array is
* returned.
+ * @param filters the filters that are applied to the external events as
+ * they occurred on the repository. An event is included
+ * in an event bundle if it is {@link EventFilter#accept(Event)
+ * accept}ed by at least one of the supplied filters. If
+ * an empty array is passed none of the potential events
+ * are include in an event bundle. This allows a client
+ * to skip or ignore events for a certain period of time.
+ * If <code>null</code> is passed no filtering is done
+ * and all events are included in the event bundle.
* @return an array of <code>EventBundle</code>s representing the external
* events that occurred.
- * @throws RepositoryException if an error occurs while retrieving the event
- * bundles or the currently set bundle
- * identifier in <code>sessionInfo</code>
- * references an unknown or outdated event
- * bundle.
+ * @throws RepositoryException if an error occurs while retrieving the
+ * event bundles or the currently set bundle
+ * identifier in <code>sessionInfo</code>
+ * references an unknown or outdated event
+ * bundle.
* @throws UnsupportedRepositoryOperationException
- * if this implementation does not support
- * observation.
- */
- public EventBundle[] getEvents(SessionInfo sessionInfo, long timeout)
- throws RepositoryException, UnsupportedRepositoryOperationException;
+ * if this implementation does not support
+ * observation.
+ * @throws InterruptedException if the calling thread is interrupted while
+ * waiting for events within the specified
+ * <code>timeout</code>.
+ */
+ public EventBundle[] getEvents(SessionInfo sessionInfo,
+ long timeout,
+ EventFilter[] filters)
+ throws RepositoryException, UnsupportedRepositoryOperationException, InterruptedException;
//---------------------------------------------------------< Namespaces >---
/**
Modified: jackrabbit/trunk/contrib/spi/spi/src/main/java/org/apache/jackrabbit/spi/SessionInfo.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/spi/src/main/java/org/apache/jackrabbit/spi/SessionInfo.java?view=diff&rev=472888&r1=472887&r2=472888
==============================================================================
--- jackrabbit/trunk/contrib/spi/spi/src/main/java/org/apache/jackrabbit/spi/SessionInfo.java (original)
+++ jackrabbit/trunk/contrib/spi/spi/src/main/java/org/apache/jackrabbit/spi/SessionInfo.java Thu Nov 9 05:12:21 2006
@@ -57,7 +57,7 @@
/**
* Sets the identifier of the last {@link EventBundle} delivered using this
* <code>SessionInfo</code>. This identifier will be used to retrieve the
- * subsequent event bundles when calling {@link RepositoryService#getEvents(SessionInfo, long)}.
+ * subsequent event bundles when calling {@link RepositoryService#getEvents(SessionInfo, long, EventFilter[])}.
*
* @param eventBundleId the identifier of the last {@link EventBundle}
* delivered using this <code>SessionInfo</code>.
Modified: jackrabbit/trunk/contrib/spi/spi/src/main/java/org/apache/jackrabbit/spi/package.html
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/spi/src/main/java/org/apache/jackrabbit/spi/package.html?view=diff&rev=472888&r1=472887&r2=472888
==============================================================================
--- jackrabbit/trunk/contrib/spi/spi/src/main/java/org/apache/jackrabbit/spi/package.html (original)
+++ jackrabbit/trunk/contrib/spi/spi/src/main/java/org/apache/jackrabbit/spi/package.html Thu Nov 9 05:12:21 2006
@@ -45,19 +45,7 @@
SPI. With only little thread synchronization overhead events can be acquired
using a <code>timeout</code> of {@link java.lang.Long#MAX_VALUE}.
<p/>
-In addition all methods on the RepositoryService that execute an operation on
-the repository return an array of <code>EventBundle</code>s. This array not
-only contains the bundle that is associated to the previously executed operation
-but also contains all preceeding event bundles not yet delivered since the last
-call to <code>RepositoryService.getEvents()</code> or any other method on the
-<code>RepositoryService</code> which returns <code>EventBundle</code>s. This
-design ensures a consistent sequence of event bundles delivered to the SPI
-client.
-<p/>
If an SPI implementation does not support observation, the method
<code>RepositoryService.getEvents()</code> will always throw an
-{@link javax.jcr.UnsupportedRepositoryOperationException} and all methods
-on <code>RepositoryService</code> which return an array of
-<code>EventBundle</code>s will only return one event bundle which is associated
-with the local operation that has just been executed.
+{@link javax.jcr.UnsupportedRepositoryOperationException}.
</body>
Added: jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/EventFilterImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/EventFilterImpl.java?view=auto&rev=472888
==============================================================================
--- jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/EventFilterImpl.java (added)
+++ jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/EventFilterImpl.java Thu Nov 9 05:12:21 2006
@@ -0,0 +1,147 @@
+/*
+ * 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.spi2dav;
+
+import org.apache.jackrabbit.spi.EventFilter;
+import org.apache.jackrabbit.spi.Event;
+import org.apache.jackrabbit.spi.NodeId;
+import org.apache.jackrabbit.name.Path;
+import org.apache.jackrabbit.name.MalformedPathException;
+import org.slf4j.LoggerFactory;
+import org.slf4j.Logger;
+
+import javax.jcr.PathNotFoundException;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.Arrays;
+
+/**
+ * <code>EventFilterImpl</code> is the spi2dav implementation of an {@link
+ * EventFilter}.
+ */
+class EventFilterImpl implements EventFilter {
+
+ /**
+ * The logger instance for this class.
+ */
+ private static final Logger log = LoggerFactory.getLogger(EventFilterImpl.class);
+
+ private final int eventTypes;
+
+ private final boolean isDeep;
+
+ private final Path absPath;
+
+ private final Set uuids;
+
+ private final Set nodeTypeNames;
+
+ private final boolean noLocal;
+
+ /**
+ * Creates a new <code>EventFilterImpl</code>.
+ *
+ * @param eventTypes the event types this filter is interested in.
+ * @param absPath filter events that are below this path.
+ * @param isDeep whether this filter is applied deep.
+ * @param uuids the uuids of the nodes this filter allows.
+ * @param nodeTypeNames the QNames of the already resolved node types this
+ * filter allows.
+ * @param noLocal whether this filter accepts local events or not.
+ */
+ EventFilterImpl(int eventTypes,
+ Path absPath,
+ boolean isDeep,
+ String[] uuids,
+ Set nodeTypeNames,
+ boolean noLocal) {
+ this.eventTypes = eventTypes;
+ this.absPath = absPath;
+ this.isDeep = isDeep;
+ this.uuids = uuids != null ? new HashSet(Arrays.asList(uuids)) : null;
+ this.nodeTypeNames = nodeTypeNames != null ? new HashSet(nodeTypeNames) : null;
+ this.noLocal = noLocal;
+ }
+
+ public boolean accept(Event event, boolean isLocal) {
+ int type = event.getType();
+ // check type
+ if ((type & eventTypes) == 0) {
+ return false;
+ }
+
+ // check local flag
+ if (isLocal && noLocal) {
+ return false;
+ }
+
+ // check UUIDs
+ NodeId parentId = event.getParentId();
+ if (uuids != null) {
+ if (parentId.getPath() == null) {
+ if (!uuids.contains(parentId.getUUID())) {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+
+ // check node types
+ if (nodeTypeNames != null) {
+ Set eventTypes = new HashSet();
+ eventTypes.addAll(Arrays.asList(event.getMixinTypeNames()));
+ eventTypes.add(event.getPrimaryNodeTypeName());
+ // create intersection
+ eventTypes.retainAll(nodeTypeNames);
+ if (eventTypes.isEmpty()) {
+ return false;
+ }
+ }
+
+ // finally check path
+ try {
+ // the relevant path for the path filter depends on the event type
+ // for node events, the relevant path is the one returned by
+ // Event.getPath().
+ // for property events, the relevant path is the path of the
+ // node where the property belongs to.
+ Path eventPath;
+ if (type == Event.NODE_ADDED || type == Event.NODE_REMOVED) {
+ eventPath = event.getQPath();
+ } else {
+ eventPath = event.getQPath().getAncestor(1);
+ }
+
+ boolean match = eventPath.equals(absPath);
+ if (!match && isDeep) {
+ match = eventPath.isDescendantOf(absPath);
+ }
+ return match;
+ } catch (MalformedPathException e) {
+ // should never get here
+ log.warn("malformed path: " + e);
+ log.debug("Exception: ", e);
+ } catch (PathNotFoundException e) {
+ // should never get here
+ log.warn("invalid property path: " + e);
+ log.debug("Exception: ", e);
+ }
+ // if we get here an exception occurred while checking for the path
+ return false;
+ }
+}
Propchange: jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/EventFilterImpl.java
------------------------------------------------------------------------------
svn:eol-style = native