Permalink
Browse files

MODE-782 A fix that will work even when the events in the change set …

…are within multiple workspaces (as is sometimes the case), and augments the existing JcrObservationManagerTest case with a test to ensure that a session's listeners only see the events emanating from that session's workspace.

git-svn-id: https://svn.jboss.org/repos/modeshape/trunk@1877 76366958-4244-0410-ad5e-bbfabb93f86b
  • Loading branch information...
1 parent 323c58e commit 677e8edb58de481761b2aa0f03347f7a7d537e25 Randall Hauch committed Jun 7, 2010
View
@@ -78,3 +78,6 @@
/extensions/modeshape-sequencer-zip/target
/tools/org.modeshape.eclipse.jcr.rest.client/bin
+
+# Directory created by Eclipse
+/RemoteSystemsTempFiles
@@ -90,6 +90,11 @@
*/
private final ValueFactories valueFactories;
+ /**
+ * The name of the session's workspace; cached for performance reasons.
+ */
+ private final String workspaceName;
+
/**
* @param session the owning session (never <code>null</code>)
* @param repositoryObservable the repository observable used to register JCR listeners (never <code>null</code>)
@@ -105,6 +110,7 @@ public JcrObservationManager( JcrSession session,
this.listeners = new ConcurrentHashMap<EventListener, JcrListenerAdapter>();
this.namespaceRegistry = this.session.getExecutionContext().getNamespaceRegistry();
this.valueFactories = this.session.getExecutionContext().getValueFactories();
+ this.workspaceName = this.session.getWorkspace().getName();
}
/**
@@ -193,6 +199,13 @@ String getSessionId() {
return this.session.sessionId();
}
+ /**
+ * @return workspaceName
+ */
+ final String getWorkspaceName() {
+ return workspaceName;
+ }
+
/**
* Remove all of the listeners. This is typically called when the {@link JcrSession#logout() session logs out}.
*/
@@ -698,6 +711,10 @@ public void notify( Changes changes ) {
// loop through changes saving the parent locations of the changed locations
for (ChangeRequest request : changes.getChangeRequests()) {
+ // ignore all events other than those on this workspace ...
+ if (!getWorkspaceName().equals(request.changedWorkspace())) {
+ continue;
+ }
Path changedPath = request.changedLocation().getPath();
Path parentPath = changedPath.getParent();
changedLocations.add(Location.create(parentPath));
@@ -725,6 +742,11 @@ protected void notify( NetChanges netChanges ) {
Collection<Event> events = new ArrayList<Event>();
for (NetChange change : netChanges.getNetChanges()) {
+ // ignore all events other than those on this workspace ...
+ if (!getWorkspaceName().equals(change.getRepositoryWorkspaceName())) {
+ continue;
+ }
+
// ignore if lock/unlock
if (change.includes(ChangeType.NODE_LOCKED) || change.includes(ChangeType.NODE_UNLOCKED)) {
continue;
@@ -113,10 +113,15 @@ public static void beforeClass() {
// ===========================================================================================================================
// Fields
// ===========================================================================================================================
+ protected static final String WORKSPACE = "ws1";
+ protected static final String WORKSPACE2 = "ws2";
+ protected static final String REPOSITORY = "r1";
+ protected static final String SOURCE = "store";
private JcrEngine engine;
private Session session;
private Node testRootNode;
+ private List<Session> sessions;
// ===========================================================================================================================
// Methods
@@ -140,26 +145,49 @@ TestListener addListener( int eventsExpected,
String[] uuids,
String[] nodeTypeNames,
boolean noLocal ) throws Exception {
+ return addListener(this.session, eventsExpected, numIterators, eventTypes, absPath, isDeep, uuids, nodeTypeNames, noLocal);
+ }
+
+ TestListener addListener( Session session,
+ int eventsExpected,
+ int eventTypes,
+ String absPath,
+ boolean isDeep,
+ String[] uuids,
+ String[] nodeTypeNames,
+ boolean noLocal ) throws Exception {
+ return addListener(session, eventsExpected, 1, eventTypes, absPath, isDeep, uuids, nodeTypeNames, noLocal);
+ }
+
+ TestListener addListener( Session session,
+ int eventsExpected,
+ int numIterators,
+ int eventTypes,
+ String absPath,
+ boolean isDeep,
+ String[] uuids,
+ String[] nodeTypeNames,
+ boolean noLocal ) throws Exception {
TestListener listener = new TestListener(eventsExpected, numIterators, eventTypes);
- this.session.getWorkspace().getObservationManager().addEventListener(listener,
- eventTypes,
- absPath,
- isDeep,
- uuids,
- nodeTypeNames,
- noLocal);
+ session.getWorkspace().getObservationManager().addEventListener(listener,
+ eventTypes,
+ absPath,
+ isDeep,
+ uuids,
+ nodeTypeNames,
+ noLocal);
return listener;
}
@After
public void afterEach() {
try {
- if (this.session != null) {
- this.session.logout();
+ for (Session session : sessions) {
+ if (session != null && session.isLive()) session.logout();
}
} finally {
this.session = null;
-
+ this.sessions.clear();
try {
this.engine.shutdown();
} finally {
@@ -170,14 +198,13 @@ public void afterEach() {
@Before
public void beforeEach() throws RepositoryException {
- final String WORKSPACE = "ws1";
- final String REPOSITORY = "r1";
- final String SOURCE = "store";
+ sessions = new ArrayList<Session>();
JcrConfiguration config = new JcrConfiguration();
config.repositorySource("store")
.usingClass(InMemoryRepositorySource.class)
.setRetryLimit(100)
+ .setProperty("predefinedWorkspaceNames", new String[] {WORKSPACE, WORKSPACE2})
.setProperty("defaultWorkspaceName", WORKSPACE);
config.repository(REPOSITORY).setSource(SOURCE).setOption(Option.JAAS_LOGIN_CONFIG_NAME, "modeshape-jcr");
config.save();
@@ -187,14 +214,25 @@ public void beforeEach() throws RepositoryException {
this.engine.start();
// Create repository and session
- Repository repository = this.engine.getRepository(REPOSITORY);
- Credentials credentials = new SimpleCredentials(USER_ID, USER_ID.toCharArray());
- this.session = repository.login(credentials, WORKSPACE);
+ this.session = login(REPOSITORY, WORKSPACE, USER_ID, USER_ID.toCharArray());
this.testRootNode = this.session.getRootNode().addNode("testroot", UNSTRUCTURED);
save();
}
+ protected Session login( String repositoryName,
+ String workspaceName,
+ String userId,
+ char[] password ) throws RepositoryException {
+ Repository repository = this.engine.getRepository(repositoryName);
+ Credentials credentials = new SimpleCredentials(userId, password);
+ Session session = repository.login(credentials, workspaceName);
+ if (session != null) {
+ sessions.add(session);
+ }
+ return session;
+ }
+
void checkResults( TestListener listener ) {
if (listener.getActualEventCount() != listener.getExpectedEventCount()) {
// Wrong number ...
@@ -1643,6 +1681,42 @@ public void shouldTestWorkspaceOperationTest_testRename() throws Exception {
+ ", expected=" + oldPath, containsPath(removeNodeListener, oldPath));
}
+ @Test
+ public void shouldNotReceiveEventsFromOtherWorkspaces() throws Exception {
+ // Log into a second workspace ...
+ Session session2 = login(REPOSITORY, "ws2", USER_ID, USER_ID.toCharArray());
+
+ // Register 2 listeners in the first session ...
+ TestListener listener1 = addListener(session, 4, ALL_EVENTS, "/", true, null, null, false);
+ TestListener addListener1 = addListener(session, 1, Event.NODE_ADDED, "/", true, null, null, false);
+
+ // Register 2 listeners in the second session ...
+ TestListener listener2 = addListener(session2, 0, ALL_EVENTS, "/", true, null, null, false);
+ TestListener addListener2 = addListener(session2, 0, Event.NODE_ADDED, "/", true, null, null, false);
+
+ // Add a node to the first session ...
+ session.getRootNode().addNode("nodeA", "nt:unstructured");
+ session.save();
+
+ // Wait for the events on the first session's listeners (that should get the events) ...
+ listener1.waitForEvents();
+ addListener1.waitForEvents();
+ removeListener(listener1);
+ removeListener(addListener1);
+
+ // Wait for the events on the second session's listeners (that should NOT get the events) ...
+ listener2.waitForEvents();
+ // addListener2.waitForEvents();
+ removeListener(listener2);
+ removeListener(addListener2);
+
+ // Verify the expected events were received ...
+ checkResults(listener1);
+ checkResults(addListener1);
+ checkResults(listener2);
+ checkResults(addListener2);
+ }
+
// ===========================================================================================================================
// Inner Class
// ===========================================================================================================================

0 comments on commit 677e8ed

Please sign in to comment.