/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * 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.jackrabbit.test.api.observation; import org.apache.jackrabbit.test.NotExecutableException; import javax.jcr.observation.Event; import javax.jcr.RepositoryException; import javax.jcr.Node; import javax.jcr.Session; /** * Tests the options for addEventListener(). * <p> * Configuration requirements: * <p> * The {@link #testRoot} must allow child nodes of type {@link #testNodeType}. * The child nodes that are created will be named {@link #nodeName1} and * {@link #nodeName2}. Furthermore {@link #testNodeType} must allow to add * child nodes of the same type ({@link #testNodeType}). * <p> * Certain test require that {@link #testNodeType} is mix:referenceable or * allows to add that mixin. If the repository does not support mix:referenceable * a {@link org.apache.jackrabbit.test.NotExecutableException} is thrown * in those test cases. * */ public class AddEventListenerTest extends AbstractObservationTest { /** * Tests if events are only created for a sub tree of the workspace. */ public void testPath() throws RepositoryException { EventResult listener = new EventResult(log); obsMgr.addEventListener(listener, Event.NODE_ADDED, testRoot + "/" + nodeName1, true, null, null, false); Node n = testRootNode.addNode(nodeName1, testNodeType); n.addNode(nodeName2, testNodeType); testRootNode.getSession().save(); Event[] events = listener.getEvents(DEFAULT_WAIT_TIMEOUT); obsMgr.removeEventListener(listener); checkNodeAdded(events, new String[]{nodeName1 + "/" + nodeName2}, null); } /** * Tests if {@link javax.jcr.observation.Event#NODE_ADDED} is created only * for the specified path if <code>isDeep</code> is <code>false</code>. */ public void testIsDeepFalseNodeAdded() throws RepositoryException { EventResult listener = new EventResult(log); obsMgr.addEventListener(listener, Event.NODE_ADDED, testRoot + "/" + nodeName1, false, null, null, false); Node n = testRootNode.addNode(nodeName1, testNodeType); n.addNode(nodeName2, testNodeType); testRootNode.getSession().save(); Event[] events = listener.getEvents(DEFAULT_WAIT_TIMEOUT); obsMgr.removeEventListener(listener); checkNodeAdded(events, new String[]{nodeName1 + "/" + nodeName2}, null); } /** * Tests if {@link javax.jcr.observation.Event#PROPERTY_ADDED} is created only * for the specified path if <code>isDeep</code> is <code>false</code>. */ public void testIsDeepFalsePropertyAdded() throws RepositoryException { Node n1 = testRootNode.addNode(nodeName1, testNodeType); Node n2 = testRootNode.addNode(nodeName2, testNodeType); testRootNode.getSession().save(); EventResult listener = new EventResult(log); obsMgr.addEventListener(listener, Event.PROPERTY_ADDED, testRoot + "/" + nodeName1, false, null, null, false); n1.setProperty(propertyName1, "foo"); n2.setProperty(propertyName1, "foo"); testRootNode.getSession().save(); Event[] events = listener.getEvents(DEFAULT_WAIT_TIMEOUT); obsMgr.removeEventListener(listener); checkPropertyAdded(events, new String[]{nodeName1 + "/" + propertyName1}); } /** * Tests if no events are generated for own modifications if * <code>noLocal</code> is set to <code>true</code>. */ public void testNoLocalTrue() throws RepositoryException { EventResult listener = new EventResult(log); obsMgr.addEventListener(listener, Event.NODE_ADDED, testRoot, true, null, null, true); // noLocal testRootNode.addNode(nodeName1, testNodeType); testRootNode.getSession().save(); // only wait one second because we don't expect any event Event[] events = listener.getEvents(1000); obsMgr.removeEventListener(listener); assertEquals("EventListener must not receive own modification when noLocal=true", 0, events.length); } /** * Tests if events are only generated for specified UUIDs. */ public void testUUID() throws RepositoryException, NotExecutableException { Node n1 = null; Node n2 = null; try { n1 = createReferenceable(nodeName1, testNodeType); n2 = createReferenceable(nodeName2, testNodeType); } catch (RepositoryException e) { throw new NotExecutableException("Repository does not support mix:referenceable"); } testRootNode.getSession().save(); EventResult listener = new EventResult(log); obsMgr.addEventListener(listener, Event.PROPERTY_ADDED, testRoot, true, new String[]{n1.getIdentifier()}, null, false); n1.setProperty(propertyName1, "foo"); n2.setProperty(propertyName1, "foo"); testRootNode.getSession().save(); Event[] events = listener.getEvents(DEFAULT_WAIT_TIMEOUT); obsMgr.removeEventListener(listener); checkPropertyAdded(events, new String[]{nodeName1 + "/" + propertyName1}); } /** * Tests if events are only generated for specified node types. */ public void testNodeType() throws RepositoryException { String nodetype2 = getProperty("nodetype2"); EventResult listener = new EventResult(log); Node n1 = testRootNode.addNode(nodeName1, testNodeType); Node n2 = testRootNode.addNode(nodeName2, nodetype2); testRootNode.getSession().save(); obsMgr.addEventListener(listener, Event.NODE_ADDED, testRoot, true, null, new String[]{testNodeType}, false); Session s = getHelper().getSuperuserSession(); try { Node n = (Node) s.getItem(n1.getPath()); n.addNode(nodeName3, testNodeType); n = (Node) s.getItem(n2.getPath()); n.addNode(nodeName3, nodetype2); n = (Node) s.getItem(testRoot); n.save(); } finally { s.logout(); } Event[] events = listener.getEvents(DEFAULT_WAIT_TIMEOUT); obsMgr.removeEventListener(listener); checkNodeAdded(events, new String[]{nodeName1 + "/" + nodeName3}, null); } //-------------------------< internal >------------------------------------- /** * Creates a node with name <code>nodeName</code> with type * <code>nodeType</code> as a child node of {@link #testRootNode}. * If the created node is not of type mix:referenceable a mixin is added * of that type. * * @param nodeName the node name. * @param nodeType the node type of the node to create. * @return the created node * @throws RepositoryException if node creation fails. */ private Node createReferenceable(String nodeName, String nodeType) throws RepositoryException, NotExecutableException { Node n = testRootNode.addNode(nodeName, nodeType); ensureMixinType(n, mixReferenceable); testRootNode.getSession().save(); return n; } }