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:29:57 UTC
cvs commit: jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/observation DispatchAction.java EventConsumer.java EventDispatcher.java EventFilter.java EventImpl.java
stefan 2004/07/01 11:29:57
Added: proposals/jcrri/src/org/apache/slide/jcr/core/observation
DispatchAction.java EventConsumer.java
EventDispatcher.java EventFilter.java
EventImpl.java
Log:
jcrri
Revision Changes Path
1.1 jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/observation/DispatchAction.java
Index: DispatchAction.java
===================================================================
/*
* $Id: DispatchAction.java,v 1.1 2004/07/01 18:29:57 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 java.util.Collection;
/**
* The <code>DispatchAction</code> class is a simple struct that defines what
* <code>EventState</code>s should be dispatched to which
* <code>EventConsumer</code>s.
*
* @author Marcel Reutegger
* @version $Revision: 1.1 $, $Date: 2004/07/01 18:29:57 $
*/
class DispatchAction {
/** The collection of <code>EventState</code>s */
final EventStateCollection eventStates;
/**
* <code>EventStates</code> are dispatched to these
* <code>EventConsumer</code>s.
*/
final Collection eventConsumers;
/**
* Creates a new <code>DispatchAction</code> struct with
* <code>eventStates</code> and <code>eventConsumers</code>.
*/
DispatchAction(EventStateCollection eventStates, Collection eventConsumers) {
this.eventStates = eventStates;
this.eventConsumers = eventConsumers;
}
}
1.1 jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/observation/EventConsumer.java
Index: EventConsumer.java
===================================================================
/*
* $Id: EventConsumer.java,v 1.1 2004/07/01 18:29:57 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.EventListener;
import javax.jcr.observation.EventIterator;
/**
* The <code>EventConsumer</code> class combines the {@link
* javax.jcr.observation.EventListener} with the implementation of specified
* filter for the listener: {@link EventFilter}.
* <p>
* Collections of {@link EventState} objects will be dispatched to {@link
* #consumeEvents}.
*
* @author Marcel Reutegger
* @version $Revision: 1.1 $, $Date: 2004/07/01 18:29:57 $
*/
class EventConsumer {
/** The userId part of this <code>EventConsumer</code>. */
private final String userId;
/** The listener part of this <code>EventConsumer</code>. */
private final EventListener listener;
/** The <code>EventFilter</code> for this <code>EventConsumer</code>. */
private final EventFilter filter;
/** cached hash code value */
private int hashCode;
/**
* An <code>EventConsumer</code> consists of a <code>userId</code> which
* refers to the user id of the <code>Ticket</code>, the attached
* <code>EventListener</code> and an <code>EventFilter</code>.
*
* @param userId the user id taken from the <code>Ticket</code>.
* @param listener the actual <code>EventListener</code> to call back.
* @param filter only pass an <code>Event</code> to the listener
* if the <code>EventFilter</code> allows the <code>Event</code>.
*
* @exception NullPointerException if <code>userId</code>,
* <code>listener</code> or <code>filter</code> is<code>null</code>.
*/
EventConsumer(String userId, EventListener listener, EventFilter filter) {
if (userId == null) throw new NullPointerException("userId");
if (listener == null) throw new NullPointerException("listener");
if (filter == null) throw new NullPointerException("filter");
this.userId = userId;
this.listener = listener;
this.filter = filter;
}
/**
* Returns the userId of the <code>Ticket</code> that is associated
* with this <code>EventConsumer</code>.
* @return the userId of this <code>EventConsumer</code>.
*/
String getUserId() {
return userId;
}
/**
* Returns the <code>EventListener</code> that is associated with this
* <code>EventConsumer</code>.
*
* @return the <code>EventListener</code> of this <code>EventConsumer</code>.
*/
EventListener getEventListener() {
return listener;
}
/**
* Dispatches the events to the <code>EventListener</code>.
* @param events a collection of {@link EventState}s
* to dispatch.
*/
void consumeEvents(EventStateCollection events) {
// check if filtered iterator has at least one event
EventIterator it = new FilteredEventIterator(events, filter);
if (it.hasNext()) {
listener.onEvent(it);
} else {
// otherwise skip this listener
}
}
/**
* Returns <code>true</code> if this <code>EventConsumer</code>
* is equal to some other object, <code>false</code> otherwise.
* <p>
* Two <code>EventConsumer</code>s are considered equal if
* they refer to the same user id and the <code>EventListener</code>s
* they reference are equal. Note that the <code>EventFilter</code> is
* ignored in this check.
*
* @param obj the reference object with which to compare.
* @return <code>true</code> if this <code>EventConsumer</code>
* is equal the other <code>EventConsumer</code>.
*/
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof EventConsumer) {
EventConsumer other = (EventConsumer)obj;
return userId.equals(other.userId)
&& listener.equals(other.listener);
}
return false;
}
/**
* Returns the hash code for this <code>EventConsumer</code>.
* @return the hash code for this <code>EventConsumer</code>.
*/
public int hashCode() {
if (hashCode == 0) {
hashCode = userId.hashCode() ^ listener.hashCode();
}
return hashCode;
}
}
1.1 jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/observation/EventDispatcher.java
Index: EventDispatcher.java
===================================================================
/*
* $Id: EventDispatcher.java,v 1.1 2004/07/01 18:29:57 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;
/**
* The <code>EventDispatcher</code> interface defines a single method {@link
* #dispatchEvents}, through this method a collection of {@link EventState}
* instances is dispatched to registered {@link javax.jcr.observation.EventListener}s.
*
* @author Marcel Reutegger
* @version $Revision: 1.1 $, $Date: 2004/07/01 18:29:57 $
*/
public interface EventDispatcher {
/**
* Dispatches the {@link EventStateCollection events} to all
* registered {@link javax.jcr.observation.EventListener}s.
*
* @param events the {@link EventState}s to dispatch.
*/
public void dispatchEvents(EventStateCollection events);
}
1.1 jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/observation/EventFilter.java
Index: EventFilter.java
===================================================================
/*
* $Id: EventFilter.java,v 1.1 2004/07/01 18:29:57 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.NodeId;
import org.apache.slide.jcr.core.TicketImpl;
import javax.jcr.*;
import javax.jcr.access.AccessDeniedException;
import javax.jcr.nodetype.NodeType;
/**
* The <code>EventFilter</code> class implement the filter logic based
* on the tickets access rights and the specified filter rules.
*
* @author Marcel Reutegger
* @version $Revision: 1.1 $, $Date: 2004/07/01 18:29:57 $
*/
class EventFilter {
static final EventFilter BLOCK_ALL = new BlockAllFilter();
/** The ItemManager of the ticket */
private final ItemManager itemMgr;
/** The ticket this EventFilter belongs to. */
private final TicketImpl ticket;
/**
* This <code>EventFilter</code> should only allow events with the
* specified types.
*/
private final long eventTypes;
/** Only allow Items with the specified <code>absPath</code> */
private final String absPath;
/**
* If <code>isDeep</code> is <code>true</code> also Items under <code>absPath</code>
* are allowed.
*/
private final boolean isDeep;
/**
* Only allow Nodes with the specified <code>uuids</code>.
*/
private final String[] uuids;
/**
* Only allow Nodes with the specified {@link javax.jcr.nodetype.NodeType}s.
*/
private final NodeType[] nodeTypes;
/**
* If <code>noLocal</code> is true this filter will block events from
* the ticket that registerd this filter.
*/
private final boolean noLocal;
/**
* Creates a new <code>EventFilter</code> instance.
*
* @param itemMgr the <code>ItemManager</code> of the <code>ticket</code>.
* @param ticket the <code>Ticket</code> that registered the {@link
* javax.jcr.observation.EventListener}.
* @param eventTypes only allow specified {@link javax.jcr.observation.EventType}s.
* @param absPath only allow {@link javax.jcr.Item} with
* <code>absPath</code>.
* @param isDeep if <code>true</code> also allow events for {@link
* Item}s below <code>absPath</code>.
* @param uuids only allow events for {@link javax.jcr.Node}s with
* specified UUIDs. If <code>null</code> is passed no
* restriction regarding UUID is applied.
* @param nodeTypes only allow events for specified {@link
* javax.jcr.nodetype.NodeType}s. If <code>null</code> no
* node type restriction is applied.
* @param noLocal if <code>true</code> no events are allowed that were
* created from changes related to the <code>Ticket</code>
* that registered the {@link javax.jcr.observation.EventListener}.
*/
EventFilter(ItemManager itemMgr,
TicketImpl ticket,
long eventTypes,
String absPath,
boolean isDeep,
String[] uuids,
NodeType[] nodeTypes,
boolean noLocal) {
this.itemMgr = itemMgr;
this.ticket = ticket;
this.eventTypes = eventTypes;
this.absPath = absPath;
this.isDeep = isDeep;
this.uuids = uuids;
this.noLocal = noLocal;
this.nodeTypes = nodeTypes;
}
/**
* Returns the <code>Ticket</code> associated with this
* <code>EventFilter</code>.
*
* @return the <code>Ticket</code> associated with this
* <code>EventFilter</code>.
*/
TicketImpl getTicket() {
return ticket;
}
/**
* Returns the <code>ItemManager</code> associated with this
* <code>EventFilter</code>.
*
* @return the <code>ItemManager</code> associated with this
* <code>EventFilter</code>.
*/
ItemManager getItemManager() {
return itemMgr;
}
/**
* Returns <code>true</code> if this <code>EventFilter</code> does not allow
* the specified <code>EventState</code>; <code>false</code> otherwise.
*
* @param eventState the <code>EventState</code> in question.
* @return <code>true</code> if this <code>EventFilter</code> blocks the
* <code>EventState</code>.
*
* @throws RepositoryException if an error occurs while checking.
*/
boolean blocks(EventState eventState) throws RepositoryException {
// first do cheap checks
// check event type
long type = eventState.getType();
if ((eventTypes & type) == 0) {
return true;
}
// check for ticket local changes
if (noLocal && ticket.getUserId().equals(eventState.getUserId())) {
// listener does not wish to get local events
return true;
}
// check UUIDs
String parentUUID = eventState.getParentUUID();
if (uuids != null) {
boolean match = false;
for (int i = 0; i < uuids.length && !match; i++) {
match |= parentUUID.equals(uuids[i]);
}
if (!match) {
return true;
}
}
Node parent = null;
try {
parent = (Node)itemMgr.getItem(new NodeId(eventState.getParentUUID()));
} catch (AccessDeniedException e) {
return true;
}
// check node types
if (nodeTypes != null) {
boolean match = false;
for (int i = 0; i < nodeTypes.length && !match; i++) {
match |= parent.isNodeType(nodeTypes[i].getName());
}
if (!match) {
return true;
}
}
// check path
StringIterator paths = parent.getPaths();
boolean match = false;
while (paths.hasNext() && !match) {
match |= (isDeep) ? paths.nextString().startsWith(absPath)
: paths.nextString().equals(absPath);
}
return !match;
}
/**
* This class implements an <code>EventFilter</code> that blocks
* all {@link EventState}s.
*/
private static final class BlockAllFilter extends EventFilter {
/**
* Creates a new <code>BlockAllFilter</code>.
*/
BlockAllFilter() {
super(null, null, 0, null, true, null, null, true);
}
/**
* Always return <code>true</code>.
* @return always <code>true</code>.
*/
boolean blocks(EventState eventState) {
return true;
}
}
}
1.1 jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/observation/EventImpl.java
Index: EventImpl.java
===================================================================
/*
* $Id: EventImpl.java,v 1.1 2004/07/01 18:29:57 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.TicketImpl;
import org.apache.slide.jcr.core.ItemManager;
import org.apache.slide.jcr.core.NodeId;
import org.apache.log4j.Logger;
import javax.jcr.observation.Event;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Ticket;
/**
* Implementation of the {@link javax.jcr.observation.Event} interface.
*
* @author Marcel Reutegger
* @version $Revision: 1.1 $
*/
final class EventImpl implements Event {
/** Logger instance for this class */
private static final Logger log = Logger.getLogger(EventImpl.class);
/**
* The ticket of the {@link javax.jcr.observation.EventListener} this
* event will be delivered to.
*/
private final TicketImpl ticket;
/**
* The <code>ItemManager</code> of the ticket.
*/
private final ItemManager itemMgr;
/** The shared {@link EventState} object. */
private final EventState eventState;
/** Cached String value of this <code>Event</code> instance. */
private String stringValue;
/**
* Creates a new {@link javax.jcr.observation.Event} instance based on an
* {@link EventState eventState}.
*
* @param ticket the ticket of the registerd <code>EventListener</code>
* where this <code>Event</code> will be delivered to.
* @param itemMgr the <code>ItemManager</code> of the above
* <code>Ticket</code>.
* @param eventState the underlying <code>EventState</code>.
*/
EventImpl(TicketImpl ticket, ItemManager itemMgr, EventState eventState) {
this.ticket = ticket;
this.itemMgr = itemMgr;
this.eventState = eventState;
}
/**
* @see Event#getType()
*/
public long getType() {
return eventState.getType();
}
/**
* @see Event#getParentNode()
*/
public Node getParentNode() throws RepositoryException {
return (Node)itemMgr.getItem(new NodeId(eventState.getParentUUID()));
}
/**
* @see Event#getChildItemName()
*/
public String getChildItemName() throws RepositoryException {
return eventState.getChildItemQName().toJCRName(ticket);
}
/**
* @see Event#getUserId()
*/
public String getUserId() {
return eventState.getUserId();
}
/**
* Returns a String representation of this <code>Event</code>.
* @return a String representation of this <code>Event</code>.
*/
public String toString() {
if (stringValue == null) {
StringBuffer sb = new StringBuffer();
sb.append("Event: Path: ");
try {
sb.append(getParentNode().getPath());
} catch (RepositoryException e) {
log.error("Exception retrieving path: " + e);
sb.append("[Error retrieving path]");
}
sb.append(", ").append(EventState.valueOf(getType())).append(": ");
try {
sb.append(getChildItemName());
} catch (RepositoryException e) {
log.error("Exception retrieving child item name: " + e);
sb.append("[Error retrieving child item name]");
}
sb.append(", UserId: ").append(getUserId());
stringValue = sb.toString();
}
return stringValue;
}
/**
* @see Object#hashCode()
*/
public int hashCode() {
return eventState.hashCode() ^ ticket.getUserId().hashCode();
}
/**
* Returns <code>true</code> if this <code>Event</code> is equal to another
* object.
* <p/>
* Two <code>Event</code> instances are equal if their respective
* <code>EventState</code> instances are equal and both <code>Event</code>
* instances are intended for the same <code>Ticket</code> that registerd
* the <code>EventListener</code>.
*
* @param obj the reference object with which to compare.
* @return <code>true</code> if this <code>Event</code> is equal to another
* object.
*/
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof EventImpl) {
EventImpl other = (EventImpl)obj;
return this.eventState.equals(other.eventState)
// FIXME rather use ticket.equals(other.ticket) ?
&& this.ticket.getUserId().equals(other.ticket.getUserId());
}
return false;
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: slide-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: slide-dev-help@jakarta.apache.org