/* * 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.Node; import javax.jcr.PathNotFoundException; import javax.jcr.Property; import javax.jcr.Repository; import javax.jcr.RepositoryException; import javax.jcr.Session; import javax.jcr.lock.LockException; import javax.jcr.nodetype.ConstraintViolationException; import javax.jcr.nodetype.NoSuchNodeTypeException; import javax.jcr.version.VersionException; import org.apache.jackrabbit.test.AbstractJCRTest; import org.apache.jackrabbit.test.NotExecutableException; /** * <code>NodeRemoveMixinTest</code> contains the test cases for the method * <code>Node.removeMixin(String)</code>. * */ public class NodeRemoveMixinTest extends AbstractJCRTest { /** * Tests if <code>Node.removeMixin(String mixinName)</code> removes the * requested mixin properly */ public void testRemoveSuccessfully() throws NotExecutableException, RepositoryException { Session session = testRootNode.getSession(); Node node = testRootNode.addNode(nodeName1, testNodeType); String mixinName = NodeMixinUtil.getAddableMixinName(session, node); if (mixinName == null) { throw new NotExecutableException("No testable mixin node type found"); } node.addMixin(mixinName); testRootNode.getSession().save(); try { node.removeMixin(mixinName); } catch (ConstraintViolationException e) { /** * In some implementations it may not be possible to remove mixin node * types (short of removing the node itself). In these cases this * method will throw a ConstraintViolationException. */ throw new NotExecutableException("Repository does not support remove of mixin."); } // test if mixin is removed from property jcr:mixinTypes immediately // it is implementation-specific, if the property is removed completely // or set to an empty array when removing the last mixin type try { Property mixinProps = node.getProperty(jcrMixinTypes); // getValues() returns an empty array assertTrue("Node.removeMixin(String mixinName) did not remove mixin from " + "property " + jcrMixinTypes + ".", mixinProps.getValues().length == 0); } catch (PathNotFoundException e) { // success (property jcr:mixinTypes has been completely removed) } // it is implementation-specific if a removed mixin isn't available // before or after save therefore save before further tests testRootNode.getSession().save(); // test if removed mixin isn't available anymore by node.getMixinNodeTypes() assertTrue("removeMixin(String mixinName) did not remove mixin.", node.getMixinNodeTypes().length == 0); } /** * Tests if <code>Node.removeMixin(String mixinName)</code> throws a * NoSuchNodeTypeException <code>Node</code> does not have assigned the * requested mixin */ public void testNotAssigned() throws NotExecutableException, RepositoryException { Session session = testRootNode.getSession(); Node node = testRootNode.addNode(nodeName1, testNodeType); String mixinName = NodeMixinUtil.getAddableMixinName(session, node); if (mixinName == null) { throw new NotExecutableException("No testable mixin node type found"); } node.addMixin(mixinName); testRootNode.getSession().save(); String notAssignedMixin = NodeMixinUtil.getNotAssignedMixinName(session, node); if (notAssignedMixin == null) { throw new NotExecutableException("No testable mixin node type found"); } try { node.removeMixin(notAssignedMixin); fail("Node.removeMixin(String mixinName) must throw a " + "NoSuchNodeTypeException if Node does not have the " + "specified mixin."); } catch (NoSuchNodeTypeException e) { // success } } /** * Tests if <code>Node.removeMixin(String mixinName)</code> throws a * <code>LockException</code> if <code>Node</code> is locked. * <p> * The test creates a node <code>nodeName1</code> of type * <code>testNodeType</code> under <code>testRoot</code>, adds a mixin and * then locks the node with the superuser session. Then the test tries to * remove the before added mixin readWrite <code>Session</code>. */ public void testLocked() throws ConstraintViolationException, NotExecutableException, RepositoryException { Session session = testRootNode.getSession(); if (!isSupported(Repository.OPTION_LOCKING_SUPPORTED)) { throw new NotExecutableException("Locking is not supported."); } // create a node that is lockable Node node = testRootNode.addNode(nodeName1, testNodeType); // or try to make it lockable if it is not ensureMixinType(node, mixLockable); testRootNode.getSession().save(); String mixinName = NodeMixinUtil.getAddableMixinName(session, node); if (mixinName == null) { throw new NotExecutableException("No testable mixin node type found"); } node.addMixin(mixinName); testRootNode.getSession().save(); // remove first slash of path to get rel path to root String pathRelToRoot = node.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 { // remove mixin on locked node must throw either directly upon // removeMixin or upon save. node.removeMixin(mixinName); node.save(); fail("Node.removeMixin(String mixinName) must throw a " + "LockException if the node is locked."); } catch (LockException e) { // success } // unlock to remove node at tearDown() node2.unlock(); } finally { session2.logout(); } } /** * Tests if <code>Node.removeMixin(String mixinName)</code> throws a * <code>VersionException</code> if <code>Node</code> is checked-in * <p> * The test creates a node <code>nodeName1</code> of type * <code>testNodeType</code> under <code>testRoot</code>, adds a mixin and * then checks it in. Then the test tries to remove the added. */ public void testCheckedIn() throws ConstraintViolationException, NotExecutableException, RepositoryException { Session session = testRootNode.getSession(); if (!isSupported(Repository.OPTION_VERSIONING_SUPPORTED)) { throw new NotExecutableException("Versioning is not supported."); } // create a node that is versionable Node node = testRootNode.addNode(nodeName1, testNodeType); // or try to make it versionable if it is not ensureMixinType(node, mixVersionable); testRootNode.getSession().save(); String mixinName = NodeMixinUtil.getAddableMixinName(session, node); if (mixinName == null || node.isNodeType(mixinName)) { throw new NotExecutableException("No testable mixin node type found"); } node.addMixin(mixinName); testRootNode.getSession().save(); node.checkin(); try { node.removeMixin(mixinName); fail("Node.removeMixin(String mixinName) must throw a " + "VersionException if the node is checked-in."); } catch (VersionException e) { // success } } }