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/10/27 16:16:15 UTC
svn commit: r468388 [1/2] - in /jackrabbit/trunk/contrib/spi:
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/observation/
jcr2spi/src/ma...
Author: mreutegg
Date: Fri Oct 27 07:16:13 2006
New Revision: 468388
URL: http://svn.apache.org/viewvc?view=rev&rev=468388
Log:
- replace all EventIterator return values in RepositoryService with EventBundle[]
- remove RepositoryService.addEventListener()/removeEventListener() and introduce getEvents() instead
- added quick description of new design: see org/apache/jackrabbit/spi/package.html
- update spi/project.properties with correct links to external javadoc
- fix package in spi/project.xml
Added:
jackrabbit/trunk/contrib/spi/spi/src/main/java/org/apache/jackrabbit/spi/EventBundle.java (with props)
jackrabbit/trunk/contrib/spi/spi/src/main/java/org/apache/jackrabbit/spi/package.html (with props)
jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/EventBundleImpl.java (with props)
Removed:
jackrabbit/trunk/contrib/spi/spi/src/main/java/org/apache/jackrabbit/spi/EventListener.java
jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/SubscriptionManager.java
Modified:
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/WorkspaceItemStateManager.java
jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/version/VersionManagerImpl.java
jackrabbit/trunk/contrib/spi/spi/project.properties
jackrabbit/trunk/contrib/spi/spi/project.xml
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/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/EventIteratorImpl.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/SessionInfoImpl.java
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=468388&r1=468387&r2=468388
==============================================================================
--- 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 Fri Oct 27 07:16:13 2006
@@ -56,25 +56,22 @@
import org.apache.jackrabbit.jcr2spi.operation.RemoveLabel;
import org.apache.jackrabbit.jcr2spi.security.AccessManager;
import org.apache.jackrabbit.jcr2spi.observation.InternalEventListener;
-import org.apache.jackrabbit.util.IteratorHelper;
import org.apache.jackrabbit.name.Path;
import org.apache.jackrabbit.name.QName;
import org.apache.jackrabbit.name.MalformedPathException;
import org.apache.jackrabbit.spi.RepositoryService;
import org.apache.jackrabbit.spi.SessionInfo;
import org.apache.jackrabbit.spi.NodeId;
-import org.apache.jackrabbit.spi.EventListener;
import org.apache.jackrabbit.spi.IdFactory;
import org.apache.jackrabbit.spi.LockInfo;
import org.apache.jackrabbit.spi.QueryInfo;
import org.apache.jackrabbit.spi.QNodeDefinition;
import org.apache.jackrabbit.spi.QNodeTypeDefinitionIterator;
-import org.apache.jackrabbit.spi.EventIterator;
-import org.apache.jackrabbit.spi.Event;
import org.apache.jackrabbit.spi.ItemId;
import org.apache.jackrabbit.spi.QNodeTypeDefinition;
import org.apache.jackrabbit.spi.PropertyId;
import org.apache.jackrabbit.spi.Batch;
+import org.apache.jackrabbit.spi.EventBundle;
import org.apache.jackrabbit.value.QValue;
import org.slf4j.LoggerFactory;
import org.slf4j.Logger;
@@ -114,6 +111,11 @@
private static Logger log = LoggerFactory.getLogger(WorkspaceManager.class);
+ /**
+ * TODO: make configurable
+ */
+ private static final int EXTERNAL_EVENT_POLLING_INTERVAL = 3 * 1000;
+
private final RepositoryService service;
private final SessionInfo sessionInfo;
@@ -123,11 +125,17 @@
private final NodeTypeRegistry ntRegistry;
/**
- * This is the event listener that listens on the repository service
- * for external changes. If <code>null</code> then the underlying repository
- * service does not support observation.
+ * Monitor object to synchronize the external feed thread with client
+ * threads that call {@link #execute(Operation)} or {@link
+ * #execute(ChangeLog)}.
+ */
+ private final Object updateMonitor = new Object();
+
+ /**
+ * This is the event polling for external changes. If <code>null</code>
+ * then the underlying repository service does not support observation.
*/
- private final EventListener externalChangeListener;
+ private final Thread externalChangeFeed;
/**
* List of event listener that are set on this WorkspaceManager to get
@@ -145,7 +153,7 @@
nsRegistry = createNamespaceRegistry(repositoryDescriptors);
ntRegistry = createNodeTypeRegistry(nsRegistry, repositoryDescriptors);
- externalChangeListener = createChangeListener(repositoryDescriptors);
+ externalChangeFeed = createChangeFeed(repositoryDescriptors, EXTERNAL_EVENT_POLLING_INTERVAL);
}
public NamespaceRegistryImpl getNamespaceRegistryImpl() {
@@ -278,30 +286,24 @@
}
/**
- * Creates and registers an EventListener on the RepositoryService that
- * listens for external changes.
+ * Creates a background thread which polls for external changes on the
+ * RepositoryService.
*
- * @param descriptors the repository descriptors
- * @return the listener or <code>null</code> if the underlying
+ * @param descriptors the repository descriptors.
+ * @param pollingInterval the polling interval in milliseconds.
+ * @return the background polling thread or <code>null</code> if the underlying
* <code>RepositoryService</code> does not support observation.
- * @throws RepositoryException if an error occurs while registering the
- * event listener.
*/
- private EventListener createChangeListener(Properties descriptors) throws RepositoryException {
+ private Thread createChangeFeed(Properties descriptors, int pollingInterval) {
String desc = descriptors.getProperty(Repository.OPTION_OBSERVATION_SUPPORTED);
- EventListener l = null;
+ Thread t = null;
if (Boolean.valueOf(desc).booleanValue()) {
- l = new EventListener() {
- public void onEvent(EventIterator events) {
- // external change
- onEventReceived(events, false, null);
- }
- };
- // register for all non-local events
- service.addEventListener(sessionInfo, service.getRootId(sessionInfo),
- l, Event.ALL_TYPES, true, null, null);
+ t = new Thread(new ExternalChangePolling(pollingInterval));
+ t.setName("External Change Polling");
+ t.setDaemon(true);
+ t.start();
}
- return l;
+ return t;
}
//---------------------------------------------------< ItemStateManager >---
@@ -366,7 +368,9 @@
* @see UpdatableItemStateManager#execute(Operation)
*/
public void execute(Operation operation) throws RepositoryException {
- new OperationVisitorImpl(sessionInfo).execute(operation);
+ synchronized (updateMonitor) {
+ new OperationVisitorImpl(sessionInfo).execute(operation);
+ }
}
/**
@@ -376,15 +380,18 @@
* @throws RepositoryException
*/
public void execute(ChangeLog changes) throws RepositoryException {
- new OperationVisitorImpl(sessionInfo).execute(changes);
+ synchronized (updateMonitor) {
+ new OperationVisitorImpl(sessionInfo).execute(changes);
+ }
}
public void dispose() {
- if (externalChangeListener != null) {
+ if (externalChangeFeed != null) {
+ externalChangeFeed.interrupt();
try {
- service.removeEventListener(sessionInfo, service.getRootId(sessionInfo), externalChangeListener);
- } catch (RepositoryException e) {
- log.warn("Exception while disposing workspace manager: " + e);
+ externalChangeFeed.join();
+ } catch (InterruptedException e) {
+ log.warn("Interrupted while waiting for external change thread to terminate.");
}
}
try {
@@ -537,6 +544,7 @@
* </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
@@ -545,27 +553,21 @@
* of a workspace operation. In that case there are no
* local transient changes.
*/
- private void onEventReceived(EventIterator events, boolean isLocal,
- ChangeLog changeLog) {
+ private void onEventReceived(EventBundle[] events, ChangeLog changeLog) {
// notify listener
- // need to copy events into a list because we notify multiple listeners
- List eventList = new ArrayList();
- while (events.hasNext()) {
- Event e = events.nextEvent();
- eventList.add(e);
- }
- if (eventList.isEmpty()) {
- return;
- }
-
InternalEventListener[] lstnrs = (InternalEventListener[]) listeners.toArray(new InternalEventListener[listeners.size()]);
- if (changeLog == null) {
- for (int i = 0; i < lstnrs.length; i++) {
- lstnrs[i].onEvent(new EventIteratorImpl(eventList), isLocal);
- }
- } else {
- for (int i = 0; i < lstnrs.length; i++) {
- lstnrs[i].onEvent(new EventIteratorImpl(eventList), changeLog);
+ 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);
+ }
}
}
}
@@ -582,7 +584,7 @@
private final SessionInfo sessionInfo;
private Batch batch;
- private EventIterator events;
+ private EventBundle[] events;
private OperationVisitorImpl(SessionInfo sessionInfo) {
this.sessionInfo = sessionInfo;
@@ -604,7 +606,7 @@
} finally {
if (batch != null) {
events = service.submit(batch);
- onEventReceived(events, true, changeLog);
+ onEventReceived(events, changeLog);
// reset batch field
batch = null;
}
@@ -625,7 +627,7 @@
// 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, true, null);
+ onEventReceived(events, null);
}
}
}
@@ -782,8 +784,20 @@
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());
- // todo: improve.... inform operation about modified items (build mergefailed iterator)
- operation.getEventListener().onEvent(events, true);
+ 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);
+ }
}
public void visit(ResolveMergeConflict operation) throws VersionException, InvalidItemStateException, UnsupportedRepositoryOperationException, RepositoryException {
@@ -859,14 +873,45 @@
}
}
- private static final class EventIteratorImpl extends IteratorHelper implements EventIterator {
+ /**
+ * Implements the polling for external changes on the repository service.
+ */
+ private final class ExternalChangePolling implements Runnable {
- public EventIteratorImpl(Collection c) {
- super(c);
+ /**
+ * The polling interval in milliseconds.
+ */
+ private final int pollingInterval;
+
+ /**
+ * Creates a new external change polling with a given polling interval.
+ *
+ * @param pollingInterval the interval in milliseconds.
+ */
+ private ExternalChangePolling(int pollingInterval) {
+ this.pollingInterval = pollingInterval;
}
- public Event nextEvent() {
- return (Event) next();
+ public void run() {
+ while (!Thread.interrupted()) {
+ try {
+ Thread.sleep(pollingInterval);
+ } catch (InterruptedException e) {
+ // terminate
+ break;
+ }
+ try {
+ synchronized (updateMonitor) {
+ EventBundle[] bundles = service.getEvents(sessionInfo, 0);
+ if (bundles.length > 0) {
+ onEventReceived(bundles, null);
+ }
+ }
+ } catch (RepositoryException e) {
+ log.warn("Exception while retrieving event bundles: " + e);
+ log.debug("Dump:", e);
+ }
+ }
}
}
}
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=468388&r1=468387&r2=468388
==============================================================================
--- 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 Fri Oct 27 07:16:13 2006
@@ -31,6 +31,7 @@
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.slf4j.LoggerFactory;
import org.slf4j.Logger;
@@ -261,7 +262,7 @@
// remove any session scoped locks:
NodeState[] lhStates = (NodeState[]) lockMap.keySet().toArray(new NodeState[lockMap.size()]);
for (int i = 0; i < lhStates.length; i++) {
- NodeState nState = (NodeState) lhStates[i];
+ NodeState nState = lhStates[i];
LockImpl l = (LockImpl) lockMap.get(nState);
if (l.isSessionScoped()) {
try {
@@ -531,7 +532,7 @@
}
//------------------------------------------< InternalEventListener >---
- public void onEvent(EventIterator events, boolean isLocal) {
+ public void onEvent(EventBundle events) {
if (!isLive) {
// since we only monitor the removal of the lock (by means
// of deletion of the jcr:lockIsDeep property, we are not interested
@@ -539,8 +540,8 @@
return;
}
- while (events.hasNext()) {
- Event ev = events.nextEvent();
+ for (EventIterator it = events.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
@@ -557,7 +558,7 @@
}
}
- public void onEvent(EventIterator events, ChangeLog changeLog) {
+ public void onEvent(EventBundle events, ChangeLog changeLog) {
// nothing to do. not interested in transient modifications
}
}
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=468388&r1=468387&r2=468388
==============================================================================
--- 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 Fri Oct 27 07:16:13 2006
@@ -18,6 +18,7 @@
import org.slf4j.LoggerFactory;
import org.slf4j.Logger;
+import org.apache.jackrabbit.spi.EventBundle;
import javax.jcr.RepositoryException;
import javax.jcr.observation.Event;
@@ -25,7 +26,6 @@
import java.util.Iterator;
import java.util.NoSuchElementException;
-import java.util.Collection;
/**
*/
@@ -65,17 +65,15 @@
/**
* Creates a new <code>FilteredEventIterator</code>.
*
- * @param c an unmodifiable Collection of {@link org.apache.jackrabbit.spi.Event}s.
+ * @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 isLocal if <code>true</code> these are local events.
*/
- public FilteredEventIterator(Collection c,
- EventFilter filter,
- boolean isLocal) {
- actualEvents = c.iterator();
+ public FilteredEventIterator(EventBundle events,
+ EventFilter filter) {
+ actualEvents = events.getEvents();
this.filter = filter;
- this.isLocal = isLocal;
+ this.isLocal = events.isLocal();
fetchNext();
}
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=468388&r1=468387&r2=468388
==============================================================================
--- 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 Fri Oct 27 07:16:13 2006
@@ -16,13 +16,12 @@
*/
package org.apache.jackrabbit.jcr2spi.observation;
-import org.apache.jackrabbit.spi.EventIterator;
+import org.apache.jackrabbit.spi.EventBundle;
import org.apache.jackrabbit.jcr2spi.state.ChangeLog;
/**
- * <code>InternalEventListener</code> is similar to {@link org.apache.jackrabbit.spi.EventListener}
- * but adds information about the location of the events. Whether they are local
- * or external.
+ * <code>InternalEventListener</code> receives changes as a result of a local
+ * or an external modification.
*/
public interface InternalEventListener {
@@ -30,9 +29,8 @@
* Gets called when an event occurs.
*
* @param events the event set received.
- * @param isLocal <code>true</code> if these are local changes.
*/
- public void onEvent(EventIterator events, boolean isLocal);
+ public void onEvent(EventBundle events);
- public void onEvent(EventIterator events, ChangeLog changeLog);
+ public void onEvent(EventBundle events, ChangeLog changeLog);
}
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=468388&r1=468387&r2=468388
==============================================================================
--- 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 Fri Oct 27 07:16:13 2006
@@ -25,7 +25,7 @@
import org.apache.jackrabbit.name.Path;
import org.apache.jackrabbit.name.PathFormat;
import org.apache.jackrabbit.name.QName;
-import org.apache.jackrabbit.spi.EventIterator;
+import org.apache.jackrabbit.spi.EventBundle;
import org.apache.jackrabbit.util.IteratorHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -34,12 +34,9 @@
import javax.jcr.observation.EventListener;
import javax.jcr.observation.EventListenerIterator;
import javax.jcr.observation.ObservationManager;
-import java.util.ArrayList;
import java.util.Collection;
-import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
-import java.util.List;
import java.util.Map;
/**
@@ -152,16 +149,7 @@
//-----------------------< InternalEventListener >--------------------------
- public void onEvent(EventIterator events, boolean isLocal) {
- List eventList = new ArrayList();
- while (events.hasNext()) {
- eventList.add(events.nextEvent());
- }
- if (eventList.isEmpty()) {
- return;
- }
- eventList = Collections.unmodifiableList(eventList);
-
+ public void onEvent(EventBundle events) {
// get active listeners
Map activeListeners;
synchronized (subscriptions) {
@@ -171,7 +159,7 @@
for (Iterator it = activeListeners.keySet().iterator(); it.hasNext(); ) {
EventListener listener = (EventListener) it.next();
EventFilter filter = (EventFilter) activeListeners.get(listener);
- FilteredEventIterator eventIter = new FilteredEventIterator(eventList, filter, isLocal);
+ FilteredEventIterator eventIter = new FilteredEventIterator(events, filter);
if (eventIter.hasNext()) {
try {
listener.onEvent(eventIter);
@@ -185,14 +173,14 @@
}
/**
- * Same as {@link #onEvent(EventIterator, boolean)} with the boolean flag
- * set to <code>true</code>.
+ * Same as {@link #onEvent(EventBundle)} but only used for local changes
+ * with a <code>ChangeLog</code>.
*
* @param events
* @param changeLog
*/
- public void onEvent(EventIterator events, ChangeLog changeLog) {
- onEvent(events, true);
+ public void onEvent(EventBundle events, ChangeLog changeLog) {
+ onEvent(events);
}
//-------------------------< internal >-------------------------------------
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=468388&r1=468387&r2=468388
==============================================================================
--- 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 Fri Oct 27 07:16:13 2006
@@ -20,6 +20,7 @@
import org.apache.jackrabbit.spi.EventIterator;
import org.apache.jackrabbit.spi.IdFactory;
import org.apache.jackrabbit.spi.Event;
+import org.apache.jackrabbit.spi.EventBundle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -51,10 +52,9 @@
* might have invoked changes (autocreated items etc.).
*
* @param events
- * @param isLocal
*/
- public void onEvent(EventIterator events, boolean isLocal) {
- pushEvents(getEventCollection(events));
+ public void onEvent(EventBundle events) {
+ pushEvents(getEventCollection(events.getEvents()));
}
/**
@@ -62,11 +62,11 @@
* @param events
* @param changeLog
*/
- public void onEvent(EventIterator events, ChangeLog changeLog) {
+ public void onEvent(EventBundle events, ChangeLog changeLog) {
if (changeLog == null) {
throw new IllegalArgumentException("ChangeLog must not be null.");
}
- Collection evs = getEventCollection(events);
+ Collection evs = getEventCollection(events.getEvents());
// 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
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=468388&r1=468387&r2=468388
==============================================================================
--- 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 Fri Oct 27 07:16:13 2006
@@ -42,6 +42,7 @@
import org.apache.jackrabbit.name.Path;
import org.apache.jackrabbit.spi.EventIterator;
import org.apache.jackrabbit.spi.Event;
+import org.apache.jackrabbit.spi.EventBundle;
import java.util.Collection;
import java.util.List;
@@ -158,17 +159,18 @@
// TODO find better solution to build the mergeFailed-collection
final List failedIds = new ArrayList();
InternalEventListener mergeFailedCollector = new InternalEventListener() {
- public void onEvent(EventIterator events, boolean isLocal) {
- if (isLocal) {
- while (events.hasNext()) {
- Event ev = events.nextEvent();
+ public void onEvent(EventBundle events) {
+ if (events.isLocal()) {
+ EventIterator it = events.getEvents();
+ while (it.hasNext()) {
+ Event ev = it.nextEvent();
if (ev.getType() == Event.PROPERTY_ADDED && QName.JCR_MERGEFAILED.equals(ev.getQPath().getNameElement().getName())) {
failedIds.add(ev.getParentId());
}
}
}
}
- public void onEvent(EventIterator events, ChangeLog changeLog) {
+ public void onEvent(EventBundle events, ChangeLog changeLog) {
// nothing to do. we are not interested in transient modifications
}
};
Modified: jackrabbit/trunk/contrib/spi/spi/project.properties
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/spi/project.properties?view=diff&rev=468388&r1=468387&r2=468388
==============================================================================
--- jackrabbit/trunk/contrib/spi/spi/project.properties (original)
+++ jackrabbit/trunk/contrib/spi/spi/project.properties Fri Oct 27 07:16:13 2006
@@ -1,2 +1,2 @@
-maven.javadoc.links=http://java.sun.com/j2se/1.4.2/docs/api/,http://www.day.com/maven/jsr170/javadocs/jcr-0.16.1-pfd/
+maven.javadoc.links=http://java.sun.com/j2se/1.4.2/docs/api/,http://www.day.com/maven/jsr170/javadocs/jcr-1.0/
maven.repo.remote = http://www.ibiblio.org/maven/,http://www.day.com/maven/
Modified: jackrabbit/trunk/contrib/spi/spi/project.xml
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/spi/project.xml?view=diff&rev=468388&r1=468387&r2=468388
==============================================================================
--- jackrabbit/trunk/contrib/spi/spi/project.xml (original)
+++ jackrabbit/trunk/contrib/spi/spi/project.xml Fri Oct 27 07:16:13 2006
@@ -22,7 +22,7 @@
<extend>${basedir}/../project.xml</extend>
<artifactId>jackrabbit-spi</artifactId>
<name>Service Provider Interface (SPI)</name>
- <package>org.apache.jackrabbit.spi.*</package>
+ <package>org.apache.jackrabbit.spi</package>
<!-- ====================================================================== -->
<!-- D E P E N D E N C I E S -->
Added: jackrabbit/trunk/contrib/spi/spi/src/main/java/org/apache/jackrabbit/spi/EventBundle.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/spi/src/main/java/org/apache/jackrabbit/spi/EventBundle.java?view=auto&rev=468388
==============================================================================
--- jackrabbit/trunk/contrib/spi/spi/src/main/java/org/apache/jackrabbit/spi/EventBundle.java (added)
+++ jackrabbit/trunk/contrib/spi/spi/src/main/java/org/apache/jackrabbit/spi/EventBundle.java Fri Oct 27 07:16:13 2006
@@ -0,0 +1,51 @@
+/*
+ * 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;
+
+/**
+ * An <code>EventBundle</code> is similar to the
+ * {@link javax.jcr.observation.EventIterator} interface. Other than the
+ * <code>EventIterator</code> an <code>EventBundle</code> allows to retrieve
+ * the events multiple times using the {@link #getEvents} method.
+ */
+public interface EventBundle {
+
+ /**
+ * Returns the events of this bundle.
+ *
+ * @return the events of this bundle.
+ */
+ public EventIterator getEvents();
+
+ /**
+ * Returns the identifier for this <code>EventBundle</code>.
+ *
+ * @return the identifier for this <code>EventBundle</code>.
+ */
+ public String getBundleId();
+
+ /**
+ * Returns <code>true</code> if this event bundle is associated with a
+ * change that was initiated by a local session info. Event bundles for
+ * external changes will aways return <code>false</code>.
+ *
+ * @return <code>true</code> if this event bundle is associated with a local
+ * change, <code>false</code> if this event bundle contains external
+ * changes.
+ */
+ public boolean isLocal();
+}
Propchange: jackrabbit/trunk/contrib/spi/spi/src/main/java/org/apache/jackrabbit/spi/EventBundle.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=468388&r1=468387&r2=468388
==============================================================================
--- 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 Fri Oct 27 07:16:13 2006
@@ -212,7 +212,7 @@
* Completes the this Batch or discard all the previous modifications.
*
* @param batch
- * @return EventIterator
+ * @return EventBundle
* @throws PathNotFoundException
* @throws ItemNotFoundException
* @throws NoSuchNodeTypeException
@@ -224,7 +224,7 @@
* @throws UnsupportedRepositoryOperationException
* @throws RepositoryException
*/
- public EventIterator submit(Batch batch) throws PathNotFoundException, ItemNotFoundException, NoSuchNodeTypeException, ValueFormatException, VersionException, LockException, ConstraintViolationException, AccessDeniedException, UnsupportedRepositoryOperationException, RepositoryException;
+ public EventBundle[] submit(Batch batch) throws PathNotFoundException, ItemNotFoundException, NoSuchNodeTypeException, ValueFormatException, VersionException, LockException, ConstraintViolationException, AccessDeniedException, UnsupportedRepositoryOperationException, RepositoryException;
//-------------------------------------------------------------< Import >---
/**
@@ -244,7 +244,7 @@
* @throws RepositoryException
* @see javax.jcr.Workspace#importXML(String, java.io.InputStream, int)
*/
- public EventIterator importXml(SessionInfo sessionInfo, NodeId parentId, InputStream xmlStream, int uuidBehaviour) throws ItemExistsException, PathNotFoundException, VersionException, ConstraintViolationException, LockException, AccessDeniedException, UnsupportedRepositoryOperationException, RepositoryException;
+ public EventBundle[] importXml(SessionInfo sessionInfo, NodeId parentId, InputStream xmlStream, int uuidBehaviour) throws ItemExistsException, PathNotFoundException, VersionException, ConstraintViolationException, LockException, AccessDeniedException, UnsupportedRepositoryOperationException, RepositoryException;
//---------------------------------------------------------< Copy, Move >---
/**
@@ -262,7 +262,7 @@
* @throws javax.jcr.RepositoryException
* @see javax.jcr.Workspace#move(String, String)
*/
- public EventIterator move(SessionInfo sessionInfo, NodeId srcNodeId, NodeId destParentNodeId, QName destName) throws ItemExistsException, PathNotFoundException, VersionException, ConstraintViolationException, LockException, AccessDeniedException, UnsupportedRepositoryOperationException, RepositoryException;
+ public EventBundle[] move(SessionInfo sessionInfo, NodeId srcNodeId, NodeId destParentNodeId, QName destName) throws ItemExistsException, PathNotFoundException, VersionException, ConstraintViolationException, LockException, AccessDeniedException, UnsupportedRepositoryOperationException, RepositoryException;
/**
* @param sessionInfo
@@ -282,7 +282,7 @@
* @see javax.jcr.Workspace#copy(String, String)
* @see javax.jcr.Workspace#copy(String, String, String)
*/
- public EventIterator copy(SessionInfo sessionInfo, String srcWorkspaceName, NodeId srcNodeId, NodeId destParentNodeId, QName destName) throws NoSuchWorkspaceException, ConstraintViolationException, VersionException, AccessDeniedException, PathNotFoundException, ItemExistsException, LockException, UnsupportedRepositoryOperationException, RepositoryException;
+ public EventBundle[] 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 +296,7 @@
* @throws javax.jcr.RepositoryException
* @see javax.jcr.Node#update(String)
*/
- public EventIterator update(SessionInfo sessionInfo, NodeId nodeId, String srcWorkspaceName) throws NoSuchWorkspaceException, AccessDeniedException, LockException, InvalidItemStateException, RepositoryException;
+ public EventBundle[] update(SessionInfo sessionInfo, NodeId nodeId, String srcWorkspaceName) throws NoSuchWorkspaceException, AccessDeniedException, LockException, InvalidItemStateException, RepositoryException;
/**
* @param sessionInfo
@@ -316,7 +316,7 @@
* @throws javax.jcr.RepositoryException
* @see javax.jcr.Workspace#clone(String, String, String, boolean)
*/
- public EventIterator clone(SessionInfo sessionInfo, String srcWorkspaceName, NodeId srcNodeId, NodeId destParentNodeId, QName destName, boolean removeExisting) throws NoSuchWorkspaceException, ConstraintViolationException, VersionException, AccessDeniedException, PathNotFoundException, ItemExistsException, LockException, UnsupportedRepositoryOperationException, RepositoryException;
+ 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;
//------------------------------------------------------------< Locking >---
@@ -344,7 +344,7 @@
* @throws javax.jcr.RepositoryException
* @see javax.jcr.Node#lock(boolean, boolean)
*/
- public EventIterator lock(SessionInfo sessionInfo, NodeId nodeId, boolean deep, boolean sessionScoped) throws UnsupportedRepositoryOperationException, LockException, AccessDeniedException, InvalidItemStateException, RepositoryException;
+ public EventBundle[] 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 +356,7 @@
* @throws javax.jcr.RepositoryException
* @see javax.jcr.lock.Lock#refresh()
*/
- public EventIterator refreshLock(SessionInfo sessionInfo, NodeId nodeId) throws LockException, RepositoryException;
+ public EventBundle[] refreshLock(SessionInfo sessionInfo, NodeId nodeId) throws LockException, RepositoryException;
/**
* Releases the lock on the given node.<p/>
@@ -372,7 +372,7 @@
* @throws javax.jcr.RepositoryException
* @see javax.jcr.Node#unlock()
*/
- public EventIterator unlock(SessionInfo sessionInfo, NodeId nodeId) throws UnsupportedRepositoryOperationException, LockException, AccessDeniedException, InvalidItemStateException, RepositoryException;
+ public EventBundle[] unlock(SessionInfo sessionInfo, NodeId nodeId) throws UnsupportedRepositoryOperationException, LockException, AccessDeniedException, InvalidItemStateException, RepositoryException;
//---------------------------------------------------------< Versioning >---
/**
@@ -385,7 +385,7 @@
* @throws javax.jcr.RepositoryException
* @see javax.jcr.Node#checkin()
*/
- public EventIterator checkin(SessionInfo sessionInfo, NodeId nodeId) throws VersionException, UnsupportedRepositoryOperationException, InvalidItemStateException, LockException, RepositoryException;
+ public EventBundle[] checkin(SessionInfo sessionInfo, NodeId nodeId) throws VersionException, UnsupportedRepositoryOperationException, InvalidItemStateException, LockException, RepositoryException;
/**
* @param sessionInfo
@@ -395,7 +395,7 @@
* @throws javax.jcr.RepositoryException
* @see javax.jcr.Node#checkout()
*/
- public EventIterator checkout(SessionInfo sessionInfo, NodeId nodeId) throws UnsupportedRepositoryOperationException, LockException, RepositoryException;
+ public EventBundle[] checkout(SessionInfo sessionInfo, NodeId nodeId) throws UnsupportedRepositoryOperationException, LockException, RepositoryException;
/**
* @param sessionInfo
@@ -414,7 +414,7 @@
* @see javax.jcr.Node#restore(javax.jcr.version.Version, String, boolean)
* @see javax.jcr.Node#restoreByLabel(String, boolean)
*/
- public EventIterator restore(SessionInfo sessionInfo, NodeId nodeId, NodeId versionId, boolean removeExisting) throws VersionException, PathNotFoundException, ItemExistsException, UnsupportedRepositoryOperationException, LockException, InvalidItemStateException, RepositoryException;
+ public EventBundle[] restore(SessionInfo sessionInfo, NodeId nodeId, NodeId versionId, boolean removeExisting) throws VersionException, PathNotFoundException, ItemExistsException, UnsupportedRepositoryOperationException, LockException, InvalidItemStateException, RepositoryException;
/**
* @param sessionInfo
@@ -428,7 +428,7 @@
* @throws javax.jcr.RepositoryException
* @see javax.jcr.Workspace#restore(javax.jcr.version.Version[], boolean)
*/
- public EventIterator restore(SessionInfo sessionInfo, NodeId[] versionIds, boolean removeExisting) throws ItemExistsException, UnsupportedRepositoryOperationException, VersionException, LockException, InvalidItemStateException, RepositoryException;
+ public EventBundle[] restore(SessionInfo sessionInfo, NodeId[] versionIds, boolean removeExisting) throws ItemExistsException, UnsupportedRepositoryOperationException, VersionException, LockException, InvalidItemStateException, RepositoryException;
/**
* @param sessionInfo
@@ -443,7 +443,7 @@
* @throws javax.jcr.RepositoryException
* @see javax.jcr.Node#merge(String, boolean)
*/
- public EventIterator merge(SessionInfo sessionInfo, NodeId nodeId, String srcWorkspaceName, boolean bestEffort) throws NoSuchWorkspaceException, AccessDeniedException, MergeException, LockException, InvalidItemStateException, RepositoryException;
+ public EventBundle[] merge(SessionInfo sessionInfo, NodeId nodeId, String srcWorkspaceName, boolean bestEffort) throws NoSuchWorkspaceException, AccessDeniedException, MergeException, LockException, InvalidItemStateException, RepositoryException;
/**
* @param sessionInfo
@@ -461,7 +461,7 @@
* @see javax.jcr.Node#cancelMerge(javax.jcr.version.Version)
* @see javax.jcr.Node#doneMerge(javax.jcr.version.Version)
*/
- public EventIterator resolveMergeConflict(SessionInfo sessionInfo, NodeId nodeId, NodeId[] mergeFailedIds, NodeId[] predecessorIds) throws VersionException, InvalidItemStateException, UnsupportedRepositoryOperationException, RepositoryException;
+ public EventBundle[] resolveMergeConflict(SessionInfo sessionInfo, NodeId nodeId, NodeId[] mergeFailedIds, NodeId[] predecessorIds) throws VersionException, InvalidItemStateException, UnsupportedRepositoryOperationException, RepositoryException;
/**
* @param sessionInfo
@@ -472,7 +472,7 @@
* @throws javax.jcr.RepositoryException
* @see javax.jcr.version.VersionHistory#addVersionLabel(String, String, boolean)
*/
- public EventIterator addVersionLabel(SessionInfo sessionInfo, NodeId versionHistoryId, NodeId versionId, QName label, boolean moveLabel) throws VersionException, RepositoryException;
+ public EventBundle[] addVersionLabel(SessionInfo sessionInfo, NodeId versionHistoryId, NodeId versionId, QName label, boolean moveLabel) throws VersionException, RepositoryException;
/**
* @param sessionInfo
@@ -483,7 +483,7 @@
* @throws javax.jcr.RepositoryException
* @see javax.jcr.version.VersionHistory#removeVersionLabel(String)
*/
- public EventIterator removeVersionLabel(SessionInfo sessionInfo, NodeId versionHistoryId, NodeId versionId, QName label) throws VersionException, RepositoryException;
+ public EventBundle[] removeVersionLabel(SessionInfo sessionInfo, NodeId versionHistoryId, NodeId versionId, QName label) throws VersionException, RepositoryException;
//----------------------------------------------------------< Searching >---
/**
@@ -507,41 +507,31 @@
//--------------------------------------------------------< Observation >---
/**
- * Registers a listener to receive events about changes that were applied
- * by other sessions. In contrast to {@link javax.jcr.observation.ObservationManager#addEventListener)}
- * this method does not have a <code>noLocal</code> flag.
- * </p>
- * The implementation must ensure that {@link EventIterator}s issued to
- * potential listeners and the ones returned by the individual methods
- * are in a proper sequence.
+ * 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.
*
- * @param sessionInfo
- * @param nodeId
- * @param listener
- * @param eventTypes
- * @param isDeep
- * @param uuid
- * @param nodeTypeIds
- * @throws javax.jcr.RepositoryException
- * @see javax.jcr.observation.ObservationManager#addEventListener(javax.jcr.observation.EventListener, int, String, boolean, String[], String[], boolean)
- */
- public void addEventListener(SessionInfo sessionInfo, NodeId nodeId, EventListener listener, int eventTypes, boolean isDeep, String[] uuid, QName[] nodeTypeIds) throws RepositoryException;
-
- /**
- * Removes the registration of the specified <code>EventListener</code>. If
- * the event listener was not registered for the node indentified by <code>nodeId</code>
- * an <code>RepositoryException</code> is thrown. The same applies if the
- * registration timeouted before or an other error occurs.<p/>
- * Please note, that all eventlistener registrations must be removed upon
- * {@link javax.jcr.Session#logout()} logout) of the <code>Session</code>.
- *
- * @param sessionInfo
- * @param nodeId
- * @param listener
- * @throws javax.jcr.RepositoryException
- * @see javax.jcr.observation.ObservationManager#removeEventListener(javax.jcr.observation.EventListener)
+ * @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.
+ * @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 UnsupportedRepositoryOperationException
+ * if this implementation does not support
+ * observation.
*/
- public void removeEventListener(SessionInfo sessionInfo, NodeId nodeId, EventListener listener) throws RepositoryException;
+ public EventBundle[] getEvents(SessionInfo sessionInfo, long timeout)
+ throws RepositoryException, UnsupportedRepositoryOperationException;
//---------------------------------------------------------< 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=468388&r1=468387&r2=468388
==============================================================================
--- 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 Fri Oct 27 07:16:13 2006
@@ -17,6 +17,11 @@
package org.apache.jackrabbit.spi;
/**
+ * TODO: implement as bean and instanticate on client?
+ * TODO: use credentials instead of UserID?
+ * TODO: add name/value parameter facility
+ * TODO: server returns set of name/value pairs which should be set by the client?
+ *
* <code>SessionInfo</code>...
*/
public interface SessionInfo {
@@ -30,4 +35,32 @@
public void addLockToken(String lockToken);
public void removeLockToken(String lockToken);
+
+ /**
+ * Returns the identifier of the last {@link EventBundle} delivered using
+ * this <code>SessionInfo</code>. When a <code>SessionInfo</code> is
+ * initially aquired the returned event identifier is set to the last
+ * <code>EventBundle</code> created by the SPI implementation previously to
+ * the call to {@link RepositoryService#obtain(javax.jcr.Credentials, String)
+ * RepositoryService.obtain()}. If there was no previous event <code>null</code>
+ * is returned. Thus a <code>null</code> value will effectively return all
+ * events that occurred since the start of the SPI server.
+ * <p/>
+ * For implementations, that do not support observation this method will
+ * always return <code>null</code>.
+ *
+ * @return the identifier of the last {@link EventBundle} delivered using
+ * this <code>SessionInfo</code>.
+ */
+ public String getLastEventBundleId();
+
+ /**
+ * 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)}.
+ *
+ * @param eventBundleId the identifier of the last {@link EventBundle}
+ * delivered using this <code>SessionInfo</code>.
+ */
+ public void setLastEventBundleId(String eventBundleId);
}
Added: 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=auto&rev=468388
==============================================================================
--- jackrabbit/trunk/contrib/spi/spi/src/main/java/org/apache/jackrabbit/spi/package.html (added)
+++ jackrabbit/trunk/contrib/spi/spi/src/main/java/org/apache/jackrabbit/spi/package.html Fri Oct 27 07:16:13 2006
@@ -0,0 +1,63 @@
+<!--
+ 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.
+-->
+<body>
+Defines the interfaces of the JCR SPI (Service Provider Interface).
+<p/>
+The SPI cuts the JCR stack into two parts:
+<ul>
+<li>Above the SPI an implementation that whishes to expose the JCR API again
+needs to implement the transient item space, the session local namespace mapping
+and various conversions from the fully qualified values present in the SPI to
+the resolved values in the JCR API.</li>
+<li>An implementation of the SPI interfaces has to deal with the persistent
+view of a JCR repository. This includes almost all aspects of the JSR 170
+specification, except the previously stated transient space and the session
+local namespace resolution to prefixes.</li>
+</ul>
+
+<h3>Observation</h3>
+Because one of the goals of this SPI is to make it easier to implement a
+remoting layer using various existing protocols, the observation mechanism has
+been design with this goal in mind. Instead of a listener registration with
+a callback for each event bundle, the SPI uses a polling mechanism with a
+timeout: {@link org.apache.jackrabbit.spi.RepositoryService#getEvents
+RepositoryService.getEvents()}. With every call to this method the repository
+is advised to return the events that occurred since the last call. As a
+reference to the last retrieved {@link org.apache.jackrabbit.spi.EventBundle}
+the {@link org.apache.jackrabbit.spi.SessionInfo} contains a bundle identifier
+which is automatically updated on each call to <code>RepositoryService.getEvents()</code>.
+While this design allows for a polling implementation on top of the SPI it is
+also well suited for a listener based observation implementation on top of the
+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.
+</body>
\ No newline at end of file
Propchange: jackrabbit/trunk/contrib/spi/spi/src/main/java/org/apache/jackrabbit/spi/package.html
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/EventBundleImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/EventBundleImpl.java?view=auto&rev=468388
==============================================================================
--- jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/EventBundleImpl.java (added)
+++ jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/EventBundleImpl.java Fri Oct 27 07:16:13 2006
@@ -0,0 +1,89 @@
+/*
+ * 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.EventBundle;
+import org.apache.jackrabbit.spi.EventIterator;
+import org.apache.jackrabbit.spi.SessionInfo;
+import org.apache.jackrabbit.webdav.xml.DomUtil;
+import org.apache.jackrabbit.webdav.observation.ObservationConstants;
+import org.w3c.dom.Element;
+
+/**
+ * <code>EventBundleImpl</code> implements a bundle of events. The individual
+ * events can be retrieved when calling {@link #getEvents()}.
+ */
+class EventBundleImpl implements EventBundle, ObservationConstants {
+
+ static final EventBundle EMPTY = new EventBundleImpl(null, null, null) {
+ public EventIterator getEvents() {
+ return IteratorHelper.EMPTY;
+ }
+ };
+
+ private final Element eventBundleElement;
+
+ private final URIResolver uriResolver;
+
+ private final SessionInfo sessionInfo;
+
+ private final boolean isLocal;
+
+ /**
+ * Creates a new event bundle.
+ *
+ * @param eventBundleElement
+ * @param uriResolver
+ * @param sessionInfo
+ */
+ EventBundleImpl(Element eventBundleElement,
+ URIResolver uriResolver,
+ SessionInfo sessionInfo) {
+ this.eventBundleElement = eventBundleElement;
+ this.uriResolver = uriResolver;
+ this.sessionInfo = sessionInfo;
+ String value = null;
+ if (eventBundleElement != null) {
+ value = DomUtil.getAttribute(eventBundleElement,
+ XML_EVENT_IS_LOCAL, NAMESPACE);
+ }
+ this.isLocal = (value != null) ? Boolean.valueOf(value).booleanValue() : false;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public EventIterator getEvents() {
+ return new EventIteratorImpl(eventBundleElement, uriResolver, sessionInfo);
+ }
+
+ /**
+ * @inheritDoc
+ * <p/>
+ * TODO implement
+ */
+ public String getBundleId() {
+ return null;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public boolean isLocal() {
+ return isLocal;
+ }
+}
Propchange: jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/EventBundleImpl.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/EventIteratorImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/EventIteratorImpl.java?view=diff&rev=468388&r1=468387&r2=468388
==============================================================================
--- jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/EventIteratorImpl.java (original)
+++ jackrabbit/trunk/contrib/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/EventIteratorImpl.java Fri Oct 27 07:16:13 2006
@@ -38,18 +38,16 @@
private final SessionInfo sessionInfo;
private final URIResolver uriResolver;
- private ElementIterator bundleIterator;
private ElementIterator eventElementIterator;
private Event next;
private long pos;
- public EventIteratorImpl(Element eventDiscoveryElem, URIResolver uriResolver, SessionInfo sessionInfo) {
+ public EventIteratorImpl(Element eventBundleElement, URIResolver uriResolver, SessionInfo sessionInfo) {
this.sessionInfo = sessionInfo;
this.uriResolver = uriResolver;
- bundleIterator = DomUtil.getChildren(eventDiscoveryElem, ObservationConstants.XML_EVENTBUNDLE, ObservationConstants.NAMESPACE);;
- retrieveNextEventIterator();
+ this.eventElementIterator = DomUtil.getChildren(eventBundleElement, ObservationConstants.XML_EVENT, ObservationConstants.NAMESPACE);
retrieveNextEvent();
}
@@ -103,18 +101,6 @@
log.error("Unexpected error while creating event.", e);
}
}
-
- if (!eventElementIterator.hasNext()) {
- retrieveNextEventIterator();
- }
- }
- }
-
- private void retrieveNextEventIterator() {
- eventElementIterator = null;
- if (bundleIterator.hasNext()) {
- Element bundleElem = bundleIterator.nextElement();
- eventElementIterator = DomUtil.getChildren(bundleElem, ObservationConstants.XML_EVENT, ObservationConstants.NAMESPACE);
}
}
}