/*
* Copyright (C) 2009 eXo Platform SAS.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.exoplatform.services.jcr.api.observation;
import org.exoplatform.services.jcr.JcrAPIBaseTest;
import org.exoplatform.services.jcr.core.CredentialsImpl;
import org.exoplatform.services.jcr.impl.core.RepositoryImpl;
import org.exoplatform.services.jcr.observation.ExtendedEvent;
import org.exoplatform.services.log.Log;
import java.util.Calendar;
import java.util.Map;
import javax.jcr.Node;
import javax.jcr.Property;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.observation.Event;
import javax.jcr.observation.EventIterator;
import javax.jcr.observation.EventListener;
import javax.jcr.observation.EventListenerIterator;
import javax.jcr.observation.ObservationManager;
/**
* Created by The eXo Platform SAS.
*
* @author <a href="mailto:geaz@users.sourceforge.net">Gennady Azarenkov</a>
* @version $Id: TestObservationManager.java 15053 2008-06-02 10:31:38Z
* andrew00x $
*/
public class TestObservationManager extends JcrAPIBaseTest
{
private static int counter;
private Node testRoot;
public void setUp() throws Exception
{
super.setUp();
counter = 0;
testRoot = root.addNode("testRoot");
root.save();
}
public void tearDown() throws Exception
{
EventListenerIterator listeners = this.workspace.getObservationManager().getRegisteredEventListeners();
while (listeners.hasNext())
{
this.workspace.getObservationManager().removeEventListener(listeners.nextEventListener());
}
testRoot.remove();
root.save();
// testRoot.save();ipossible to call save() on removed node
super.tearDown();
}
public void testObtainObservationManager() throws RepositoryException
{
ObservationManager om = this.workspace.getObservationManager();
assertNotNull(om);
// Not the same as in ws
Session session2 = repository.login(credentials, "ws2");
ObservationManager om2 = session2.getWorkspace().getObservationManager();
assertNotNull(om2);
assertFalse(om.equals(om2));
}
public void testListenerRegistration() throws RepositoryException
{
ObservationManager observationManager = this.workspace.getObservationManager();
assertEquals(0, observationManager.getRegisteredEventListeners().getSize());
EventListener listener = new DummyListener(log);
observationManager.addEventListener(listener, Event.PROPERTY_ADDED | Event.NODE_ADDED, "/", true,
new String[]{"0"}, new String[]{"nt:base"}, false);
assertEquals(1, observationManager.getRegisteredEventListeners().getSize());
// [PN] 16.06.07
// Listener in observation manager is per session, global listeners is
// registered in observation
// registry.
// Listeners list can be acquired there (Impl level).
// Session session1 = repository.login(credentials,
// this.workspace.getName()); // the same ws
// ObservationManager observationManager1 =
// session1.getWorkspace().getObservationManager();
// assertEquals(1,
// observationManager1.getRegisteredEventListeners().getSize());
Session session2 = repository.login(credentials, "ws2"); // another ws
ObservationManager observationManager2 = session2.getWorkspace().getObservationManager();
assertEquals(0, observationManager2.getRegisteredEventListeners().getSize());
observationManager.removeEventListener(listener);
assertEquals(0, observationManager.getRegisteredEventListeners().getSize());
}
public void testNodeEventGeneration() throws RepositoryException
{
// ObservationManager observationManager =
// this.workspace.getObservationManager();
ObservationManager observationManager = repository.getSystemSession("ws").getWorkspace().getObservationManager();
EventListener listener = new DummyListener(log);
// Add/remove node by explicit path
observationManager.addEventListener(listener, Event.NODE_ADDED | Event.NODE_REMOVED, "/childNode", false, null,
null, false);
testRoot.addNode("childNode", "nt:unstructured");
testRoot.addNode("childNode1", "nt:unstructured");
root.save();
checkEventNumAndCleanCounter(0);
testRoot.getNode("childNode").remove();
testRoot.getNode("childNode1").remove();
testRoot.save();
checkEventNumAndCleanCounter(0);
observationManager.removeEventListener(listener);
// Add node by descendant path
observationManager.addEventListener(listener, Event.NODE_ADDED, "/", true, null, null, false);
testRoot.addNode("childNode", "nt:unstructured");
testRoot.addNode("childNode1", "nt:unstructured");
testRoot.save();
checkEventNumAndCleanCounter(2);
testRoot.getNode("childNode").remove();
testRoot.getNode("childNode1").remove();
testRoot.save();
checkEventNumAndCleanCounter(0); // no remove event
observationManager.removeEventListener(listener);
// Add node by node type
observationManager.addEventListener(listener, Event.NODE_ADDED, "/", true, null, new String[]{"nt:unstructured"},
false);
Node cn = testRoot.addNode("childNode", "nt:folder");
// associated parent is not 'nt:unstructured' - no event will be generated
cn.addNode("childNode1", "nt:hierarchyNode");
testRoot.save();
checkEventNumAndCleanCounter(1);
observationManager.removeEventListener(listener);
// Add node by UUID (never knows the UUID before adding :) )
observationManager.addEventListener(listener, Event.NODE_ADDED, "/", true, new String[]{"0"},
new String[]{"nt:unstructured"}, false);
testRoot.addNode("childNode", "nt:unstructured");
testRoot.save();
checkEventNumAndCleanCounter(0);
observationManager.removeEventListener(listener);
}
public void testRemoveNodeEvents() throws Exception
{
session.getWorkspace().getObservationManager().addEventListener(new DummyListener(log),
Event.NODE_ADDED | Event.NODE_REMOVED, "/", true, null, new String[]{"nt:file"}, false);
Node file = testRoot.addNode("test", "nt:file");
Node d = file.addNode("jcr:content", "nt:resource");
d.setProperty("jcr:mimeType", "text/plain");
d.setProperty("jcr:lastModified", Calendar.getInstance());
d.setProperty("jcr:data", "test content");
session.save();
checkEventNumAndCleanCounter(1);
file.remove();
session.save();
checkEventNumAndCleanCounter(1);
}
public void testMoveNodeEvents() throws Exception
{
DummyListener listener = new DummyListener(log);
session.getWorkspace().getObservationManager().addEventListener(listener,
ExtendedEvent.NODE_MOVED, "/", true, null, null, false);
Node n1 = testRoot.addNode("n1");
Node n2 = n1.addNode("n2");
Node n3 = testRoot.addNode("n3");
Node n4 = testRoot.addNode("n4");
n4.addNode("n5");
session.save();
session.move(n4.getPath(), n2.getPath());
session.save();
checkEventNumAndCleanCounter(1);
assertEquals("/testRoot/n4", listener.getInfo().get(ExtendedEvent.SRC_ABS_PATH));
assertEquals("/testRoot/n1/n2[2]", listener.getInfo().get(ExtendedEvent.DEST_ABS_PATH));
session.move(n1.getPath(), n3.getPath()+"/n6");
session.save();
checkEventNumAndCleanCounter(1);
assertEquals("/testRoot/n1", listener.getInfo().get(ExtendedEvent.SRC_ABS_PATH));
assertEquals("/testRoot/n3/n6", listener.getInfo().get(ExtendedEvent.DEST_ABS_PATH));
session.getWorkspace().move("/testRoot/n3/n6","/testRoot/n7");
checkEventNumAndCleanCounter(1);
assertEquals("/testRoot/n3/n6", listener.getInfo().get(ExtendedEvent.SRC_ABS_PATH));
assertEquals("/testRoot/n7", listener.getInfo().get(ExtendedEvent.DEST_ABS_PATH));
session.getWorkspace().move("/testRoot/n3","/testRoot/n7");
checkEventNumAndCleanCounter(1);
assertEquals("/testRoot/n3", listener.getInfo().get(ExtendedEvent.SRC_ABS_PATH));
assertEquals("/testRoot/n7[2]", listener.getInfo().get(ExtendedEvent.DEST_ABS_PATH));
}
public void testOrderNodeEvents() throws Exception
{
DummyListener listener = new DummyListener(log);
session.getWorkspace().getObservationManager().addEventListener(listener,
ExtendedEvent.NODE_MOVED, "/", true, null, null, false);
testRoot.addNode("n1");
testRoot.addNode("n2");
testRoot.addNode("n1");
testRoot.addNode("n3");
testRoot.addNode("n2");
testRoot.addNode("n4");
testRoot.save();
testRoot.orderBefore("n1[2]","n1");
session.save();
checkEventNumAndCleanCounter(1);
assertEquals("/testRoot/n1[2]", listener.getInfo().get(ExtendedEvent.SRC_CHILD_REL_PATH));
assertEquals("/testRoot/n1", listener.getInfo().get(ExtendedEvent.DEST_CHILD_REL_PATH));
testRoot.orderBefore("n2","n3");
session.save();
checkEventNumAndCleanCounter(0);
}
public void testPropertyEventGeneration() throws RepositoryException
{
ObservationManager observationManager = this.workspace.getObservationManager();
EventListener listener = new DummyListener(log);
if (log.isDebugEnabled())
log.debug("SET PROP>>");
// Add/remove node by explicit path
observationManager.addEventListener(listener, Event.PROPERTY_ADDED | Event.PROPERTY_CHANGED
| Event.PROPERTY_REMOVED, "/", true, null, null, false);
Node node = testRoot.addNode("childNode", "nt:unstructured");
Property prop = node.setProperty("prop", "prop");
root.save();
if (log.isDebugEnabled())
log.debug("SET PROP>>");
// SET /childNode/jcr:primaryType and /childNode/prop
checkEventNumAndCleanCounter(2);
prop.setValue("test1");
testRoot.save();
checkEventNumAndCleanCounter(1);
prop.remove();
testRoot.save();
checkEventNumAndCleanCounter(1);
observationManager.removeEventListener(listener);
}
/*
* public void testMultiEventGeneration() throws RepositoryException {
* ObservationManager observationManager =
* this.workspace.getObservationManager(); EventListener listener = new
* SimpleListener(log); observationManager.addEventListener(listener,
* Event.NODE_ADDED|Event.PROPERTY_ADDED
* |Event.PROPERTY_REMOVED|Event.NODE_REMOVED|Event.PROPERTY_CHANGED, "/",
* true, null, null, false); Node node = root.addNode("childNode",
* "nt:unstructured"); root.save(); Property prop = node.setProperty("prop",
* "test"); root.save(); checkAndCleanCounter(3); prop.setValue("test1");
* root.save(); checkAndCleanCounter(1); prop.remove(); root.save();
* checkAndCleanCounter(1); node.remove(); root.save();
* checkAndCleanCounter(1); observationManager.removeEventListener(listener);
* }
*/
public void testMultiListener() throws RepositoryException
{
ObservationManager observationManager = this.workspace.getObservationManager();
EventListener listener = new DummyListener(log);
EventListener listener1 = new DummyListener1(log);
observationManager.addEventListener(listener, Event.NODE_ADDED | Event.PROPERTY_ADDED | Event.PROPERTY_REMOVED
| Event.NODE_REMOVED | Event.PROPERTY_CHANGED, "/testRoot", true, null, null, false);
observationManager.addEventListener(listener1, Event.NODE_ADDED | Event.PROPERTY_ADDED | Event.PROPERTY_REMOVED
| Event.NODE_REMOVED | Event.PROPERTY_CHANGED, "/testRoot", false, null, null, false);
Node node = testRoot.addNode("childNode", "nt:unstructured");
root.save();
Property prop = testRoot.setProperty("prop", "test");
root.save();
checkEventNumAndCleanCounter(5); // 3 by Dy listener + 2 by listener1
observationManager.removeEventListener(listener);
observationManager.removeEventListener(listener1);
}
public void testCloneEvents() throws RepositoryException
{
ObservationManager observationManager = this.workspace.getObservationManager();
Session session2 = repository.login(credentials, "ws2");
Node root = session2.getRootNode();
Node node = root.addNode("testCloneEvents");
node.addMixin("mix:referenceable");
session2.save();
// Node node = testRoot.addNode("testCloneEvents", "nt:unstructured");
session.save();
checkEventNumAndCleanCounter(0);
EventListener listener = new DummyListener(log);
observationManager.addEventListener(listener, Event.NODE_ADDED | Event.PROPERTY_ADDED | Event.PROPERTY_REMOVED
| Event.NODE_REMOVED | Event.PROPERTY_CHANGED, "/", true, null, null, false);
session.getWorkspace().clone("ws2", "/testCloneEvents", "/testRoot/testCloneEvents", true);
checkEventNumAndCleanCounter(4);
observationManager.removeEventListener(listener);
}
public void testRemoveSourceNodeEvents() throws RepositoryException
{
ObservationManager observationManager = this.workspace.getObservationManager();
testRoot.addNode("testRemoveSourceNode");
EventListener listener = new RemoveDummyListener(log, this.repository, this.credentials);
observationManager.addEventListener(listener, Event.NODE_ADDED, "/", true, null, null, false);
root.save();
Session session2 = repository.login(credentials, "ws2");
Session session = repository.login(credentials, "ws");
assertFalse(session.itemExists("/testRoot/testRemoveSourceNode"));
assertTrue(session2.itemExists("/testRemoveSourceNode"));
observationManager.removeEventListener(listener);
}
public void testWithAnUnknownNodeType() throws RepositoryException
{
ObservationManager observationManager = this.workspace.getObservationManager();
checkEventNumAndCleanCounter(0);
EventListener listener = new DummyListener(log);
try
{
observationManager.addEventListener(listener, Event.NODE_ADDED, "/", true, null, new String[]{"nt:anUnknownNodeType"}, false);
testRoot.addNode("testWithAnUnknownNodeType");
root.save();
checkEventNumAndCleanCounter(0);
}
finally
{
observationManager.removeEventListener(listener);
}
}
private void checkEventNumAndCleanCounter(int cnt)
{
assertEquals(cnt, counter);
counter = 0;
}
private static class DummyListener implements EventListener
{
private Log log;
private Map<String, String> info ;
public DummyListener(Log log)
{
this.log = log;
}
public void onEvent(EventIterator events)
{
while (events.hasNext())
{
Event event = events.nextEvent();
counter++;
if(event.getType()== ExtendedEvent.NODE_MOVED)
{
try
{
info=((ExtendedEvent)event).getInfo();
}
catch (RepositoryException e)
{
log.error(e.getMessage(),e);
}
}
try
{
if (log.isDebugEnabled())
log.debug("EVENT fired by SimpleListener " + event.getPath() + " " + event.getType());
}
catch (RepositoryException e)
{
e.printStackTrace();
}
}
}
public Map<String, String> getInfo()
{
return info;
}
}
private static class DummyListener1 implements EventListener
{
private Log log;
public DummyListener1(Log log)
{
this.log = log;
}
public void onEvent(EventIterator events)
{
while (events.hasNext())
{
Event event = events.nextEvent();
counter++;
if (log.isDebugEnabled())
log.debug("EVENT fired by SimpleListener-1 " + event + " " + event.getType());
}
}
}
private static class RemoveDummyListener implements EventListener
{
protected Log log;
protected RepositoryImpl repository;
protected CredentialsImpl credentials;
public RemoveDummyListener(Log log, RepositoryImpl repository, CredentialsImpl credentials)
{
this.log = log;
this.repository = repository;
this.credentials = credentials;
}
public void onEvent(EventIterator events)
{
while (events.hasNext())
{
Event event = events.nextEvent();
counter++;
try
{
String path = event.getPath();
Session session2 = repository.login(credentials, "ws2");
session2.getWorkspace().clone("ws", path, "/testRemoveSourceNode", true);
Session session = repository.login(credentials, "ws");
session.getItem(path).remove();
session.save();
}
catch (RepositoryException re)
{
System.out.println(re.getMessage());
if (log.isErrorEnabled())
{
log.error(re.getMessage());
}
}
if (log.isDebugEnabled())
log.debug("EVENT fired by RemoveDummyListener " + event + " " + event.getType());
}
}
}
}