use of javax.jcr.observation.EventIterator in project jackrabbit by apache.
the class Locked method with.
/**
* Executes the method {@link #run} within the scope of a lock held on
* <code>lockable</code>.
*
* @param lockable the node where the lock is obtained from.
* @param isDeep <code>true</code> if <code>lockable</code> will be locked
* deep.
* @param timeout time in milliseconds to wait at most to acquire the lock.
* @param isSessionScoped <code>true</code> if the lock is session scoped.
* @return the object returned by {@link #run} or {@link #TIMED_OUT} if the
* lock on <code>lockable</code> could not be acquired within the
* specified timeout.
* @throws IllegalArgumentException if <code>timeout</code> is negative or
* <code>lockable</code> is not
* <i>mix:lockable</i>.
* @throws RepositoryException if {@link #run} throws an exception.
* @throws UnsupportedRepositoryOperationException
* if this repository does not support
* locking.
* @throws InterruptedException if this thread is interrupted while
* waiting for the lock on node
* <code>lockable</code>.
*/
public Object with(Node lockable, boolean isDeep, long timeout, boolean isSessionScoped) throws UnsupportedRepositoryOperationException, RepositoryException, InterruptedException {
if (timeout < 0) {
throw new IllegalArgumentException("timeout must be >= 0");
}
Session session = lockable.getSession();
EventListener listener = null;
try {
// check whether the lockable can be locked at all
String mix = session.getNamespacePrefix(MIX);
if (!lockable.isNodeType(mix + ":lockable")) {
throw new IllegalArgumentException("Node is not lockable");
}
Lock lock = tryLock(lockable, isDeep, timeout, isSessionScoped);
if (lock != null) {
return runAndUnlock(lock);
}
if (timeout == 0) {
return TIMED_OUT;
}
long timelimit;
if (timeout == Long.MAX_VALUE) {
timelimit = Long.MAX_VALUE;
} else {
timelimit = System.currentTimeMillis() + timeout;
}
// node is locked by other session -> register event listener if possible
if (isObservationSupported(session)) {
ObservationManager om = session.getWorkspace().getObservationManager();
listener = new EventListener() {
public void onEvent(EventIterator events) {
synchronized (Locked.this) {
Locked.this.notify();
}
}
};
om.addEventListener(listener, Event.PROPERTY_REMOVED, lockable.getPath(), false, null, null, true);
}
// the current thread when the lockable node is possibly unlocked
for (; ; ) {
synchronized (this) {
lock = tryLock(lockable, isDeep, timeout, isSessionScoped);
if (lock != null) {
return runAndUnlock(lock);
} else {
// check timeout
if (System.currentTimeMillis() > timelimit) {
return TIMED_OUT;
}
if (listener != null) {
// event listener *should* wake us up, however
// there is a chance that removal of the lockOwner
// property is notified before the node is acutally
// unlocked. therefore we use a safety net to wait
// at most 1000 millis.
this.wait(Math.min(1000, timeout));
} else {
// repository does not support observation
// wait at most 50 millis then retry
this.wait(Math.min(50, timeout));
}
}
}
}
} finally {
if (listener != null) {
session.getWorkspace().getObservationManager().removeEventListener(listener);
}
}
}
use of javax.jcr.observation.EventIterator in project jackrabbit by apache.
the class CachingHierarchyManagerConsistencyTest method testObservation.
public void testObservation() throws Exception {
final List<Exception> exceptions = new ArrayList<Exception>();
Thread writer = new Thread(new Runnable() {
public void run() {
try {
long end = System.currentTimeMillis() + TEST_DURATION * 1000;
Session s = getHelper().getSuperuserSession();
try {
log.info("Starting to replace nodes");
int i = 0;
while (System.currentTimeMillis() < end) {
replaceNodes(s, i++);
}
} finally {
s.logout();
}
} catch (RepositoryException e) {
exceptions.add(e);
}
}
});
List<EventListener> listeners = new ArrayList<EventListener>();
for (int i = 0; i < NUM_LISTENERS; i++) {
final Session session = getHelper().getSuperuserSession();
listeners.add(new EventListener() {
public void onEvent(EventIterator events) {
while (events.hasNext()) {
Event event = events.nextEvent();
String path = "n/a";
try {
if (event.getType() == Event.NODE_ADDED || event.getType() == Event.PROPERTY_ADDED) {
path = event.getPath();
session.getItem(path);
}
} catch (PathNotFoundException e) {
// ignore
} catch (RepositoryException e) {
log.error(e.toString() + " Unable to get item with path: " + path);
exceptions.add(e);
}
}
}
});
}
for (EventListener listener : listeners) {
superuser.getWorkspace().getObservationManager().addEventListener(listener, ALL_EVENTS, "/", true, null, null, false);
}
writer.start();
writer.join();
for (EventListener listener : listeners) {
superuser.getWorkspace().getObservationManager().removeEventListener(listener);
}
log.info("" + exceptions.size() + " exception(s) occurred.");
if (!exceptions.isEmpty()) {
throw exceptions.get(0);
}
}
use of javax.jcr.observation.EventIterator in project jackrabbit by apache.
the class EventConsumer method consumeEvents.
/**
* Dispatches the events to the <code>EventListener</code>.
*
* @param events a collection of {@link EventState}s
* to dispatch.
*/
void consumeEvents(EventStateCollection events) throws RepositoryException {
// Set of ItemIds of denied ItemStates
Set<ItemId> denied = accessDenied.remove(events);
if (denied == null) {
denied = new HashSet<ItemId>();
}
// check permissions
for (Iterator<EventState> it = events.iterator(); it.hasNext() && session.isLive(); ) {
EventState state = it.next();
if (state.getType() == Event.NODE_ADDED || state.getType() == Event.PROPERTY_ADDED || state.getType() == Event.PROPERTY_CHANGED) {
ItemId targetId = state.getTargetId();
if (!canRead(state)) {
denied.add(targetId);
}
}
}
// only deliver if session is still live
if (!session.isLive()) {
return;
}
// check if filtered iterator has at least one event
EventIterator it = new FilteredEventIterator(session, events.iterator(), events.getTimestamp(), events.getUserData(), filter, denied, false);
if (it.hasNext()) {
long time = System.currentTimeMillis();
listener.onEvent(it);
time = System.currentTimeMillis() - time;
if (log.isDebugEnabled()) {
log.debug("listener {} processed events in {} ms.", listener.getClass().getName(), time);
}
} else {
// otherwise skip this listener
}
}
use of javax.jcr.observation.EventIterator in project jackrabbit by apache.
the class ListenerTracker method getTrackedListener.
public EventListener getTrackedListener() {
return new EventListener() {
@Override
public void onEvent(EventIterator events) {
eventDeliveries.incrementAndGet();
final long start = nanoTime();
try {
beforeEventDelivery();
listener.onEvent(new EventIteratorAdapter(events) {
long t0 = start;
private void recordTime(TimeSeriesRecorder recorder) {
recorder.getCounter().addAndGet(-(t0 - (t0 = nanoTime())));
}
@Override
public Object next() {
recordTime(eventConsumerTime);
eventsDelivered.incrementAndGet();
eventCount.getCounter().incrementAndGet();
Object object = super.next();
if (object instanceof JackrabbitEvent) {
object = new JackrabbitEventTracker(ListenerTracker.this, (JackrabbitEvent) object);
} else if (object instanceof Event) {
object = new EventTracker(ListenerTracker.this, (Event) object);
}
recordTime(eventProducerTime);
return object;
}
@Override
public boolean hasNext() {
recordTime(eventConsumerTime);
boolean result = super.hasNext();
recordTime(eventProducerTime);
return result;
}
});
} finally {
afterEventDelivery();
eventDeliveryTime.addAndGet(nanoTime() - start);
}
}
@Override
public String toString() {
return ListenerTracker.this.toString();
}
};
}
use of javax.jcr.observation.EventIterator in project jackrabbit by apache.
the class Locked method with.
/**
* Executes the method {@link #run} within the scope of a lock held on
* <code>lockable</code>.
*
* @param lockable the node where the lock is obtained from.
* @param isDeep <code>true</code> if <code>lockable</code> will be locked
* deep.
* @param timeout time in milliseconds to wait at most to aquire the lock.
* @return the object returned by {@link #run} or {@link #TIMED_OUT} if the
* lock on <code>lockable</code> could not be aquired within the
* specified timeout.
* @throws IllegalArgumentException if <code>timeout</code> is negative or
* <code>lockable</code> is not
* <i>mix:lockable</i>.
* @throws RepositoryException if {@link #run} throws an exception.
* @throws UnsupportedRepositoryOperationException
* if this repository does not support
* locking.
* @throws InterruptedException if this thread is interrupted while
* waiting for the lock on node
* <code>lockable</code>.
*/
public Object with(Node lockable, boolean isDeep, long timeout) throws UnsupportedRepositoryOperationException, RepositoryException, InterruptedException {
if (timeout < 0) {
throw new IllegalArgumentException("timeout must be >= 0");
}
Session session = lockable.getSession();
NamePathResolver resolver = new DefaultNamePathResolver(session);
Lock lock;
EventListener listener = null;
try {
// check whether the lockable can be locked at all
if (!lockable.isNodeType(resolver.getJCRName(NameConstants.MIX_LOCKABLE))) {
throw new IllegalArgumentException("Node is not lockable");
}
lock = tryLock(lockable, isDeep);
if (lock != null) {
return runAndUnlock(lock);
}
if (timeout == 0) {
return TIMED_OUT;
}
long timelimit;
if (timeout == Long.MAX_VALUE) {
timelimit = Long.MAX_VALUE;
} else {
timelimit = System.currentTimeMillis() + timeout;
}
// node is locked by other session -> register event listener if possible
if (isObservationSupported(session)) {
ObservationManager om = session.getWorkspace().getObservationManager();
listener = new EventListener() {
public void onEvent(EventIterator events) {
synchronized (this) {
this.notify();
}
}
};
om.addEventListener(listener, Event.PROPERTY_REMOVED, lockable.getPath(), false, null, null, true);
}
// the current thread when the lockable node is possibly unlocked
for (; ; ) {
synchronized (this) {
lock = tryLock(lockable, isDeep);
if (lock != null) {
return runAndUnlock(lock);
} else {
// check timeout
if (System.currentTimeMillis() > timelimit) {
return TIMED_OUT;
}
if (listener != null) {
// event listener *should* wake us up, however
// there is a chance that removal of the lockOwner
// property is notified before the node is acutally
// unlocked. therefore we use a safety net to wait
// at most 1000 millis.
this.wait(Math.min(1000, timeout));
} else {
// repository does not support observation
// wait at most 50 millis then retry
this.wait(Math.min(50, timeout));
}
}
}
}
} catch (NameException e) {
throw new RepositoryException(e);
} finally {
if (listener != null) {
session.getWorkspace().getObservationManager().removeEventListener(listener);
}
}
}
Aggregations