Author: mreutegg
Date: Fri Jul 3 08:39:57 2009
New Revision: 790826
URL: http://svn.apache.org/viewvc?rev=790826&view=rev
Log:
JCR-2108: JSR 283 Observation
Added:
jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/EventJournalImpl.java (with props)
jackrabbit/trunk/jackrabbit-spi2jcr/src/main/java/org/apache/jackrabbit/spi2jcr/EventFactory.java (with props)
jackrabbit/trunk/jackrabbit-spi2jcr/src/test/resources/repository.xml (with props)
Modified:
jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceManager.java
jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/HierarchyEventListener.java
jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/FilteredEventIterator.java
jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/InternalEventListener.java
jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/ObservationManagerImpl.java
jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/AbstractReadableRepositoryService.java
jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/EventBundleImpl.java
jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/logging/RepositoryServiceLogger.java
jackrabbit/trunk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/EventBundle.java
jackrabbit/trunk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/RepositoryService.java
jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/RepositoryServiceImpl.java
jackrabbit/trunk/jackrabbit-spi2jcr/pom.xml
jackrabbit/trunk/jackrabbit-spi2jcr/src/main/java/org/apache/jackrabbit/spi2jcr/EventSubscription.java
jackrabbit/trunk/jackrabbit-spi2jcr/src/main/java/org/apache/jackrabbit/spi2jcr/RepositoryServiceImpl.java
jackrabbit/trunk/jackrabbit-spi2jcr/src/test/resources/repositoryStubImpl.properties
Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceManager.java?rev=790826&r1=790825&r2=790826&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceManager.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceManager.java Fri Jul 3 08:39:57 2009
@@ -395,6 +395,22 @@
}
/**
+ * Returns the events from the journal that occurred after a given date.
+ *
+ * @param filter the event filter to apply.
+ * @param after a date in milliseconds.
+ * @return the events as a bundle.
+ * @throws RepositoryException if an error occurs.
+ * @throws UnsupportedRepositoryOperationException
+ * if the implementation does not support
+ * journaled observation.
+ */
+ public EventBundle getEvents(EventFilter filter, long after)
+ throws RepositoryException, UnsupportedRepositoryOperationException {
+ return service.getEvents(sessionInfo, filter, after);
+ }
+
+ /**
*
* @param userData
* @throws RepositoryException
Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/HierarchyEventListener.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/HierarchyEventListener.java?rev=790826&r1=790825&r2=790826&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/HierarchyEventListener.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/HierarchyEventListener.java Fri Jul 3 08:39:57 2009
@@ -26,6 +26,7 @@
import org.apache.jackrabbit.spi.EventBundle;
import org.apache.jackrabbit.spi.NodeId;
import org.apache.jackrabbit.spi.Path;
+import org.apache.jackrabbit.spi.ItemId;
import javax.jcr.RepositoryException;
import java.util.Collection;
@@ -44,7 +45,7 @@
private static Logger log = LoggerFactory.getLogger(HierarchyEventListener.class);
private final HierarchyManager hierarchyMgr;
- private final Collection eventFilter;
+ private final Collection<EventFilter> eventFilter;
public HierarchyEventListener(WorkspaceManager wspManager,
HierarchyManager hierarchyMgr,
@@ -59,14 +60,18 @@
} catch (RepositoryException e) {
// spi does not support observation, or another error occurred.
}
- this.eventFilter = (filter == null) ? Collections.EMPTY_LIST : Collections.singletonList(filter);
+ if (filter == null) {
+ this.eventFilter = Collections.emptyList();
+ } else {
+ this.eventFilter = Collections.singletonList(filter);
+ }
try {
wspManager.addEventListener(this);
} catch (RepositoryException e) {
// spi does not support observation, or another error occurred.
}
} else {
- this.eventFilter = Collections.EMPTY_LIST;
+ this.eventFilter = Collections.emptyList();
}
}
@@ -74,7 +79,7 @@
/**
* @see InternalEventListener#getEventFilters()
*/
- public Collection getEventFilters() {
+ public Collection<EventFilter> getEventFilters() {
return eventFilter;
}
@@ -84,7 +89,7 @@
* since workspace operations are reported as local changes as well and
* might have invoked changes (autocreated items etc.).
*
- * @param eventBundle
+ * @param eventBundle the events.
* @see InternalEventListener#onEvent(EventBundle)
*/
public void onEvent(EventBundle eventBundle) {
@@ -99,9 +104,9 @@
* Retrieve the workspace state(s) affected by the given event and refresh
* them accordingly.
*
- * @param events
+ * @param events the events to process.
*/
- private void pushEvents(Collection events) {
+ private void pushEvents(Collection<Event> events) {
if (events.isEmpty()) {
log.debug("Empty event bundle");
return;
@@ -110,9 +115,9 @@
// TODO: handle new 283 event types and clean add/remove that is also present as move-event.
// collect set of removed node ids
- Set removedEvents = new HashSet();
+ Set<ItemId> removedEvents = new HashSet<ItemId>();
// separately collect the add events
- Set addEvents = new HashSet();
+ Set<Event> addEvents = new HashSet<Event>();
for (Iterator it = events.iterator(); it.hasNext();) {
Event event = (Event) it.next();
@@ -170,8 +175,7 @@
}
/* process all other events (removal, property changed) */
- for (Iterator it = events.iterator(); it.hasNext(); ) {
- Event event = (Event) it.next();
+ for (Event event : events) {
int type = event.getType();
NodeId parentId = event.getParentId();
@@ -211,9 +215,9 @@
}
}
- private static Collection getEventCollection(EventBundle eventBundle) {
- List evs = new ArrayList();
- for (Iterator it = eventBundle.getEvents(); it.hasNext();) {
+ private static Collection<Event> getEventCollection(EventBundle eventBundle) {
+ List<Event> evs = new ArrayList<Event>();
+ for (Iterator<Event> it = eventBundle.getEvents(); it.hasNext();) {
evs.add(it.next());
}
return evs;
Added: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/EventJournalImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/EventJournalImpl.java?rev=790826&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/EventJournalImpl.java (added)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/EventJournalImpl.java Fri Jul 3 08:39:57 2009
@@ -0,0 +1,169 @@
+/*
+ * 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.jcr2spi.observation;
+
+import java.util.List;
+import java.util.LinkedList;
+import java.util.NoSuchElementException;
+
+import javax.jcr.observation.EventJournal;
+import javax.jcr.RepositoryException;
+
+import org.apache.jackrabbit.spi.Event;
+import org.apache.jackrabbit.spi.EventFilter;
+import org.apache.jackrabbit.spi.EventBundle;
+import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
+import org.apache.jackrabbit.jcr2spi.WorkspaceManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * <code>EventJournalImpl</code> implement the JSR 283 event journal over SPI.
+ */
+public class EventJournalImpl implements EventJournal {
+
+ /**
+ * The logger instance for this class.
+ */
+ private static final Logger log = LoggerFactory.getLogger(EventJournalImpl.class);
+
+ private final WorkspaceManager wspMgr;
+
+ private final EventFilter filter;
+
+ private final NamePathResolver resolver;
+
+ private List<Event> buffer = new LinkedList<Event>();
+
+ private long lastTimestamp = 0;
+
+ /**
+ * Current position.
+ */
+ private long position = 0;
+
+ public EventJournalImpl(WorkspaceManager wspMgr,
+ EventFilter filter,
+ NamePathResolver resolver) {
+ this.wspMgr = wspMgr;
+ this.filter = filter;
+ this.resolver = resolver;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void skipTo(long date) {
+ // first try to skip in buffer
+ while (!buffer.isEmpty()) {
+ long eDate;
+ try {
+ eDate = buffer.get(0).getDate();
+ } catch (RepositoryException e) {
+ eDate = 0;
+ }
+ if (eDate <= date) {
+ buffer.remove(0);
+ } else {
+ return;
+ }
+ }
+ // if we get here then we need to refill the buffer after
+ // the given date
+ lastTimestamp = date;
+ refill();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public javax.jcr.observation.Event nextEvent() {
+ return (javax.jcr.observation.Event) next();
+ }
+
+ public long getDate() {
+ // TODO
+ throw new RuntimeException("Not implemented, see JCR-2086");
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void skip(long skipNum) {
+ while (skipNum-- > 0) {
+ next();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getSize() {
+ return -1;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getPosition() {
+ return position;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean hasNext() {
+ if (buffer.isEmpty()) {
+ refill();
+ }
+ return !buffer.isEmpty();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object next() {
+ if (hasNext()) {
+ position++;
+ return new EventImpl(buffer.remove(0),
+ resolver, wspMgr.getIdFactory());
+ } else {
+ throw new NoSuchElementException();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+
+ //----------------------------< internal >----------------------------------
+
+ private void refill() {
+ try {
+ EventBundle bundle = wspMgr.getEvents(filter, lastTimestamp);
+ for (Event e : bundle) {
+ buffer.add(e);
+ lastTimestamp = e.getDate();
+ }
+ } catch (RepositoryException e) {
+ log.warn("Exception while refilling event journal buffer", e);
+ }
+ }
+}
Propchange: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/EventJournalImpl.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/FilteredEventIterator.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/FilteredEventIterator.java?rev=790826&r1=790825&r2=790826&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/FilteredEventIterator.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/FilteredEventIterator.java Fri Jul 3 08:39:57 2009
@@ -22,27 +22,21 @@
import javax.jcr.observation.Event;
import javax.jcr.observation.EventIterator;
-import org.apache.jackrabbit.spi.EventBundle;
import org.apache.jackrabbit.spi.EventFilter;
import org.apache.jackrabbit.spi.IdFactory;
import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
/**
+ * Implements an event iterator that converts SPI events into JCR events and
+ * filters out the ones that are not accepted by an {@link EventFilter}.
*/
class FilteredEventIterator implements EventIterator {
/**
- * Logger instance for this class
- */
- private static final Logger log = LoggerFactory.getLogger(FilteredEventIterator.class);
-
- /**
* The actual {@link org.apache.jackrabbit.spi.Event}s fired by the repository service
* (unfiltered).
*/
- private final Iterator actualEvents;
+ protected final Iterator<org.apache.jackrabbit.spi.Event> actualEvents;
/**
* For filtering the {@link javax.jcr.observation.Event}s.
@@ -77,20 +71,22 @@
/**
* 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 resolver
- * @param idFactory
+ * @param events the {@link org.apache.jackrabbit.spi.Event}s as an
+ * iterator.
+ * @param isLocal whether the events were caused by the local session.
+ * @param filter only event that pass the filter will be dispatched to
+ * the event listener.
+ * @param resolver the name path resolver.
+ * @param idFactory the id factory.
*/
- public FilteredEventIterator(EventBundle events,
+ public FilteredEventIterator(Iterator<org.apache.jackrabbit.spi.Event> events,
+ boolean isLocal,
EventFilter filter,
NamePathResolver resolver,
IdFactory idFactory) {
- this.actualEvents = events.getEvents();
+ this.actualEvents = events;
this.filter = filter;
- this.isLocal = events.isLocal();
+ this.isLocal = isLocal;
this.resolver = resolver;
this.idFactory = idFactory;
fetchNext();
@@ -177,7 +173,7 @@
org.apache.jackrabbit.spi.Event event;
next = null;
while (next == null && actualEvents.hasNext()) {
- event = (org.apache.jackrabbit.spi.Event) actualEvents.next();
+ event = actualEvents.next();
next = filter.accept(event, isLocal) ? new EventImpl(event, resolver, idFactory) : null;
}
}
Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/InternalEventListener.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/InternalEventListener.java?rev=790826&r1=790825&r2=790826&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/InternalEventListener.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/InternalEventListener.java Fri Jul 3 08:39:57 2009
@@ -44,5 +44,5 @@
* @return an unmodifiable collection of {@link EventFilter}s currently
* in use by this event listener.
*/
- public Collection getEventFilters();
+ public Collection<EventFilter> getEventFilters();
}
Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/ObservationManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/ObservationManagerImpl.java?rev=790826&r1=790825&r2=790826&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/ObservationManagerImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/observation/ObservationManagerImpl.java Fri Jul 3 08:39:57 2009
@@ -19,12 +19,10 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.jcr.RepositoryException;
-import javax.jcr.UnsupportedRepositoryOperationException;
import javax.jcr.observation.EventJournal;
import javax.jcr.observation.EventListener;
import javax.jcr.observation.EventListenerIterator;
@@ -37,6 +35,7 @@
import org.apache.jackrabbit.spi.EventFilter;
import org.apache.jackrabbit.spi.Name;
import org.apache.jackrabbit.spi.Path;
+import org.apache.jackrabbit.spi.Event;
import org.apache.jackrabbit.spi.commons.conversion.NameException;
import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
import org.slf4j.Logger;
@@ -71,21 +70,22 @@
/**
* Live mapping of <code>EventListener</code> to <code>EventFilter</code>.
*/
- private final Map subscriptions = new HashMap();
+ private final Map<EventListener, EventFilter> subscriptions = new HashMap<EventListener, EventFilter>();
/**
* A read only mapping of <code>EventListener</code> to <code>EventFilter</code>.
*/
- private Map readOnlySubscriptions;
+ private Map<EventListener, EventFilter> readOnlySubscriptions;
/**
* Creates a new observation manager for <code>session</code>.
+ *
* @param wspManager the WorkspaceManager.
- * @param resolver
+ * @param resolver the name path resolver for this session.
* @param ntRegistry The <code>NodeTypeRegistry</code> of the session.
- * @param valueFactory
*/
- public ObservationManagerImpl(WorkspaceManager wspManager, NamePathResolver resolver,
+ public ObservationManagerImpl(WorkspaceManager wspManager,
+ NamePathResolver resolver,
NodeTypeRegistry ntRegistry) {
this.wspManager = wspManager;
this.resolver = resolver;
@@ -102,33 +102,8 @@
String[] uuids,
String[] nodeTypeNames,
boolean noLocal) throws RepositoryException {
- Path path;
- try {
- path = resolver.getQPath(absPath).getCanonicalPath();
- } catch (NameException e) {
- throw new RepositoryException("Malformed path: " + absPath);
- }
-
- // create NodeType instances from names
- Name[] qNodeTypeNames;
- if (nodeTypeNames == null) {
- qNodeTypeNames = null;
- } else {
- try {
- qNodeTypeNames = new Name[nodeTypeNames.length];
- for (int i = 0; i < nodeTypeNames.length; i++) {
- Name ntName = resolver.getQName(nodeTypeNames[i]);
- if (!ntRegistry.isRegistered(ntName)) {
- throw new RepositoryException("unknown node type: " + nodeTypeNames[i]);
- }
- qNodeTypeNames[i] = ntName;
- }
- } catch (NameException e) {
- throw new RepositoryException(e.getMessage());
- }
- }
-
- EventFilter filter = wspManager.createEventFilter(eventTypes, path, isDeep, uuids, qNodeTypeNames, noLocal);
+ EventFilter filter = createEventFilter(eventTypes, absPath,
+ isDeep, uuids, nodeTypeNames, noLocal);
synchronized (subscriptions) {
subscriptions.put(listener, filter);
readOnlySubscriptions = null;
@@ -173,15 +148,18 @@
* @see javax.jcr.observation.ObservationManager#getEventJournal()
*/
public EventJournal getEventJournal() throws RepositoryException {
- // TODO
- throw new UnsupportedRepositoryOperationException("JCR-2108");
+ return getEventJournal(Event.ALL_TYPES, "/", true, null, null);
}
+ /**
+ * @see javax.jcr.observation.ObservationManager#getEventJournal(int, String, boolean, String[], String[])
+ */
public EventJournal getEventJournal(
int eventTypes, String absPath, boolean isDeep,
String[] uuid, String[] nodeTypeName)
throws RepositoryException {
- throw new UnsupportedRepositoryOperationException("JCR-2108");
+ EventFilter filter = createEventFilter(eventTypes, absPath, isDeep, uuid, nodeTypeName, false);
+ return new EventJournalImpl(wspManager, filter, resolver);
}
/**
@@ -193,8 +171,8 @@
//-----------------------< InternalEventListener >--------------------------
- public Collection getEventFilters() {
- List filters = new ArrayList();
+ public Collection<EventFilter> getEventFilters() {
+ List<EventFilter> filters = new ArrayList<EventFilter>();
synchronized (subscriptions) {
ensureReadOnlyMap();
filters.addAll(readOnlySubscriptions.values());
@@ -204,16 +182,17 @@
public void onEvent(EventBundle eventBundle) {
// get active listeners
- Map activeListeners;
+ Map<EventListener, EventFilter> activeListeners;
synchronized (subscriptions) {
ensureReadOnlyMap();
activeListeners = readOnlySubscriptions;
}
- for (Iterator it = activeListeners.entrySet().iterator(); it.hasNext(); ) {
- Map.Entry entry = (Map.Entry) it.next();
- EventListener listener = (EventListener) entry.getKey();
- EventFilter filter = (EventFilter) entry.getValue();
- FilteredEventIterator eventIter = new FilteredEventIterator(eventBundle, filter, resolver, wspManager.getIdFactory());
+ for (Map.Entry<EventListener, EventFilter> entry : activeListeners.entrySet()) {
+ EventListener listener = entry.getKey();
+ EventFilter filter = entry.getValue();
+ FilteredEventIterator eventIter = new FilteredEventIterator(
+ eventBundle.getEvents(), eventBundle.isLocal(), filter,
+ resolver, wspManager.getIdFactory());
if (eventIter.hasNext()) {
try {
listener.onEvent(eventIter);
@@ -235,8 +214,58 @@
*/
private void ensureReadOnlyMap() {
if (readOnlySubscriptions == null) {
- readOnlySubscriptions = new HashMap(subscriptions);
+ readOnlySubscriptions = new HashMap<EventListener, EventFilter>(subscriptions);
}
}
+ /**
+ * Creates an SPI event filter from the given list of constraints.
+ *
+ * @param eventTypes the event types.
+ * @param absPath an absolute path.
+ * @param isDeep whether to include events for descendant items of
+ * the node at absPath.
+ * @param uuids uuid filters.
+ * @param nodeTypeNames node type filters.
+ * @param noLocal whether to exclude changes from the local session.
+ * @return the SPI event filter instance.
+ * @throws RepositoryException if an error occurs while creating the event
+ * filter.
+ */
+ private EventFilter createEventFilter(int eventTypes,
+ String absPath,
+ boolean isDeep,
+ String[] uuids,
+ String[] nodeTypeNames,
+ boolean noLocal)
+ throws RepositoryException {
+ Path path;
+ try {
+ path = resolver.getQPath(absPath).getCanonicalPath();
+ } catch (NameException e) {
+ throw new RepositoryException("Malformed path: " + absPath);
+ }
+
+ // create NodeType instances from names
+ Name[] qNodeTypeNames;
+ if (nodeTypeNames == null) {
+ qNodeTypeNames = null;
+ } else {
+ try {
+ qNodeTypeNames = new Name[nodeTypeNames.length];
+ for (int i = 0; i < nodeTypeNames.length; i++) {
+ Name ntName = resolver.getQName(nodeTypeNames[i]);
+ if (!ntRegistry.isRegistered(ntName)) {
+ throw new RepositoryException("unknown node type: " + nodeTypeNames[i]);
+ }
+ qNodeTypeNames[i] = ntName;
+ }
+ } catch (NameException e) {
+ throw new RepositoryException(e.getMessage());
+ }
+ }
+
+ return wspManager.createEventFilter(eventTypes, path, isDeep,
+ uuids, qNodeTypeNames, noLocal);
+ }
}
Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/AbstractReadableRepositoryService.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/AbstractReadableRepositoryService.java?rev=790826&r1=790825&r2=790826&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/AbstractReadableRepositoryService.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/AbstractReadableRepositoryService.java Fri Jul 3 08:39:57 2009
@@ -726,6 +726,15 @@
/**
* @throws UnsupportedRepositoryOperationException always.
*/
+ public EventBundle getEvents(SessionInfo sessionInfo, EventFilter filter,
+ long after) throws
+ RepositoryException, UnsupportedRepositoryOperationException {
+ throw new UnsupportedRepositoryOperationException();
+ }
+
+ /**
+ * @throws UnsupportedRepositoryOperationException always.
+ */
public void dispose(Subscription subscription) throws RepositoryException {
throw new UnsupportedRepositoryOperationException();
}
Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/EventBundleImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/EventBundleImpl.java?rev=790826&r1=790825&r2=790826&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/EventBundleImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/EventBundleImpl.java Fri Jul 3 08:39:57 2009
@@ -17,6 +17,7 @@
package org.apache.jackrabbit.spi.commons;
import org.apache.jackrabbit.spi.EventBundle;
+import org.apache.jackrabbit.spi.Event;
import java.io.Serializable;
import java.util.Collection;
@@ -35,7 +36,7 @@
/**
* The events in this bundle.
*/
- private final Collection events;
+ private final Collection<Event> events;
/**
* Creates a new event bundle with <code>events</code>.
@@ -43,7 +44,7 @@
* @param events the events for this bundle.
* @param isLocal if this events were created due to a local change.
*/
- public EventBundleImpl(Collection events, boolean isLocal) {
+ public EventBundleImpl(Collection<Event> events, boolean isLocal) {
this.events = events;
this.isLocal = isLocal;
}
@@ -51,7 +52,7 @@
/**
* {@inheritDoc}
*/
- public Iterator getEvents() {
+ public Iterator<Event> getEvents() {
return events.iterator();
}
@@ -61,4 +62,13 @@
public boolean isLocal() {
return isLocal;
}
+
+ //-----------------------------< Iterable >---------------------------------
+
+ /**
+ * {@inheritDoc}
+ */
+ public Iterator<Event> iterator() {
+ return getEvents();
+ }
}
Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/logging/RepositoryServiceLogger.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/logging/RepositoryServiceLogger.java?rev=790826&r1=790825&r2=790826&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/logging/RepositoryServiceLogger.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/logging/RepositoryServiceLogger.java Fri Jul 3 08:39:57 2009
@@ -615,6 +615,18 @@
return result;
}
+ public EventBundle getEvents(final SessionInfo sessionInfo,
+ final EventFilter filter,
+ final long after) throws RepositoryException,
+ UnsupportedRepositoryOperationException {
+ return (EventBundle) execute(new Callable() {
+ public Object call() throws RepositoryException {
+ return service.getEvents(sessionInfo, filter, after);
+ }
+ }, "getEvents(SessionInfo, EventFilter, long)",
+ new Object[]{unwrap(sessionInfo), filter, after});
+ }
+
public void updateEventFilters(final Subscription subscription, final EventFilter[] eventFilters)
throws RepositoryException {
Modified: jackrabbit/trunk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/EventBundle.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/EventBundle.java?rev=790826&r1=790825&r2=790826&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/EventBundle.java (original)
+++ jackrabbit/trunk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/EventBundle.java Fri Jul 3 08:39:57 2009
@@ -24,7 +24,7 @@
* <code>EventIterator</code> an <code>EventBundle</code> allows to retrieve
* the events multiple times using the {@link #getEvents} method.
*/
-public interface EventBundle {
+public interface EventBundle extends Iterable<Event> {
/**
* Returns the events of this bundle.
Modified: jackrabbit/trunk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/RepositoryService.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/RepositoryService.java?rev=790826&r1=790825&r2=790826&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/RepositoryService.java (original)
+++ jackrabbit/trunk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/RepositoryService.java Fri Jul 3 08:39:57 2009
@@ -1031,6 +1031,29 @@
throws RepositoryException, InterruptedException;
/**
+ * Returns events from the <code>EventJournal</code> after a given point in
+ * time. The returned event bundle may only contain events up to a given
+ * time. In order to retrieve more events a client must call this method
+ * again with the timestamp from the last event bundle. An empty bundle
+ * indicates that there are no more events.
+ *
+ * @param sessionInfo the session info.
+ * @param filter the event filter to apply. Please note: the
+ * <code>noLocal</code> flag is ignored.
+ * @param after retrieve events that occurred after the given
+ * timestamp.
+ * @return the event bundle.
+ * @throws RepositoryException if an error occurs.
+ * @throws UnsupportedRepositoryOperationException
+ * if the underlying implementation does not
+ * support event journaling.
+ */
+ public EventBundle getEvents(SessionInfo sessionInfo,
+ EventFilter filter,
+ long after)
+ throws RepositoryException, UnsupportedRepositoryOperationException;
+
+ /**
* Indicates that the passed subscription is no longer needed.
* <p/>
* <b>Note on thread-safety:</b> it is permissible to call this methods
Modified: jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/RepositoryServiceImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/RepositoryServiceImpl.java?rev=790826&r1=790825&r2=790826&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/RepositoryServiceImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/RepositoryServiceImpl.java Fri Jul 3 08:39:57 2009
@@ -1760,6 +1760,16 @@
}
/**
+ * @see RepositoryService#getEvents(SessionInfo, EventFilter,long)
+ */
+ public EventBundle getEvents(SessionInfo sessionInfo, EventFilter filter,
+ long after) throws
+ RepositoryException, UnsupportedRepositoryOperationException {
+ // TODO
+ throw new UnsupportedRepositoryOperationException();
+ }
+
+ /**
* @see RepositoryService#createSubscription(SessionInfo, EventFilter[])
*/
public Subscription createSubscription(SessionInfo sessionInfo,
Modified: jackrabbit/trunk/jackrabbit-spi2jcr/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi2jcr/pom.xml?rev=790826&r1=790825&r2=790826&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi2jcr/pom.xml (original)
+++ jackrabbit/trunk/jackrabbit-spi2jcr/pom.xml Fri Jul 3 08:39:57 2009
@@ -69,7 +69,6 @@
<value>
org.apache.jackrabbit.jcr2spi.name.NamespaceRegistryTest#testReRegisteredNamespaceVisibility
org.apache.jackrabbit.jcr2spi.name.NamespaceRegistryTest#testRegisteredNamespaceVisibility
- org.apache.jackrabbit.test.api.observation.EventJournalTest
org.apache.jackrabbit.test.api.ShareableNodeTest
org.apache.jackrabbit.test.api.version.simple
org.apache.jackrabbit.test.api.NodeReadMethodsTest#testGetPropertiesNamePatternArray
Added: jackrabbit/trunk/jackrabbit-spi2jcr/src/main/java/org/apache/jackrabbit/spi2jcr/EventFactory.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi2jcr/src/main/java/org/apache/jackrabbit/spi2jcr/EventFactory.java?rev=790826&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi2jcr/src/main/java/org/apache/jackrabbit/spi2jcr/EventFactory.java (added)
+++ jackrabbit/trunk/jackrabbit-spi2jcr/src/main/java/org/apache/jackrabbit/spi2jcr/EventFactory.java Fri Jul 3 08:39:57 2009
@@ -0,0 +1,156 @@
+/*
+ * 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.spi2jcr;
+
+import java.util.Map;
+import java.util.HashMap;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.UnsupportedRepositoryOperationException;
+import javax.jcr.PropertyType;
+import javax.jcr.Session;
+import javax.jcr.NamespaceException;
+import javax.jcr.nodetype.NodeType;
+
+import org.apache.jackrabbit.spi.Event;
+import org.apache.jackrabbit.spi.Path;
+import org.apache.jackrabbit.spi.NodeId;
+import org.apache.jackrabbit.spi.ItemId;
+import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.QValue;
+import org.apache.jackrabbit.spi.IdFactory;
+import org.apache.jackrabbit.spi.QValueFactory;
+import org.apache.jackrabbit.spi.commons.value.ValueFormat;
+import org.apache.jackrabbit.spi.commons.EventImpl;
+import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
+import org.apache.jackrabbit.spi.commons.conversion.NameException;
+import org.apache.jackrabbit.spi.commons.conversion.NameResolver;
+
+/**
+ * <code>EventFactory</code> implements a factory for SPI Event instances.
+ */
+class EventFactory {
+
+ private final Session session;
+
+ private final NamePathResolver resolver;
+
+ private final IdFactory idFactory;
+
+ private final QValueFactory qValueFactory;
+
+ public EventFactory(Session session,
+ NamePathResolver resolver,
+ IdFactory idFactory,
+ QValueFactory qValueFactory) {
+ this.session = session;
+ this.resolver = resolver;
+ this.idFactory = idFactory;
+ this.qValueFactory = qValueFactory;
+ }
+
+ public Event fromJCREvent(javax.jcr.observation.Event e)
+ throws RepositoryException {
+ Path p = resolver.getQPath(e.getPath());
+ Path parent = p.getAncestor(1);
+ int type = e.getType();
+
+ NodeId parentId = idFactory.createNodeId((String) null, parent);
+ String identifier = e.getIdentifier();
+ ItemId itemId;
+ Node node = null;
+ if (identifier != null) {
+ itemId = idFactory.fromJcrIdentifier(e.getIdentifier());
+ try {
+ node = session.getItem(e.getPath()).getParent();
+ } catch (RepositoryException re) {
+ // ignore. TODO improve
+ }
+ } else {
+ switch (type) {
+ case Event.NODE_ADDED:
+ case Event.NODE_MOVED:
+ node = session.getItem(e.getPath()).getParent();
+ case Event.NODE_REMOVED:
+ itemId = idFactory.createNodeId((String) null, p);
+ break;
+ case Event.PROPERTY_ADDED:
+ case Event.PROPERTY_CHANGED:
+ node = session.getItem(e.getPath()).getParent();
+ case Event.PROPERTY_REMOVED:
+ itemId = idFactory.createPropertyId(parentId,
+ p.getNameElement().getName());
+ break;
+ case Event.PERSIST:
+ default:
+ itemId = null;
+ }
+ }
+
+ Name nodeTypeName = null;
+ Name[] mixinTypes = new Name[0];
+ if (node != null) {
+ try {
+ parentId = idFactory.createNodeId(node.getUUID(), null);
+ } catch (UnsupportedRepositoryOperationException ex) {
+ // not referenceable
+ }
+ nodeTypeName = resolver.getQName(node.getPrimaryNodeType().getName());
+ mixinTypes = getNodeTypeNames(node.getMixinNodeTypes(), resolver);
+ }
+ Map<Name, QValue> info = new HashMap<Name, QValue>();
+ Map<String, Object> jcrInfo = e.getInfo();
+ for (Map.Entry<String, Object> entry : jcrInfo.entrySet()) {
+ String key = entry.getKey();
+ Object value = entry.getValue();
+
+ Name name = resolver.getQName(key);
+ if (value != null) {
+ // event information is generated for NODE_MOVED only in which
+ // case all values are of type PATH.
+ QValue v = ValueFormat.getQValue(value.toString(), PropertyType.PATH, resolver, qValueFactory);
+ info.put(name, v);
+ } else {
+ info.put(name, null);
+ }
+ }
+ return new EventImpl(e.getType(), p, itemId, parentId, nodeTypeName,
+ mixinTypes, e.getUserID(), e.getUserData(), e.getDate(), info);
+ }
+
+ /**
+ * Returns the names of the passed node types using the namespace resolver
+ * to parse the names.
+ *
+ * @param nt the node types
+ * @param resolver the name resolver.
+ * @return the names of the node types.
+ * @throws NameException if a node type returns an illegal name.
+ * @throws NamespaceException if the name of a node type contains a prefix
+ * that is not known to <code>resolver</code>.
+ */
+ private static Name[] getNodeTypeNames(NodeType[] nt, NameResolver resolver)
+ throws NameException, NamespaceException {
+ Name[] names = new Name[nt.length];
+ for (int i = 0; i < nt.length; i++) {
+ Name ntName = resolver.getQName(nt[i].getName());
+ names[i] = ntName;
+ }
+ return names;
+ }
+}
Propchange: jackrabbit/trunk/jackrabbit-spi2jcr/src/main/java/org/apache/jackrabbit/spi2jcr/EventFactory.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: jackrabbit/trunk/jackrabbit-spi2jcr/src/main/java/org/apache/jackrabbit/spi2jcr/EventSubscription.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi2jcr/src/main/java/org/apache/jackrabbit/spi2jcr/EventSubscription.java?rev=790826&r1=790825&r2=790826&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi2jcr/src/main/java/org/apache/jackrabbit/spi2jcr/EventSubscription.java (original)
+++ jackrabbit/trunk/jackrabbit-spi2jcr/src/main/java/org/apache/jackrabbit/spi2jcr/EventSubscription.java Fri Jul 3 08:39:57 2009
@@ -19,40 +19,22 @@
import org.apache.jackrabbit.spi.EventBundle;
import org.apache.jackrabbit.spi.EventFilter;
import org.apache.jackrabbit.spi.Event;
-import org.apache.jackrabbit.spi.ItemId;
-import org.apache.jackrabbit.spi.NodeId;
import org.apache.jackrabbit.spi.IdFactory;
-import org.apache.jackrabbit.spi.Name;
-import org.apache.jackrabbit.spi.Path;
import org.apache.jackrabbit.spi.Subscription;
-import org.apache.jackrabbit.spi.QValue;
import org.apache.jackrabbit.spi.QValueFactory;
-import org.apache.jackrabbit.spi.commons.EventImpl;
import org.apache.jackrabbit.spi.commons.EventBundleImpl;
import org.apache.jackrabbit.spi.commons.EventFilterImpl;
-import org.apache.jackrabbit.spi.commons.value.ValueFormat;
-import org.apache.jackrabbit.spi.commons.conversion.NameException;
-import org.apache.jackrabbit.spi.commons.conversion.NameResolver;
-import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
import org.slf4j.LoggerFactory;
import org.slf4j.Logger;
import javax.jcr.observation.EventListener;
import javax.jcr.observation.ObservationManager;
-import javax.jcr.Session;
-import javax.jcr.Node;
-import javax.jcr.UnsupportedRepositoryOperationException;
-import javax.jcr.NamespaceException;
import javax.jcr.RepositoryException;
-import javax.jcr.PropertyType;
-import javax.jcr.nodetype.NodeType;
import java.util.ArrayList;
import java.util.List;
import java.util.Iterator;
import java.util.Arrays;
import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
/**
* <code>EventSubscription</code> listens for JCR events and creates SPI event
@@ -76,37 +58,33 @@
| javax.jcr.observation.Event.NODE_MOVED
| javax.jcr.observation.Event.PERSIST;
- private final List eventBundles = new ArrayList();
-
- private final IdFactory idFactory;
-
- private final QValueFactory qValueFactory;
+ private final List<EventBundle> eventBundles = new ArrayList<EventBundle>();
private final SessionInfoImpl sessionInfo;
/**
* Current list of filters. Copy on write is performed on this list.
*/
- private volatile List filters;
+ private volatile List<EventFilter> filters;
/**
- * The resolver of the underlying session.
+ * Set to <code>true</code> if this subscription has been disposed.
*/
- private final NamePathResolver resolver;
+ private volatile boolean disposed = false;
/**
- * Set to <code>true</code> if this subscription has been disposed.
+ * The event factory.
*/
- private volatile boolean disposed = false;
+ private final EventFactory eventFactory;
/**
* Creates a new subscription for the passed session.
*
- * @param idFactory the id factory.
- * @param qValueFactory
- * @param sessionInfo the session info.
- * @param filters the filters that should be applied to the generated
- * events.
+ * @param idFactory the id factory.
+ * @param qValueFactory the QValueFactory.
+ * @param sessionInfo the session info.
+ * @param filters the filters that should be applied to the generated
+ * events.
* @throws RepositoryException if an error occurs while an event listener is
* registered with the session.
*/
@@ -114,14 +92,12 @@
QValueFactory qValueFactory,
SessionInfoImpl sessionInfo,
EventFilter[] filters) throws RepositoryException {
- this.idFactory = idFactory;
- this.qValueFactory = qValueFactory;
this.sessionInfo = sessionInfo;
- this.resolver = sessionInfo.getNamePathResolver();
+ this.eventFactory = new EventFactory(sessionInfo.getSession(),
+ sessionInfo.getNamePathResolver(), idFactory, qValueFactory);
setFilters(filters);
ObservationManager obsMgr = sessionInfo.getSession().getWorkspace().getObservationManager();
- obsMgr.addEventListener(this, EventSubscription.ALL_EVENTS,
- "/", true, null, null, true);
+ obsMgr.addEventListener(this, EventSubscription.ALL_EVENTS, "/", true, null, null, true);
}
/**
@@ -140,12 +116,12 @@
*/
void setFilters(EventFilter[] filters) throws RepositoryException {
// check type
- for (int i = 0; i < filters.length; i++) {
- if (!(filters[i] instanceof EventFilterImpl)) {
+ for (EventFilter filter : filters) {
+ if (!(filter instanceof EventFilterImpl)) {
throw new RepositoryException("Unknown filter implementation");
}
}
- List tmp = new ArrayList(Arrays.asList(filters));
+ List<EventFilter> tmp = new ArrayList<EventFilter>(Arrays.asList(filters));
this.filters = Collections.unmodifiableList(tmp);
}
@@ -234,76 +210,10 @@
if (disposed) {
return;
}
- List spiEvents = new ArrayList();
+ List<Event> spiEvents = new ArrayList<Event>();
while (events.hasNext()) {
try {
- Session session = sessionInfo.getSession();
- javax.jcr.observation.Event e = events.nextEvent();
- Path p = resolver.getQPath(e.getPath());
- Path parent = p.getAncestor(1);
- int type = e.getType();
-
- NodeId parentId = idFactory.createNodeId((String) null, parent);
- String identifier = e.getIdentifier();
- ItemId itemId;
- Node node = null;
- if (identifier != null) {
- itemId = idFactory.fromJcrIdentifier(e.getIdentifier());
- try {
- node = session.getItem(e.getPath()).getParent();
- } catch (RepositoryException re) {
- // ignore. TODO improve
- }
- } else {
- switch (type) {
- case Event.NODE_ADDED:
- case Event.NODE_MOVED:
- node = session.getItem(e.getPath()).getParent();
- case Event.NODE_REMOVED:
- itemId = idFactory.createNodeId((String) null, p);
- break;
- case Event.PROPERTY_ADDED:
- case Event.PROPERTY_CHANGED:
- node = session.getItem(e.getPath()).getParent();
- case Event.PROPERTY_REMOVED:
- itemId = idFactory.createPropertyId(parentId,
- p.getNameElement().getName());
- break;
- case Event.PERSIST:
- default:
- itemId = null;
- }
- }
-
- Name nodeTypeName = null;
- Name[] mixinTypes = new Name[0];
- if (node != null) {
- try {
- parentId = idFactory.createNodeId(node.getUUID(), null);
- } catch (UnsupportedRepositoryOperationException ex) {
- // not referenceable
- }
- nodeTypeName = resolver.getQName(node.getPrimaryNodeType().getName());
- mixinTypes = getNodeTypeNames(node.getMixinNodeTypes(), resolver);
- }
- Map<Name, QValue> info = new HashMap();
- Map jcrInfo = e.getInfo();
- for (Iterator it = jcrInfo.keySet().iterator(); it.hasNext();) {
- String key = it.next().toString();
- Object value = jcrInfo.get(key);
-
- Name name = resolver.getQName(key);
- if (value != null) {
- // event information is generated for NODE_MOVED only in which
- // case all values are of type PATH.
- QValue v = ValueFormat.getQValue(value.toString(), PropertyType.PATH, resolver, qValueFactory);
- info.put(name, v);
- } else {
- info.put(name, null);
- }
- }
- Event spiEvent = new EventImpl(e.getType(), p, itemId, parentId,
- nodeTypeName, mixinTypes, e.getUserID(), e.getUserData(), e.getDate(), info);
+ Event spiEvent = eventFactory.fromJCREvent(events.nextEvent());
spiEvents.add(spiEvent);
} catch (Exception ex) {
log.warn("Unable to create SPI Event: " + ex);
@@ -315,25 +225,4 @@
eventBundles.notify();
}
}
-
- /**
- * Returns the names of the passed node types using the namespace
- * resolver to parse the names.
- *
- * @param nt the node types
- * @param resolver
- * @return the names of the node types.
- * @throws NameException if a node type returns an illegal name.
- * @throws NamespaceException if the name of a node type contains a
- * prefix that is not known to <code>resolver</code>.
- */
- private static Name[] getNodeTypeNames(NodeType[] nt, NameResolver resolver)
- throws NameException, NamespaceException {
- Name[] names = new Name[nt.length];
- for (int i = 0; i < nt.length; i++) {
- Name ntName = resolver.getQName(nt[i].getName());
- names[i] = ntName;
- }
- return names;
- }
}
Modified: jackrabbit/trunk/jackrabbit-spi2jcr/src/main/java/org/apache/jackrabbit/spi2jcr/RepositoryServiceImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi2jcr/src/main/java/org/apache/jackrabbit/spi2jcr/RepositoryServiceImpl.java?rev=790826&r1=790825&r2=790826&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi2jcr/src/main/java/org/apache/jackrabbit/spi2jcr/RepositoryServiceImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-spi2jcr/src/main/java/org/apache/jackrabbit/spi2jcr/RepositoryServiceImpl.java Fri Jul 3 08:39:57 2009
@@ -39,7 +39,9 @@
import org.apache.jackrabbit.spi.Path;
import org.apache.jackrabbit.spi.Subscription;
import org.apache.jackrabbit.spi.QNodeTypeDefinition;
+import org.apache.jackrabbit.spi.Event;
import org.apache.jackrabbit.spi.commons.EventFilterImpl;
+import org.apache.jackrabbit.spi.commons.EventBundleImpl;
import org.apache.jackrabbit.spi.commons.nodetype.NodeTypeDefinitionImpl;
import org.apache.jackrabbit.spi.commons.name.NameFactoryImpl;
import org.apache.jackrabbit.spi.commons.name.PathFactoryImpl;
@@ -83,6 +85,7 @@
import javax.jcr.util.TraversingItemVisitor;
import javax.jcr.observation.ObservationManager;
import javax.jcr.observation.EventListener;
+import javax.jcr.observation.EventJournal;
import javax.jcr.query.InvalidQueryException;
import javax.jcr.query.QueryManager;
import javax.jcr.query.Query;
@@ -1100,6 +1103,37 @@
/**
* {@inheritDoc}
*/
+ public EventBundle getEvents(SessionInfo sessionInfo,
+ EventFilter filter,
+ long after)
+ throws RepositoryException, UnsupportedRepositoryOperationException {
+ SessionInfoImpl sInfo = getSessionInfoImpl(sessionInfo);
+ EventJournal journal = sInfo.getSession().getWorkspace().getObservationManager().getEventJournal();
+ if (journal == null) {
+ throw new UnsupportedRepositoryOperationException();
+ }
+ EventFactory factory = new EventFactory(sInfo.getSession(),
+ sInfo.getNamePathResolver(), idFactory, qValueFactory);
+ journal.skipTo(after);
+ List<Event> events = new ArrayList<Event>();
+ int batchSize = 1024;
+ boolean distinctDates = true;
+ long lastDate = Long.MIN_VALUE;
+ while (journal.hasNext() && (batchSize > 0 || !distinctDates)) {
+ Event e = factory.fromJCREvent(journal.nextEvent());
+ if (filter.accept(e, false)) {
+ distinctDates = lastDate != e.getDate();
+ lastDate = e.getDate();
+ events.add(e);
+ batchSize--;
+ }
+ }
+ return new EventBundleImpl(events, false);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public void updateEventFilters(Subscription subscription,
EventFilter[] filters)
throws RepositoryException {
Added: jackrabbit/trunk/jackrabbit-spi2jcr/src/test/resources/repository.xml
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi2jcr/src/test/resources/repository.xml?rev=790826&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi2jcr/src/test/resources/repository.xml (added)
+++ jackrabbit/trunk/jackrabbit-spi2jcr/src/test/resources/repository.xml Fri Jul 3 08:39:57 2009
@@ -0,0 +1,146 @@
+<?xml version="1.0"?>
+<!--
+ 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.
+-->
+<!DOCTYPE Repository PUBLIC "-//The Apache Software Foundation//DTD Jackrabbit 1.6//EN"
+ "http://jackrabbit.apache.org/dtd/repository-1.6.dtd">
+<!-- Example Repository Configuration File
+ Used by
+ - org.apache.jackrabbit.core.config.RepositoryConfigTest.java
+ -
+-->
+<Repository>
+ <Cluster id="node1">
+ <Journal class="org.apache.jackrabbit.core.journal.FileJournal">
+ <param name="revision" value="${rep.home}/repository/revision"/>
+ <param name="directory" value="${rep.home}/repository/journal"/>
+ </Journal>
+ </Cluster>
+
+ <!--
+ virtual file system where the repository stores global state
+ (e.g. registered namespaces, custom node types, etc.)
+ -->
+ <FileSystem class="org.apache.jackrabbit.core.fs.local.LocalFileSystem">
+ <param name="path" value="${rep.home}/repository"/>
+ </FileSystem>
+
+ <!--
+ security configuration
+ -->
+ <Security appName="Jackrabbit">
+ <!--
+ security manager:
+ class: FQN of class implementing the JackrabbitSecurityManager interface
+ -->
+ <SecurityManager class="org.apache.jackrabbit.core.security.simple.SimpleSecurityManager" workspaceName="security">
+ <!--
+ workspace access:
+ class: FQN of class implementing the WorkspaceAccessManager interface
+ -->
+ <!-- <WorkspaceAccessManager class="..."/> -->
+ <!-- <param name="config" value="${rep.home}/security.xml"/> -->
+ </SecurityManager>
+
+ <!--
+ access manager:
+ class: FQN of class implementing the AccessManager interface
+ -->
+ <AccessManager class="org.apache.jackrabbit.core.security.simple.SimpleAccessManager">
+ <!-- <param name="config" value="${rep.home}/access.xml"/> -->
+ </AccessManager>
+
+ <LoginModule class="org.apache.jackrabbit.core.security.simple.SimpleLoginModule">
+ <!--
+ anonymous user name ('anonymous' is the default value)
+ -->
+ <param name="anonymousId" value="anonymous"/>
+ <!--
+ administrator user id (default value if param is missing is 'admin')
+ -->
+ <param name="adminId" value="admin"/>
+ </LoginModule>
+ </Security>
+
+ <!--
+ location of workspaces root directory and name of default workspace
+ -->
+ <Workspaces rootPath="${rep.home}/workspaces" defaultWorkspace="default"/>
+ <!--
+ workspace configuration template:
+ used to create the initial workspace if there's no workspace yet
+ -->
+ <Workspace name="${wsp.name}">
+ <!--
+ virtual file system of the workspace:
+ class: FQN of class implementing the FileSystem interface
+ -->
+ <FileSystem class="org.apache.jackrabbit.core.fs.local.LocalFileSystem">
+ <param name="path" value="${wsp.home}"/>
+ </FileSystem>
+ <!--
+ persistence manager of the workspace:
+ class: FQN of class implementing the PersistenceManager interface
+ -->
+ <PersistenceManager class="org.apache.jackrabbit.core.persistence.bundle.DerbyPersistenceManager">
+ <param name="url" value="jdbc:derby:${wsp.home}/db;create=true"/>
+ <param name="schemaObjectPrefix" value="${wsp.name}_"/>
+ </PersistenceManager>
+ <!--
+ Search index and the file system it uses.
+ class: FQN of class implementing the QueryHandler interface
+ -->
+ <SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex">
+ <param name="path" value="${wsp.home}/index"/>
+ <param name="extractorPoolSize" value="2"/>
+ <param name="supportHighlighting" value="true"/>
+ </SearchIndex>
+ </Workspace>
+
+ <!--
+ Configures the versioning
+ -->
+ <Versioning rootPath="${rep.home}/version">
+ <!--
+ Configures the filesystem to use for versioning for the respective
+ persistence manager
+ -->
+ <FileSystem class="org.apache.jackrabbit.core.fs.local.LocalFileSystem">
+ <param name="path" value="${rep.home}/version" />
+ </FileSystem>
+
+ <!--
+ Configures the persistence manager to be used for persisting version state.
+ Please note that the current versioning implementation is based on
+ a 'normal' persistence manager, but this could change in future
+ implementations.
+ -->
+ <PersistenceManager class="org.apache.jackrabbit.core.persistence.bundle.DerbyPersistenceManager">
+ <param name="url" value="jdbc:derby:${rep.home}/version/db;create=true"/>
+ <param name="schemaObjectPrefix" value="version_"/>
+ </PersistenceManager>
+ </Versioning>
+
+ <!--
+ Search index for content that is shared repository wide
+ (/jcr:system tree, contains mainly versions)
+ -->
+ <SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex">
+ <param name="path" value="${rep.home}/repository/index"/>
+ <param name="extractorPoolSize" value="2"/>
+ <param name="supportHighlighting" value="true"/>
+ </SearchIndex>
+</Repository>
Propchange: jackrabbit/trunk/jackrabbit-spi2jcr/src/test/resources/repository.xml
------------------------------------------------------------------------------
svn:eol-style = native
Modified: jackrabbit/trunk/jackrabbit-spi2jcr/src/test/resources/repositoryStubImpl.properties
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi2jcr/src/test/resources/repositoryStubImpl.properties?rev=790826&r1=790825&r2=790826&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi2jcr/src/test/resources/repositoryStubImpl.properties (original)
+++ jackrabbit/trunk/jackrabbit-spi2jcr/src/test/resources/repositoryStubImpl.properties Fri Jul 3 08:39:57 2009
@@ -22,6 +22,9 @@
# Use this stub implementation for testing Jackrabbit-Core without intermediate SPI
# javax.jcr.tck.repository_stub_impl=org.apache.jackrabbit.spi2jcr.DefaultRepositoryStub
+# the repository configuration
+org.apache.jackrabbit.repository.config=target/test-classes/repository.xml
+
# alternative workspace used for update tests etc.
org.apache.jackrabbit.jcr2spi.workspace2.name=test
|