You are viewing a plain text version of this content. The canonical link for it is here.
Posted to slide-dev@jakarta.apache.org by st...@apache.org on 2004/07/01 20:30:11 UTC
cvs commit: jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/observation EventListenerIteratorImpl.java EventState.java EventStateCollection.java FilteredEventIterator.java ObservationManagerFactory.java
stefan 2004/07/01 11:30:10
Added: proposals/jcrri/src/org/apache/slide/jcr/core/observation
EventListenerIteratorImpl.java EventState.java
EventStateCollection.java
FilteredEventIterator.java
ObservationManagerFactory.java
Log:
jcrri
Revision Changes Path
1.1 jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/observation/EventListenerIteratorImpl.java
Index: EventListenerIteratorImpl.java
===================================================================
/*
* $Id: EventListenerIteratorImpl.java,v 1.1 2004/07/01 18:30:08 stefan Exp $
*
* Copyright 2002-2004 Day Management AG, Switzerland.
*
* Licensed under the Day RI License, Version 2.0 (the "License"),
* as a reference implementation of the following specification:
*
* Content Repository API for Java Technology, revision 0.13
* <http://www.jcp.org/en/jsr/detail?id=170>
*
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License files at
*
* http://www.day.com/content/en/licenses/day-ri-license-2.0
* 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.slide.jcr.core.observation;
import javax.jcr.observation.EventListenerIterator;
import javax.jcr.observation.EventListener;
import javax.jcr.Ticket;
import java.util.Iterator;
import java.util.Collection;
import java.util.NoSuchElementException;
/**
* @author Marcel Reutegger
* @version $Revision: 1.1 $, $Date: 2004/07/01 18:30:08 $
*/
class EventListenerIteratorImpl implements EventListenerIterator {
/**
* This iterator will return {@link EventListener}s registered by this
* <code>Ticket</code>.
*/
private final Ticket ticket;
/** Iterator over {@link EventConsumer} instances */
private final Iterator consumers;
/**
* The next <code>EventListener</code> that belongs to the ticket
* passed in the constructor of this <code>EventListenerIteratorImpl</code>.
*/
private EventListener next;
/** Current position */
private long pos = 0;
/**
* Creates a new <code>EventListenerIteratorImpl</code>.
*
* @param ticket
* @param consumers
* @throws NullPointerException if <code>ticket</code> or <code>consumer</code>
* is <code>null</code>.
*/
EventListenerIteratorImpl(Ticket ticket, Collection consumers) {
if (ticket == null) throw new NullPointerException("ticket");
if (consumers == null) throw new NullPointerException("consumers");
this.ticket = ticket;
this.consumers = consumers.iterator();
fetchNext();
}
/**
* @see javax.jcr.observation.EventListenerIterator#nextEventListener()
*/
public EventListener nextEventListener() {
if (next == null) throw new NoSuchElementException();
EventListener l = next;
fetchNext();
pos++;
return l;
}
/**
* @see javax.jcr.RangeIterator#skip(int)
*/
public void skip(int skipNum) {
while (skipNum-- > 0) {
next();
}
}
/**
* Always returns <code>-1</code>.
* @return <code>-1</code>.
*/
public long getSize() {
return -1;
}
/**
* @see javax.jcr.RangeIterator#getPos()
*/
public long getPos() {
return pos;
}
/**
* Remove is not supported on this Iterator.
* @exception UnsupportedOperationException
*/
public void remove() {
throw new UnsupportedOperationException("EventListenerIterator.remove()");
}
/**
* Returns <tt>true</tt> if the iteration has more elements. (In other
* words, returns <tt>true</tt> if <tt>next</tt> would return an element
* rather than throwing an exception.)
*
* @return <tt>true</tt> if the consumers has more elements.
*/
public boolean hasNext() {
return (next != null);
}
/**
* @see Iterator#next()
*/
public Object next() {
return nextEventListener();
}
/**
* Fetches the next {@link javax.jcr.observation.EventListener} associated
* with the <code>Ticket</code> passed in the constructor of this
* <code>EventListenerIteratorImpl</code> from all register
* <code>EventListener</code>s
*/
private void fetchNext() {
EventConsumer consumer;
next = null;
while (next == null && consumers.hasNext()) {
consumer = (EventConsumer)consumers.next();
if (consumer.getUserId().equals(ticket.getUserId())) {
next = consumer.getEventListener();
}
}
}
}
1.1 jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/observation/EventState.java
Index: EventState.java
===================================================================
/*
* $Id: EventState.java,v 1.1 2004/07/01 18:30:08 stefan Exp $
*
* Copyright 2002-2004 Day Management AG, Switzerland.
*
* Licensed under the Day RI License, Version 2.0 (the "License"),
* as a reference implementation of the following specification:
*
* Content Repository API for Java Technology, revision 0.13
* <http://www.jcp.org/en/jsr/detail?id=170>
*
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License files at
*
* http://www.day.com/content/en/licenses/day-ri-license-2.0
* 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.slide.jcr.core.observation;
import org.apache.slide.jcr.core.QName;
import javax.jcr.observation.EventType;
/**
* The <code>EventState</code> class encapsulates the ticket
* independent state of an {@link javax.jcr.observation.Event}.
*
* @author Marcel Reutegger
* @version $Revision: 1.1 $
*/
class EventState {
/** The {@link javax.jcr.observation.EventType} of this event. */
private final long type;
/** The UUID of the parent node associated with this event. */
private final String parentUUID;
/** The qualified name of the child item associated with this event. */
private final QName childName;
/** The userId of the ticket that caused this event. */
private final String userId;
/** Cached String representation of this <code>EventState</code>. */
private String stringValue;
/** Cached hashCode value for this <code>Event</code>. */
private int hashCode;
/**
* Creates a new <code>EventState</code> instance.
*
* @param type the {@link javax.jcr.observation.EventType} of this
* event.
* @param parentUUID the uuid of the parent node associated with this event.
* @param childName the qualified name of the child item associated with
* this event.
* @param userId the userId of the {@link javax.jcr.Ticket} that
* caused this event.
*/
private EventState(long type, String parentUUID, QName childName, String userId) {
this.type = type;
this.parentUUID = parentUUID;
this.childName = childName;
this.userId = userId;
}
//-----------------< factory methods >--------------------------------------
/**
* Creates a new {@link javax.jcr.observation.Event} of type
* {@link javax.jcr.observation.EventType#CHILD_NODE_ADDED}.
*
* @param parentUUID the uuid of the parent node associated with
* this <code>EventState</code>.
* @param childName the qualified name of the child node that was added.
* @param userId the userId of the ticket that added the node.
* @return an <code>EventState</code> instance.
*/
public static EventState ChildNodeAdded(String parentUUID,
QName childName,
String userId) {
return new EventState(EventType.CHILD_NODE_ADDED,
parentUUID,
childName,
userId);
}
/**
* Creates a new {@link javax.jcr.observation.Event} of type
* {@link javax.jcr.observation.EventType#CHILD_NODE_REMOVED}.
*
* @param parentUUID the uuid of the parent node associated with
* this <code>EventState</code>.
* @param childName the qualified name of the child node that was removed.
* @param userId the userId of the ticket that removed the node.
* @return an <code>EventState</code> instance.
*/
public static EventState ChildNodeRemoved(String parentUUID,
QName childName,
String userId) {
return new EventState(EventType.CHILD_NODE_REMOVED,
parentUUID,
childName,
userId);
}
/**
* Creates a new {@link javax.jcr.observation.Event} of type
* {@link javax.jcr.observation.EventType#PROPERTY_ADDED}.
*
* @param parentUUID the uuid of the parent node associated with
* this <code>EventState</code>.
* @param childName the qualified name of the property that was added.
* @param userId the userId of the ticket that added the property.
* @return an <code>EventState</code> instance.
*/
public static EventState PropertyAdded(String parentUUID,
QName childName,
String userId) {
return new EventState(EventType.PROPERTY_ADDED,
parentUUID,
childName,
userId);
}
/**
* Creates a new {@link javax.jcr.observation.Event} of type
* {@link javax.jcr.observation.EventType#PROPERTY_REMOVED}.
*
* @param parentUUID the uuid of the parent node associated with
* this <code>EventState</code>.
* @param childName the qualified name of the property that was removed.
* @param userId the userId of the ticket that removed the property.
* @return an <code>EventState</code> instance.
*/
public static EventState PropertyRemoved(String parentUUID,
QName childName,
String userId) {
return new EventState(EventType.PROPERTY_REMOVED,
parentUUID,
childName,
userId);
}
/**
* Creates a new {@link javax.jcr.observation.Event} of type
* {@link javax.jcr.observation.EventType#PROPERTY_CHANGED}.
*
* @param parentUUID the uuid of the parent node associated with
* this <code>EventState</code>.
* @param childName the qualified name of the property that changed.
* @param userId the userId of the ticket that changed the property.
* @return an <code>EventState</code> instance.
*/
public static EventState PropertyChanged(String parentUUID,
QName childName,
String userId) {
return new EventState(EventType.PROPERTY_CHANGED,
parentUUID,
childName,
userId);
}
/**
* @see javax.jcr.observation.Event#getType()
*/
public long getType() {
return type;
}
/**
* Returns the uuid of the parent node.
* @return the uuid of the parent node.
*/
public String getParentUUID() {
return parentUUID;
}
/**
* Returns the {@link QName} of the
* {@link javax.jcr.Item} associated with this event.
* @return the <code>QName</code> associated with this event.
*/
public QName getChildItemQName() {
return childName;
}
/**
* @see javax.jcr.observation.Event#getUserId()
*/
public String getUserId() {
return userId;
}
/**
* Returns a String representation of this <code>EventState</code>.
* @return a String representation of this <code>EventState</code>.
*/
public String toString() {
if (stringValue == null) {
StringBuffer sb = new StringBuffer();
sb.append("EventState: ").append(valueOf(type));
sb.append(", Parent: ").append(parentUUID);
sb.append(", Child: ").append(childName);
sb.append(", UserId: ").append(userId);
stringValue = sb.toString();
}
return stringValue;
}
/**
* Returns a hashCode for this <code>EventState</code>.
* @return a hashCode for this <code>EventState</code>.
*/
public int hashCode() {
int h = hashCode;
if (h == 0) {
h = 37;
h = 37*h + (int)type;
h = 37*h + parentUUID.hashCode();
h = 37*h + childName.hashCode();
h = 37*h + userId.hashCode();
hashCode = h;
}
return hashCode;
}
/**
* Returns <code>true</code> if this <code>EventState</code> is equal to
* another object.
*
* @param obj the reference object with which to compare.
* @return <code>true</code> if object <code>obj</code> is equal to this
* <code>EventState</code>; <code>false</code> otherwise.
*/
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj instanceof EventState) {
EventState other = (EventState) obj;
return this.type == other.type
&& this.parentUUID.equals(other.parentUUID)
&& this.childName.equals(other.childName)
&& this.userId.equals(other.userId);
}
return false;
}
/**
* Returns a String representation of <code>eventType</code>.
*
* @param eventType an event type defined by {@link EventType}.
* @return a String representation of <code>eventType</code>.
*/
public static String valueOf(long eventType) {
if (eventType == EventType.CHILD_NODE_ADDED) {
return "ChildNodeAdded";
} else if (eventType == EventType.CHILD_NODE_REMOVED) {
return "ChildNodeRemoved";
} else if (eventType == EventType.PROPERTY_ADDED) {
return "PropertyAdded";
} else if (eventType == EventType.PROPERTY_CHANGED) {
return "PropertyChanged";
} else if (eventType == EventType.PROPERTY_REMOVED) {
return "PropertyRemoved";
} else {
return "UnknownEventType";
}
}
}
1.1 jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/observation/EventStateCollection.java
Index: EventStateCollection.java
===================================================================
/*
* $Id: EventStateCollection.java,v 1.1 2004/07/01 18:30:08 stefan Exp $
*
* Copyright 2002-2004 Day Management AG, Switzerland.
*
* Licensed under the Day RI License, Version 2.0 (the "License"),
* as a reference implementation of the following specification:
*
* Content Repository API for Java Technology, revision 0.13
* <http://www.jcp.org/en/jsr/detail?id=170>
*
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License files at
*
* http://www.day.com/content/en/licenses/day-ri-license-2.0
* 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.slide.jcr.core.observation;
import org.apache.slide.jcr.core.state.*;
import org.apache.log4j.Logger;
import javax.jcr.RepositoryException;
import java.util.*;
/**
* The <code>EventStateCollection</code> class implements how {@link EventState}
* objects are created based on the {@link org.apache.slide.jcr.core.state.ItemState}s
* passed to the {@link #createEventStates} method.
*
* @author mreutegg
* @version $Revision: 1.1 $
*/
final public class EventStateCollection {
/** Logger instance for this class */
private static Logger log = Logger.getLogger(EventStateCollection.class);
/** List of events */
private final List events = new ArrayList();
/** UserId of the ticket that created these events */
private final String userId;
/**
* Creates a new empty <code>EventStateCollection</code>. The <code>userId</code>
* indicates that events in this collection are created by a ticket
* associated to the user with id <code>userId</code>.
*
* @param userId the user id of the ticket that created these events.
*/
public EventStateCollection(String userId) {
this.userId = userId;
}
/**
* Creates {@link EventState}s for the passed {@link org.apache.slide.jcr.core.state.ItemState state}
* instance.
*
* @param state the transient <code>ItemState</code> for whom
* to create {@link EventState}s.
* @throws RepositoryException if an error occurs.
*/
public void createEventStates(ItemState state)
throws RepositoryException {
int status = state.getStatus();
if (status == ItemState.STATUS_EXISTING_MODIFIED ||
status == ItemState.STATUS_NEW) {
if (state.isNode()) {
// 1) check added properties
NodeState currentNode = (NodeState)state;
List addedProperties = currentNode.getAddedPropertyEntries();
for (Iterator it = addedProperties.iterator(); it.hasNext(); ) {
NodeState.PropertyEntry prop = (NodeState.PropertyEntry)it.next();
events.add(EventState.PropertyAdded(currentNode.getUUID(),
prop.getName(),
userId));
}
// 2) check removed properties
List removedProperties = currentNode.getRemovedPropertyEntries();
for (Iterator it = removedProperties.iterator(); it.hasNext(); ) {
NodeState.PropertyEntry prop = (NodeState.PropertyEntry)it.next();
events.add(EventState.PropertyRemoved(currentNode.getUUID(),
prop.getName(),
userId));
}
// 3) check for added nodes
List addedNodes = currentNode.getAddedChildNodeEntries();
for (Iterator it = addedNodes.iterator(); it.hasNext(); ) {
NodeState.ChildNodeEntry child = (NodeState.ChildNodeEntry)it.next();
events.add(EventState.ChildNodeAdded(currentNode.getUUID(),
child.getName(),
userId));
}
// 4) check for removed nodes
List removedNodes = currentNode.getRemovedChildNodeEntries();
for (Iterator it = removedNodes.iterator(); it.hasNext(); ) {
NodeState.ChildNodeEntry child = (NodeState.ChildNodeEntry)it.next();
events.add(EventState.ChildNodeRemoved(currentNode.getUUID(),
child.getName(),
userId));
}
} else {
// only add property changed event if property is existing
if (state.getStatus() == ItemState.STATUS_EXISTING_MODIFIED) {
events.add(EventState.PropertyChanged(state.getParentUUID(),
((PropertyState)state).getName(),
userId));
}
}
}
}
/**
* Returns an iterator over {@link EventState} instance.
* @return an iterator over {@link EventState} instance.
*/
Iterator iterator() {
return events.iterator();
}
}
1.1 jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/observation/FilteredEventIterator.java
Index: FilteredEventIterator.java
===================================================================
/*
* $Id: FilteredEventIterator.java,v 1.1 2004/07/01 18:30:08 stefan Exp $
*
* Copyright 2002-2004 Day Management AG, Switzerland.
*
* Licensed under the Day RI License, Version 2.0 (the "License"),
* as a reference implementation of the following specification:
*
* Content Repository API for Java Technology, revision 0.13
* <http://www.jcp.org/en/jsr/detail?id=170>
*
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License files at
*
* http://www.day.com/content/en/licenses/day-ri-license-2.0
* 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.slide.jcr.core.observation;
import org.apache.log4j.Logger;
import javax.jcr.observation.EventIterator;
import javax.jcr.observation.Event;
import javax.jcr.RepositoryException;
import java.util.Iterator;
import java.util.NoSuchElementException;
/**
*
* @author Marcel Reutegger
*/
class FilteredEventIterator implements EventIterator {
/** Logger instance for this class */
private static final Logger log
= Logger.getLogger(FilteredEventIterator.class);
/** The actual {@link EventState}s fired by the workspace (unfiltered) */
private final Iterator actualEvents;
/** For filtering the {@link javax.jcr.observation.Event}s. */
private final EventFilter filter;
/** The next {@link javax.jcr.observation.Event} in this iterator */
private Event next;
/** Current position */
private long pos = 0;
/**
* Creates a new <code>FilteredEventIterator</code>.
*
* @param c an unmodifiable Collection of
* {@link javax.jcr.observation.Event}s.
* @param filter only event that pass the filter will be
* dispatched to the event listener.
*/
public FilteredEventIterator(EventStateCollection c, EventFilter filter) {
actualEvents = c.iterator();
this.filter = filter;
fetchNext();
}
/**
* @see Iterator#next()
*/
public Object next() {
if (next == null) throw new NoSuchElementException();
Event e = next;
fetchNext();
pos++;
return e;
}
/**
* @see EventIterator#nextEvent()
*/
public Event nextEvent() {
return (Event)next();
}
/**
* @see javax.jcr.RangeIterator#skip(int)
*/
public void skip(int skipNum) {
while (skipNum-- > 0) {
next();
}
}
/**
* Always returns <code>-1</code>.
* @return <code>-1</code>.
*/
public long getSize() {
return -1;
}
/**
* @see javax.jcr.RangeIterator#getPos()
*/
public long getPos() {
return pos;
}
/**
* This method is not supported.
* Always throws a <code>UnsupportedOperationException</code>.
*/
public void remove() {
throw new UnsupportedOperationException("EventIterator.remove()");
}
/**
* Returns <tt>true</tt> if the iteration has more elements. (In other
* words, returns <tt>true</tt> if <tt>next</tt> would return an element
* rather than throwing an exception.)
*
* @return <tt>true</tt> if the iterator has more elements.
*/
public boolean hasNext() {
return (next != null);
}
/**
* Fetches the next Event from the collection of events
* passed in the constructor of <code>FilteredEventIterator</code>
* that is allowed by the {@link EventFilter}.
*/
private void fetchNext() {
EventState state;
next = null;
while (next == null && actualEvents.hasNext()) {
state = (EventState)actualEvents.next();
try {
next = filter.blocks(state) ? null : new EventImpl(filter.getTicket(),
filter.getItemManager(),
state);
} catch (RepositoryException e) {
log.error("Exception while applying filter.", e);
}
}
}
}
1.1 jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/observation/ObservationManagerFactory.java
Index: ObservationManagerFactory.java
===================================================================
/*
* $Id: ObservationManagerFactory.java,v 1.1 2004/07/01 18:30:08 stefan Exp $
*
* Copyright 2002-2004 Day Management AG, Switzerland.
*
* Licensed under the Day RI License, Version 2.0 (the "License"),
* as a reference implementation of the following specification:
*
* Content Repository API for Java Technology, revision 0.13
* <http://www.jcp.org/en/jsr/detail?id=170>
*
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License files at
*
* http://www.day.com/content/en/licenses/day-ri-license-2.0
* 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.slide.jcr.core.observation;
import org.apache.slide.jcr.core.ItemManager;
import org.apache.slide.jcr.core.TicketImpl;
import org.apache.commons.collections.Buffer;
import org.apache.commons.collections.BufferUtils;
import org.apache.commons.collections.UnboundedFifoBuffer;
import org.apache.log4j.Logger;
import javax.jcr.observation.*;
import javax.jcr.observation.EventListener;
import javax.jcr.RepositoryException;
import javax.jcr.nodetype.NodeTypeManager;
import javax.jcr.nodetype.NodeType;
import java.util.*;
/**
* The class <code>ObservationManagerFactory</code> creates new
* <code>ObservationManager</code> instances for tickets. It also implements the
* {@link EventDispatcher} interface where {@link EventStateCollection}s can be
* dispatched to {@link javax.jcr.observation.EventListener}s.
*
* @author Marcel Reutegger
*/
final public class ObservationManagerFactory implements EventDispatcher, Runnable {
/** Logger instance for this class */
private static final Logger log
= Logger.getLogger(ObservationManagerFactory.class);
/** Dummy DispatchAction indicating the notification thread to end */
private static final DispatchAction DISPOSE_MARKER = new DispatchAction(null, null);
/** Currently active <code>EventConsumer</code>s for notification */
private Set activeConsumers = new HashSet();
/** Set of <code>EventConsumer</code>s for read only Set access */
private Set readOnlyConsumers;
/** synchronization monitor for listener changes */
private Object consumerChange = new Object();
/** Contains the pending events that will be delivered to event listeners */
private Buffer eventQueue
= BufferUtils.blockingBuffer(new UnboundedFifoBuffer());
/** The background notification thread */
private Thread notificationThread;
/**
* Creates a new <code>ObservationManagerFactory</code> instance
* and starts the notification thread deamon.
*/
public ObservationManagerFactory() {
notificationThread = new Thread(this, "ObservationManager");
notificationThread.setDaemon(true);
notificationThread.start();
}
/**
* Disposes this <code>ObservationManager</code>. This will
* effectively stop the background notification thread.
*/
public void dispose() {
// dispatch dummy event to mark end of notification
eventQueue.add(DISPOSE_MARKER);
try {
notificationThread.join();
} catch (InterruptedException e) {
// FIXME log exception ?
}
log.info("Notification of EventListeners stopped.");
}
/**
* Returns an unmodifieable <code>Set</code> of <code>EventConsumer</code>s.
* @return <code>Set</code> of <code>EventConsumer</code>s.
*/
private Set getConsumers() {
synchronized (consumerChange) {
if (readOnlyConsumers == null) {
readOnlyConsumers = Collections.unmodifiableSet(
new HashSet(activeConsumers));
}
return readOnlyConsumers;
}
}
/**
* Creates a new <code>ticket</code> local <code>ObservationManager</code>
* with an associated <code>NamespaceResolver</code>.
*
* @param ticket the ticket.
* @param itemMgr the <code>ItemManager</code> of the <code>ticket</code>.
* @return an <code>ObservationManager</code>.
*/
public ObservationManager createObservationManager(TicketImpl ticket,
ItemManager itemMgr) {
return new TicketLocalObservationManager(ticket, itemMgr);
}
/**
* Implements the run method of the background notification
* thread.
*/
public void run() {
DispatchAction action;
while ((action = (DispatchAction)eventQueue.remove()) != DISPOSE_MARKER) {
log.debug("got EventStateCollection");
log.debug("event delivery to " + action.eventConsumers.size() + " consumers started...");
for (Iterator it = action.eventConsumers.iterator(); it.hasNext(); ) {
EventConsumer c = (EventConsumer)it.next();
try {
c.consumeEvents(action.eventStates);
} catch (Throwable t) {
log.error("EventConsumer threw exception.", t);
// move on to the next consumer
}
}
log.debug("event delivery finished.");
}
}
//-------------------------< EventDispatcher >------------------------------
/**
* @see EventDispatcher#dispatchEvents
*/
public void dispatchEvents(EventStateCollection events) {
eventQueue.add(new DispatchAction(events, getConsumers()));
}
//----------------------------< adapter class >-----------------------------
/**
* Each <code>Ticket</code> instance has its own <code>ObservationManager</code>
* instance. The class <code>TicketLocalObservationManager</code> implements
* this behaviour.
*/
class TicketLocalObservationManager implements ObservationManager {
/**
* The <code>Ticket</code> this <code>ObservationManager</code>
* belongs to.
*/
private TicketImpl ticket;
/**
* The <code>ItemManager</code> for this <code>ObservationManager</code>.
*/
private ItemManager itemMgr;
/**
* Creates an <code>ObservationManager</code> instance.
*
* @param ticket the <code>Ticket</code> this ObservationManager
* belongs to.
* @param itemMgr {@link org.apache.slide.jcr.core.ItemManager} of the passed
* <code>Ticket</code>.
*
* @exception NullPointerException if <code>ticket</code> or <code>itemMgr</code>
* is <code>null</code>.
*/
TicketLocalObservationManager(TicketImpl ticket,
ItemManager itemMgr) {
if (ticket == null) throw new NullPointerException("ticket");
if (itemMgr == null) throw new NullPointerException("itemMgr");
this.ticket = ticket;
this.itemMgr = itemMgr;
}
/**
* @see ObservationManager#addEventListener
*/
public void addEventListener(EventListener listener,
long eventTypes,
String absPath,
boolean isDeep,
String[] uuid,
String[] nodeTypeName,
boolean noLocal)
throws RepositoryException {
// create NodeType instances from names
NodeType[] nodeTypes;
if (nodeTypeName == null) {
nodeTypes = null;
} else {
NodeTypeManager ntMgr = ticket.getWorkspace().getNodeTypeManager();
nodeTypes = new NodeType[nodeTypeName.length];
for (int i = 0; i < nodeTypes.length; i++) {
nodeTypes[i] = ntMgr.getNodeType(nodeTypeName[i]);
}
}
// create filter
EventFilter filter = new EventFilter(itemMgr,
ticket,
eventTypes,
absPath,
isDeep,
uuid,
nodeTypes,
noLocal);
EventConsumer consumer =
new EventConsumer(ticket.getUserId(), listener, filter);
synchronized (consumerChange) {
// remove existing if any
activeConsumers.remove(consumer);
// re-add it
activeConsumers.add(consumer);
// reset read only consumer set
readOnlyConsumers = null;
}
}
/**
* @see ObservationManager#removeEventListener(javax.jcr.observation.EventListener)
*/
public void removeEventListener(EventListener listener)
throws RepositoryException {
EventConsumer consumer =
new EventConsumer(ticket.getUserId(), listener, EventFilter.BLOCK_ALL);
synchronized (consumerChange) {
activeConsumers.remove(consumer);
// reset read only listener set
readOnlyConsumers = null;
}
}
/**
* @see ObservationManager#getRegisteredEventListeners()
*/
public EventListenerIterator getRegisteredEventListeners()
throws RepositoryException {
return new EventListenerIteratorImpl(ticket, getConsumers());
}
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: slide-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: slide-dev-help@jakarta.apache.org