org.apache.jackrabbit.test.api.SessionTest Maven / Gradle / Ivy
/*
* 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;
import javax.jcr.InvalidItemStateException;
import javax.jcr.ItemExistsException;
import javax.jcr.Node;
import javax.jcr.PathNotFoundException;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.Value;
import javax.jcr.lock.LockException;
import javax.jcr.nodetype.ConstraintViolationException;
import org.apache.jackrabbit.test.AbstractJCRTest;
import org.apache.jackrabbit.test.NotExecutableException;
/**
* SessionTest
contains all test cases for the
* javax.jcr.Session
class that are level 2 (modifing repository
* content).
*
*/
public class SessionTest extends AbstractJCRTest {
/**
* Tries to move a node using {@link javax.jcr.Session#move(String src, String dest)}
* to a location where a node already exists with
* same name.
*
* Prerequisites:
*
* javax.jcr.tck.SessionTest.testMoveItemExistsException.nodetype2
* must contain name of a nodetype that does not allow same name sibling
* child nodes.
* javax.jcr.tck.SessionTest.testMoveItemExistsException.nodetype3
* must contain name of a valid nodetype that can be added as a child of
* nodetype2
*
*
* This should throw an {@link javax.jcr.ItemExistsException}.
*/
public void testMoveItemExistsException() throws RepositoryException {
// get default workspace test root node using superuser session
Node defaultRootNode = (Node) superuser.getItem(testRootNode.getPath());
// create parent node
Node srcParentNode = defaultRootNode.addNode(nodeName1, testNodeType);
// create node to move
Node moveNode = srcParentNode.addNode(nodeName2, getProperty("nodetype3"));
// create a second node that will serve as new parent, must use a nodetype that does not allow
// same name siblings
Node destParentNode = defaultRootNode.addNode(nodeName3, getProperty("nodetype2"));
// add a valid child
Node destNode = destParentNode.addNode(nodeName2, getProperty("nodetype3"));
// save the new nodes
superuser.save();
try {
// move the node
superuser.move(moveNode.getPath(), destNode.getPath());
fail("Moving a node using Session.move() to a location where a node with same name already exists must throw ItemExistsException");
} catch (ItemExistsException e) {
// ok, works as expected
}
}
/**
* Calls {@link javax.jcr.Session#move(String src, String dest)}
* with invalid destination path.
*
* Should throw a {@link javax.jcr.PathNotFoundException}.
*/
public void testMovePathNotFoundExceptionDestInvalid() throws RepositoryException {
// get default workspace test root node using superuser session
Node defaultRootNode = (Node) superuser.getItem(testRootNode.getPath());
// create parent node
Node srcParentNode = defaultRootNode.addNode(nodeName1, testNodeType);
// create node to move
Node moveNode = srcParentNode.addNode(nodeName2, testNodeType);
// save the new nodes
superuser.save();
// move the node
try {
superuser.move(moveNode.getPath(), defaultRootNode.getPath() + "/" + nodeName2 + "/" + nodeName1);
fail("Invalid destination path during Session.move() must throw PathNotFoundException");
} catch (PathNotFoundException e) {
// ok, works as expected
}
}
/**
* Calls {@link javax.jcr.Session#move(String src, String dest)} with
* invalid source path.
*
* Should throw a {@link javax.jcr.PathNotFoundException}.
*/
public void testMovePathNotFoundExceptionSrcInvalid() throws RepositoryException {
// get default workspace test root node using superuser session
Node defaultRootNode = (Node) superuser.getItem(testRootNode.getPath());
// create a node that will serve as new parent
Node destParentNode = defaultRootNode.addNode(nodeName3, testNodeType);
// save the new nodes
superuser.save();
// move the node
try {
superuser.move(defaultRootNode.getPath() + "/" + nodeName1, destParentNode.getPath() + "/" + nodeName2);
fail("Invalid source path during Session.move() must throw PathNotFoundException");
} catch (PathNotFoundException e) {
// ok. works as expected
}
}
/**
* Calls {@link javax.jcr.Session#move(String src, String dest)}
* with a destination path that has an index postfixed.
*
* This should throw a {@link javax.jcr.RepositoryException}.
*/
public void testMoveRepositoryException() throws RepositoryException {
// get default workspace test root node using superuser session
Node defaultRootNode = (Node) superuser.getItem(testRootNode.getPath());
// create parent node
Node srcParentNode = defaultRootNode.addNode(nodeName1, testNodeType);
// create node to be moved
Node moveNode = srcParentNode.addNode(nodeName2, testNodeType);
// create a node that will serve as new parent
Node destParentNode = defaultRootNode.addNode(nodeName3, testNodeType);
// save the new nodes
superuser.save();
// move the node
try {
superuser.move(moveNode.getPath(), destParentNode.getPath() + "/" + nodeName2 + "[1]");
fail("If destination path of Session.move() contains an index as postfix it must throw RepositoryException");
} catch (RepositoryException e) {
// ok works as expected
}
}
/**
* Moves a node using {@link javax.jcr.Session#move(String src, String dest)},
* afterwards it tries to only save the old parent node.
*
* This should throw {@link javax.jcr.nodetype.ConstraintViolationException}.
*
* Prerequisites:
javax.jcr.tck.nodetype
* must accept children of same nodetype
*/
public void testMoveConstraintViolationExceptionSrc() throws RepositoryException {
// get default workspace test root node using superuser session
Node defaultRootNode = (Node) superuser.getItem(testRootNode.getPath());
// create parent node
Node srcParentNode = defaultRootNode.addNode(nodeName1, testNodeType);
// create node to be moved
Node moveNode = srcParentNode.addNode(nodeName2, testNodeType);
// create a node that will serve as new parent
Node destParentNode = defaultRootNode.addNode(nodeName3, testNodeType);
// save the new nodes
superuser.save();
// move the node
superuser.move(moveNode.getPath(), destParentNode.getPath() + "/" + nodeName2);
// save only old parent node
try {
srcParentNode.save();
fail("Saving only the source parent node after a Session.move() operation must throw ConstraintViolationException");
} catch (ConstraintViolationException e) {
// ok both work as expected
}
}
/**
* Moves a node using {@link javax.jcr.Session#move(String src, String dest)},
* afterwards it tries to only save the destination parent
* node.
*
* This should throw a {@link javax.jcr.nodetype.ConstraintViolationException}.
*
* Prerequisites:
javax.jcr.tck.nodetype
* must accept children of same nodetype
*/
public void testMoveConstraintViolationExceptionDest() throws RepositoryException {
// get default workspace test root node using superuser session
Node defaultRootNode = (Node) superuser.getItem(testRootNode.getPath());
// create parent node
Node srcParentNode = defaultRootNode.addNode(nodeName1, testNodeType);
// create node to be moved
Node moveNode = srcParentNode.addNode(nodeName2, testNodeType);
// create a node that will serve as new parent
Node destParentNode = defaultRootNode.addNode(nodeName3, testNodeType);
// save the new nodes
superuser.save();
// move the node
superuser.move(moveNode.getPath(), destParentNode.getPath() + "/" + nodeName2);
// save only moved node
try {
destParentNode.save();
fail("Saving only moved node after a Session.move() operation should throw ConstraintViolationException");
} catch (ConstraintViolationException e) {
// ok try to save the source
}
}
/**
* Calls {@link javax.jcr.Session#move(String src, String dest)} where
* the parent node of src is locked.
*
* Should throw a {@link LockException} immediately or on save.
*/
public void testMoveLockException()
throws NotExecutableException, RepositoryException {
Session session = superuser;
if (!isSupported(Repository.OPTION_LOCKING_SUPPORTED)) {
throw new NotExecutableException("Locking is not supported.");
}
// create a node that is lockable
Node lockableNode = testRootNode.addNode(nodeName1, testNodeType);
// or try to make it lockable if it is not
ensureMixinType(lockableNode, mixLockable);
// add a sub node (the one that is tried to move later on)
Node srcNode = lockableNode.addNode(nodeName1, testNodeType);
testRootNode.getSession().save();
// remove first slash of path to get rel path to root
String pathRelToRoot = lockableNode.getPath().substring(1);
// access node through another session to lock it
Session session2 = getHelper().getSuperuserSession();
try {
Node node2 = session2.getRootNode().getNode(pathRelToRoot);
node2.lock(true, true);
try {
String destPath = testRoot + "/" + nodeName2;
session.move(srcNode.getPath(), destPath);
testRootNode.getSession().save();
fail("A LockException is thrown either immediately or on save if a lock prevents the move.");
} catch (LockException e){
// success
}
} finally {
session2.logout();
}
}
/**
* Checks if {@link javax.jcr.Session#move(String src, String dest)}
* works properly. To verify if node has been moved properly
* it uses a second session to retrieve the moved node.
*
* Prerequisites:
javax.jcr.tck.nodetype
* must accept children of same nodetype
*/
public void testMoveNode() throws RepositoryException {
// get default workspace test root node using superuser session
Node defaultRootNode = (Node) superuser.getItem(testRootNode.getPath());
// create parent node
Node srcParentNode = defaultRootNode.addNode(nodeName1, testNodeType);
// create node to be moved
Node moveNode = srcParentNode.addNode(nodeName2, testNodeType);
// create a node that will serve as new parent
Node destParentNode = defaultRootNode.addNode(nodeName3, testNodeType);
// save the new nodes
superuser.save();
//move the nodes
superuser.move(moveNode.getPath(), destParentNode.getPath() + "/" + nodeName2);
superuser.save();
// get moved tree root node with session 2
Session testSession = getHelper().getReadWriteSession();
try {
testSession.getItem(destParentNode.getPath() + "/" + nodeName2);
// node found
} finally {
testSession.logout();
}
}
/**
* Checks if a newly created node gets properly saved using {@link
* javax.jcr.Session#save()}
.
*
* It creates a new node, saves
* it using session.save()
then uses a different session to
* verify if the node has been properly saved.
*/
public void testSaveNewNode() throws RepositoryException {
// get default workspace test root node using superuser session
Node defaultRootNode = (Node) superuser.getItem(testRootNode.getPath());
// create a node
Node newNode = defaultRootNode.addNode(nodeName1, testNodeType);
// save changes
superuser.save();
// use a different session to verify if the node is there
Session s = getHelper().getReadOnlySession();
try {
s.getItem(newNode.getPath());
// throws PathNotFoundException if item was not saved
} finally {
s.logout();
}
}
/**
* Checks if a modified node gets properly saved using {@link
* javax.jcr.Session#save()}
.
*
* It creates a new node, saves
* it using session.save()
, modifies the node by adding a child
* node, saves again and finally verifies with a different session if
* changes have been stored properly.
*
* Prerequisites:
* javax.jcr.tck.nodetype
must accept children of same
* nodetype
*/
public void testSaveModifiedNode() throws RepositoryException {
// get default workspace test root node using superuser session
Node defaultRootNode = (Node) superuser.getItem(testRootNode.getPath());
// create a node
Node newNode = defaultRootNode.addNode(nodeName1, testNodeType);
// save new node
superuser.save();
// and add a child node
newNode.addNode(nodeName2, testNodeType);
// save the changes
superuser.save();
// check if the child node was created properly
// get a reference with a second session to the modified node
Session s = getHelper().getReadOnlySession();
try {
Node newNodeSession2 = (Node) s.getItem(newNode.getPath());
// check if child is there
assertTrue("Modifications on a node are not save after Session.save()", newNodeSession2.hasNode(nodeName2));
} finally {
s.logout();
}
}
/**
* Tries to create and save a node using {@link javax.jcr.Session#save()}
* with an mandatory property that is not set on saving time.
*
* Prerequisites:
javax.jcr.tck.SessionTest.testSaveConstraintViolationException.nodetype2
* must reference a nodetype that has one at least one property that is
* mandatory but not autocreated
*/
public void testSaveConstraintViolationException() throws RepositoryException {
// get default workspace test root node using superuser session
Node defaultRootNode = (Node) superuser.getItem(testRootNode.getPath());
// create a node with at least one mandatory, not autocreated property
defaultRootNode.addNode(nodeName1, getProperty("nodetype2"));
// save changes
try {
superuser.save();
fail("Trying to use Session.save() with a node that has a mandatory property not set, should throw ConstraintViolationException");
} catch (ConstraintViolationException e) {
// ok
}
}
/**
* Tries to save a node using {@link javax.jcr.Session#save()} that was
* already deleted by an other session.
*
* Procedure:
* - Creates a new node with session 1, saves it, adds a child node.
* - Access new node with session 2,deletes the node, saves it.
* - session 1 tries to save modifications .
This should throw
* an {@link javax.jcr.InvalidItemStateException}.
*
* Prerequisites:
*
javax.jcr.tck.nodetype
must accept children of same
* nodetype
*/
public void testSaveInvalidStateException() throws RepositoryException {
// get default workspace test root node using superuser session
Node defaultRootNode = (Node) superuser.getItem(testRootNode.getPath());
// create a node
Node nodeSession1 = defaultRootNode.addNode(nodeName1, testNodeType);
// save new node
superuser.save();
// make a modification
nodeSession1.addNode(nodeName2, testNodeType);
// get the new node with a different session
Session testSession = getHelper().getReadWriteSession();
try {
Node nodeSession2 = (Node) testSession.getItem(nodeSession1.getPath());
// delete the node with the new session
nodeSession2.remove();
// make node removal persistent
testSession.save();
// save changes made with superuser session
try {
superuser.save();
fail("Saving a modified Node using Session.save() already deleted by an other session should throw InvalidItemStateException");
} catch (InvalidItemStateException e) {
// ok, works as expected
}
} finally {
testSession.logout();
}
}
/**
* Checks if {@link javax.jcr.Session#refresh(boolean refresh)} works
* properly with refresh
set to false
.
*
* Procedure:
- Creates two nodes with session 1
- Modifies
* node 1 with session 1 by adding a child node
- Get node 2 with
* session 2
- Modifies node 2 with session 2 by adding a child
* node
- saves session 2 changes using {@link
* javax.jcr.Session#save()}
- calls
Session.refresh(false)
* on session 1
Session 1 changes should be cleared and session 2
* changes should now be visible to session 1.
*
* Prerequisites:
* javax.jcr.tck.nodetype
must accept children of same
* nodetype
*/
public void testRefreshBooleanFalse() throws RepositoryException {
// get default workspace test root node using superuser session
Node defaultRootNode = (Node) superuser.getItem(testRootNode.getPath());
// create a node
Node testNode1Session1 = defaultRootNode.addNode(nodeName1, testNodeType);
// create a second node
Node testNode2Session1 = defaultRootNode.addNode(nodeName2, testNodeType);
// save the new nodes
superuser.save();
// add child node to test node 1 using session 1
testNode1Session1.addNode(nodeName2, testNodeType);
// get session 2
Session session2 = getHelper().getReadWriteSession();
try {
// get the second node
Node testNode2Session2 = (Node) session2.getItem(testNode2Session1.getPath());
// adds a child node
testNode2Session2.addNode(nodeName3, testNodeType);
// save the changes
session2.save();
// call refresh on session 1
superuser.refresh(false);
// check if session 1 flag has been cleared
assertFalse("Session should have no pending changes recorded after Session.refresh(false)!", superuser.hasPendingChanges());
// check if added child node for node 1 by session 1 has been removed
assertFalse("Node Modifications have not been flushed after session.refresh(false)", testNode1Session1.hasNodes());
// check if added child node for node 2 by session 2 has become visible in session 1
assertTrue("Node modified by a different session has not been updated after Session.refresh(false)", testNode2Session1.hasNodes());
} finally {
session2.logout();
}
}
/**
* Checks if {@link javax.jcr.Session#refresh(boolean refresh)} works
* properly with refresh
set to true
.
*
* Procedure:
- Creates two nodes with session 1
- Modifies
* node 1 with session 1 by adding a child node
- Get node 2 with
* session 2
- Modifies node 2 with session 2 by adding a child
* node
- saves session 2 changes using {@link
* javax.jcr.Session#save()}
- calls
Session.refresh(true)
* on session 1
Session 1 changes and session 2 changes now be
* visible to session 1.
*
* Prerequisites:
* javax.jcr.tck.nodetype
must accept children of same
* nodetype
*/
public void testRefreshBooleanTrue() throws RepositoryException {
// get default workspace test root node using superuser session
Node defaultRootNode = (Node) superuser.getItem(testRootNode.getPath());
// create a node
Node testNode1Session1 = defaultRootNode.addNode(nodeName1, testNodeType);
// create a second node
Node testNode2Session1 = defaultRootNode.addNode(nodeName2, testNodeType);
// save the new nodes
superuser.save();
// add child node to test node 1 using session 1
testNode1Session1.addNode(nodeName2, testNodeType);
// get session 2
Session session2 = getHelper().getReadWriteSession();
try {
// get the second node
Node testNode2Session2 = (Node) session2.getItem(testNode2Session1.getPath());
// adds a child node
testNode2Session2.addNode(nodeName3, testNodeType);
// save the changes
session2.save();
// call refresh on session 1
superuser.refresh(true);
// check if session 1 flag has been cleared
assertTrue("Session should still have pending changes recorded after Session.refresh(true)!", superuser.hasPendingChanges());
// check if added child node for node 1 by session 1 is still there
assertTrue("Node Modifications are lost after session.refresh(true)", testNode1Session1.hasNodes());
// check if added child node for node 2 by session 2 has become visible in session 1
assertTrue("Node modified by a different session has not been updated after Session.refresh(true)", testNode2Session1.hasNodes());
} finally {
session2.logout();
}
}
/**
* Checks if {@link javax.jcr.Session#hasPendingChanges()} works
* properly.
*
* Procedure:
*
- Gets a session, checks
* inital flag setting
- Adds a node, checks flag
- Saves on
* session, checks flag
- Adds a property, checks flag
- Saves
* on session, checks flag
- Adds a child node, checks flag
* - Saves on session, checks flag
- Removes child node, checks
* flag
- Saves on session, checks flag
- Removes property,
* checks flag
- Saves on session, checks flag
* Prerequisites: javax.jcr.tck.nodetype
must accept
* children of same nodetype javax.jcr.tck.propertyname1
* must be the name of a String property that can be added to a node of type
* set in javax.jcr.tck.nodetype
*/
public void testHasPendingChanges() throws RepositoryException {
// get default workspace test root node using superuser session
Node defaultRootNode = (Node) superuser.getItem(testRootNode.getPath());
// initial check if flag is set correctly
assertFalse("Session should have no pending changes recorded!", superuser.hasPendingChanges());
// test with adding a node
Node testNode1 = defaultRootNode.addNode(nodeName1, testNodeType);
assertTrue("Session should have pending changes recorded after new node was added!", superuser.hasPendingChanges());
// save the node
superuser.save();
// pending changes should have been cleared
assertFalse("Session should have no pending changes recorded after new node was added and saved!", superuser.hasPendingChanges());
// adds a property
testNode1.setProperty(propertyName1, "test");
assertTrue("Session should have pending changes recorded after a property was added!", superuser.hasPendingChanges());
// save the new prop
superuser.save();
// pending changes should have been cleared
assertFalse("Session should have no pending changes recorded after added property hase been saved!", superuser.hasPendingChanges());
// add child node
Node testChildNode = testNode1.addNode(nodeName1, testNodeType);
assertTrue("Session should have pending changes recorded after child node has been added!", superuser.hasPendingChanges());
// save the new child nodes
superuser.save();
// pending changes should have been cleared
assertFalse("Session should have no pending changes recorded after new child node has been added and saved!", superuser.hasPendingChanges());
// remove the child node
testChildNode.remove();
assertTrue("Session should have pending changes recorded after child node has been removed", superuser.hasPendingChanges());
// save the change
superuser.save();
// pending changes should have been cleared
assertFalse("Session should have no pending changes recorded after child node has been removed and saved!", superuser.hasPendingChanges());
// remove the property
testNode1.setProperty(propertyName1, (Value) null);
assertTrue("Session should have pending changes recorded after property has been removed", superuser.hasPendingChanges());
// save the change
superuser.save();
// pending changes should have been cleared
assertFalse("Session should have no pending changes recorded after property has been removed and saved!", superuser.hasPendingChanges());
}
/**
* Checks if {@link javax.jcr.Session#hasCapability(String, Object, Object[])}
* works as specified.
*
*
* @throws RepositoryException
*/
public void testHasCapability() throws RepositoryException {
Session roSession = getHelper().getReadOnlySession();
try {
Node testRoot = roSession.getNode(testRootNode.getPath());
Object[] args = new Object[] { "foo" };
if (!roSession.hasCapability("addNode", testRoot, args)) {
// if hasCapability() returns false, the actual method call
// is expected to fail
try {
testRoot.addNode("foo");
roSession.save();
fail("Node.addNode() should fail according to Session.hasCapability()");
} catch (RepositoryException e) {
// expected
}
} else {
// hasCapability() returning true doesn't guarantee that the
// actual method call succeeds, it's just a best-effort.
// therefore nothing to test here...
}
} finally {
roSession.logout();
}
}
}