All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.jackrabbit.test.AbstractJCRTest Maven / Gradle / Ivy

There is a newer version: 2.23.1-beta
Show newest version
/*
 * 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;

import junit.framework.TestResult;

import javax.jcr.Node;
import javax.jcr.PropertyType;
import javax.jcr.Session;
import javax.jcr.NodeIterator;
import javax.jcr.RepositoryException;
import javax.jcr.NamespaceRegistry;
import javax.jcr.Repository;
import javax.jcr.NamespaceException;
import javax.jcr.RangeIterator;
import javax.jcr.UnsupportedRepositoryOperationException;
import javax.jcr.Value;
import javax.jcr.ValueFactory;
import javax.jcr.nodetype.NoSuchNodeTypeException;
import javax.jcr.nodetype.NodeDefinition;
import javax.jcr.nodetype.ConstraintViolationException;
import javax.jcr.nodetype.NodeType;
import javax.jcr.nodetype.PropertyDefinition;
import javax.jcr.retention.RetentionManager;

import java.util.StringTokenizer;
import java.util.Random;
import java.util.List;
import java.util.Arrays;

/**
 * Abstract base class for all JCR test classes.
 */
public abstract class AbstractJCRTest extends JUnitTest {

    /**
     * Pool of helper objects to access repository transparently
     */
    private static final RepositoryHelperPool HELPER_POOL = RepositoryHelperPoolImpl.getInstance();

    /**
     * Namespace URI for jcr prefix.
     */
    public static final String NS_JCR_URI = "http://www.jcp.org/jcr/1.0";

    /**
     * Namespace URI for nt prefix.
     */
    public static final String NS_NT_URI = "http://www.jcp.org/jcr/nt/1.0";

    /**
     * Namespace URI for mix prefix.
     */
    public static final String NS_MIX_URI = "http://www.jcp.org/jcr/mix/1.0";

    /**
     * Namespace URI for sv prefix
     */
    public static final String NS_SV_URI = "http://www.jcp.org/jcr/sv/1.0";

    /**
     * The repository helper for this test.
     */
    private RepositoryHelper helper;

    /**
     * JCR Name jcr:primaryType using the namespace resolver of the current session.
     */
    protected String jcrPrimaryType;

    /**
     * JCR Name jcr:mixinTypes using the namespace resolver of the current session.
     */
    protected String jcrMixinTypes;

    /**
     * JCR Name jcr:predecessors using the namespace resolver of the current session.
     */
    protected String jcrPredecessors;

    /**
     * JCR Name jcr:successors using the namespace resolver of the current session.
     */
    protected String jcrSuccessors;

    /**
     * JCR Name jcr:created using the namespace resolver of the current session.
     */
    protected String jcrCreated;

    /**
     * JCR Name jcr:created using the namespace resolver of the current session.
     */
    protected String jcrVersionHistory;

    /**
     * JCR Name jcr:copiedFrom using the namespace resolver of the current session.
     */
    protected String jcrCopiedFrom;

    /**
     * JCR Name jcr:frozenNode using the namespace resolver of the current session.
     */
    protected String jcrFrozenNode;

    /**
     * JCR Name jcr:frozenUuid using the namespace resolver of the current session.
     */
    protected String jcrFrozenUuid;

    /**
     * JCR Name jcr:rootVersion using the namespace resolver of the current session.
     */
    protected String jcrRootVersion;

    /**
     * JCR Name jcr:isCheckedOut using the namespace resolver of the current session.
     */
    protected String jcrIsCheckedOut;

    /**
     * JCR Name jcr:baseVersion using the namespace resolver of the current session.
     */
    protected String jcrBaseVersion;

    /**
     * JCR Name jcr:uuid using the namespace resolver of the current session.
     */
    protected String jcrUUID;

    /**
     * JCR Name jcr:lockOwner using the namespace resolver of the current session.
     */
    protected String jcrLockOwner;

    /**
     * JCR Name jcr:lockIsDeep using the namespace resolver of the current session.
     */
    protected String jcrlockIsDeep;

    /**
     * JCR Name jcr:mergeFailed using the namespace resolver of the current session.
     */
    protected String jcrMergeFailed;

    /**
     * JCR Name jcr:system using the namespace resolver of the current session.
     */
    protected String jcrSystem;

    /**
     * JCR Name nt:base using the namespace resolver of the current session.
     */
    protected String ntBase;

    /**
     * JCR Name nt:unstructured using the namespace resolver of the current session.
     */
    protected String ntUnstructured;

    /**
     * JCR Name nt:version using the namespace resolver of the current session.
     */
    protected String ntVersion;

    /**
     * JCR Name nt:versionHistory using the namespace resolver of the current session.
     */
    protected String ntVersionHistory;

    /**
     * JCR Name nt:versionHistory using the namespace resolver of the current session.
     */
    protected String ntVersionLabels;

    /**
     * JCR Name nt:frozenNode using the namespace resolver of the current session.
     */
    protected String ntFrozenNode;

    /**
     * JCR Name mix:referenceable using the namespace resolver of the current session.
     */
    protected String mixReferenceable;

    /**
     * JCR Name mix:versionable using the namespace resolver of the current session.
     */
    protected String mixVersionable;

    /**
     * JCR Name mix:simpleVersionable using the namespace resolver of the current session.
     */
    protected String mixSimpleVersionable;

    /**
     * JCR Name mix:lockable using the namespace resolver of the current session.
     */
    protected String mixLockable;

    /**
     * JCR Name mix:title using the namespace resolver of the current session.
     */
    protected String mixTitle;

    /**
     * JCR Name mix:shareable using the namespace resolver of the current session.
     */
    protected String mixShareable;

    /**
     * JCR Name nt:query using the namespace resolver of the current session.
     */
    protected String ntQuery;

    /**
     * JCR Name nt:activity using the namespace resolver of the current session.
     */
    protected String ntActivity;

    /**
     * Relative path to the test root node.
     */
    protected String testPath;

    /**
     * Absolute path to the test root node.
     */
    protected String testRoot;

    /**
     * The node type name for newly created nodes.
     */
    protected String testNodeType;

    /**
     * The node type name for the test root node.
     */
    protected String testNodeTypeTestRoot;

    /**
     * A node type that does not allow any child nodes, such as nt:base.
     */
    protected String testNodeTypeNoChildren;

    /**
     * Name of a node that will be created during a test case.
     */
    protected String nodeName1;

    /**
     * Name of a node that will be created during a test case.
     */
    protected String nodeName2;

    /**
     * Name of a node that will be created during a test case.
     */
    protected String nodeName3;

    /**
     * Name of a node that will be created during a test case.
     */
    protected String nodeName4;

    /**
     * Name of a property that will be used during a test case.
     */
    protected String propertyName1;

    /**
     * Name of a property that will be used during a test case.
     */
    protected String propertyName2;

    /**
     * Name of a workspace to use instead of the default workspace.
     */
    protected String workspaceName;

    /**
     * The superuser session for the default workspace
     */
    protected Session superuser;

    /**
     * Flag that indicates if the current test is a read-only test, that is
     * no content is written to the workspace by the test.
     */
    protected boolean isReadOnly = false;

    /**
     * The root Node for testing
     */
    protected Node testRootNode;

    /**
     * The value factory for {@link #superuser}.
     */
    protected ValueFactory vf;

    protected void setUp() throws Exception {
        super.setUp();
        testRoot = getProperty(RepositoryStub.PROP_TESTROOT);
        if (testRoot == null) {
            fail("Property '" + RepositoryStub.PROP_TESTROOT + "' is not defined.");
        }

        // cut off '/' to build testPath
        testPath = testRoot.substring(1);
        testNodeType = getProperty(RepositoryStub.PROP_NODETYPE);
        testNodeTypeTestRoot = getProperty(RepositoryStub.PROP_NODETYPETESTROOT);
        if (testNodeTypeTestRoot == null) {
            testNodeTypeTestRoot = testNodeType; // backwards compatibility
        }
        testNodeTypeNoChildren = getProperty(RepositoryStub.PROP_NODETYPENOCHILDREN);
        // setup node names
        nodeName1 = getProperty(RepositoryStub.PROP_NODE_NAME1);
        if (nodeName1 == null) {
            fail("Property '" + RepositoryStub.PROP_NODE_NAME1 + "' is not defined.");
        }
        nodeName2 = getProperty(RepositoryStub.PROP_NODE_NAME2);
        if (nodeName2 == null) {
            fail("Property '" + RepositoryStub.PROP_NODE_NAME2 + "' is not defined.");
        }
        nodeName3 = getProperty(RepositoryStub.PROP_NODE_NAME3);
        if (nodeName3 == null) {
            fail("Property '" + RepositoryStub.PROP_NODE_NAME3 + "' is not defined.");
        }
        nodeName4 = getProperty(RepositoryStub.PROP_NODE_NAME4);
        if (nodeName4 == null) {
            fail("Property '" + RepositoryStub.PROP_NODE_NAME4 + "' is not defined.");
        }
        propertyName1 = getProperty(RepositoryStub.PROP_PROP_NAME1);
        if (propertyName1 == null) {
            fail("Property '" + RepositoryStub.PROP_PROP_NAME1 + "' is not defined.");
        }
        propertyName2 = getProperty(RepositoryStub.PROP_PROP_NAME2);
        if (propertyName2 == null) {
            fail("Property '" + RepositoryStub.PROP_PROP_NAME2 + "' is not defined.");
        }
        workspaceName = getProperty(RepositoryStub.PROP_WORKSPACE_NAME);
        if (workspaceName == null) {
            fail("Property '" + RepositoryStub.PROP_WORKSPACE_NAME + "' is not defined.");
        }

        superuser = getHelper().getSuperuserSession();

        // setup some common names
        jcrPrimaryType = superuser.getNamespacePrefix(NS_JCR_URI) + ":primaryType";
        jcrMixinTypes = superuser.getNamespacePrefix(NS_JCR_URI) + ":mixinTypes";
        jcrPredecessors = superuser.getNamespacePrefix(NS_JCR_URI) + ":predecessors";
        jcrSuccessors = superuser.getNamespacePrefix(NS_JCR_URI) + ":successors";
        jcrCreated = superuser.getNamespacePrefix(NS_JCR_URI) + ":created";
        jcrVersionHistory = superuser.getNamespacePrefix(NS_JCR_URI) + ":versionHistory";
        jcrCopiedFrom = superuser.getNamespacePrefix(NS_JCR_URI) + ":copiedFrom";
        jcrFrozenNode = superuser.getNamespacePrefix(NS_JCR_URI) + ":frozenNode";
        jcrFrozenUuid = superuser.getNamespacePrefix(NS_JCR_URI) + ":frozenUuid";
        jcrRootVersion = superuser.getNamespacePrefix(NS_JCR_URI) + ":rootVersion";
        jcrBaseVersion = superuser.getNamespacePrefix(NS_JCR_URI) + ":baseVersion";
        jcrIsCheckedOut = superuser.getNamespacePrefix(NS_JCR_URI) + ":isCheckedOut";
        jcrUUID = superuser.getNamespacePrefix(NS_JCR_URI) + ":uuid";
        jcrLockOwner = superuser.getNamespacePrefix(NS_JCR_URI) + ":lockOwner";
        jcrlockIsDeep = superuser.getNamespacePrefix(NS_JCR_URI) + ":lockIsDeep";
        jcrMergeFailed = superuser.getNamespacePrefix(NS_JCR_URI) + ":mergeFailed";
        jcrSystem = superuser.getNamespacePrefix(NS_JCR_URI) + ":system";
        ntBase = superuser.getNamespacePrefix(NS_NT_URI) + ":base";
        ntUnstructured = superuser.getNamespacePrefix(NS_NT_URI) + ":unstructured";
        ntVersion = superuser.getNamespacePrefix(NS_NT_URI) + ":version";
        ntVersionHistory = superuser.getNamespacePrefix(NS_NT_URI) + ":versionHistory";
        ntVersionLabels = superuser.getNamespacePrefix(NS_NT_URI) + ":versionLabels";
        ntFrozenNode = superuser.getNamespacePrefix(NS_NT_URI) + ":frozenNode";
        mixReferenceable = superuser.getNamespacePrefix(NS_MIX_URI) + ":referenceable";
        mixVersionable = superuser.getNamespacePrefix(NS_MIX_URI) + ":versionable";
        mixSimpleVersionable = superuser.getNamespacePrefix(NS_MIX_URI) + ":simpleVersionable";
        mixLockable = superuser.getNamespacePrefix(NS_MIX_URI) + ":lockable";
        mixShareable = superuser.getNamespacePrefix(NS_MIX_URI) + ":shareable";
        mixTitle = superuser.getNamespacePrefix(NS_MIX_URI) + ":title";
        ntQuery = superuser.getNamespacePrefix(NS_NT_URI) + ":query";
        ntActivity = superuser.getNamespacePrefix(NS_NT_URI) + ":activity";

        // setup custom namespaces
        if (isSupported(Repository.LEVEL_2_SUPPORTED)) {
            NamespaceRegistry nsReg = superuser.getWorkspace().getNamespaceRegistry();
            String namespaces = getProperty(RepositoryStub.PROP_NAMESPACES);
            if (namespaces != null) {
                String[] prefixes = namespaces.split(" ");
                for (int i = 0; i < prefixes.length; i++) {
                    String uri = getProperty(RepositoryStub.PROP_NAMESPACES + "." + prefixes[i]);
                    if (uri != null) {
                        try {
                            nsReg.getPrefix(uri);
                        } catch (NamespaceException e) {
                            // not yet registered
                            nsReg.registerNamespace(prefixes[i], uri);
                        }
                    }
                }
            }
            vf = superuser.getValueFactory();
        }

        if (isReadOnly) {
            if (testPath.length() == 0) {
                // test root is the root node
                testRootNode = superuser.getRootNode();
            } else if (!superuser.getRootNode().hasNode(testPath)) {
                cleanUp();
                fail("Workspace does not contain test data at: " + testRoot);
            } else {
                testRootNode = superuser.getRootNode().getNode(testPath);
            }
        } else if (isSupported(Repository.LEVEL_2_SUPPORTED)) {
            testRootNode = cleanUpTestRoot(superuser);
            // also clean second workspace
            Session s = getHelper().getSuperuserSession(workspaceName);
            try {
                cleanUpTestRoot(s);
            } finally {
                s.logout();
            }
        } else {
            cleanUp();
            fail("Test case requires level 2 support.");
        }
    }

    protected void cleanUp() throws Exception {
        if (superuser != null) {
            try {
                if (!isReadOnly && isSupported(Repository.LEVEL_2_SUPPORTED)) {
                    cleanUpTestRoot(superuser);
                }
            } catch (Exception e) {
                log.println("Exception in tearDown: " + e.toString());
            } finally {
                superuser.logout();
                superuser = null;
                vf = null;
            }
        }
        testRootNode = null;
    }

    protected void tearDown() throws Exception {
        cleanUp();
        super.tearDown();
    }

    /**
     * Runs the test cases of this test class and reports the results to
     * testResult. In contrast to the default implementation of
     * TestCase.run() this method will suppress tests errors with
     * a {@link NotExecutableException}. That is, test cases that throw this
     * exception will still result as successful.
     * @param testResult the test result.
     */
    public void run(TestResult testResult) {
        try {
            helper = HELPER_POOL.borrowHelper();
            try {
                super.run(new JCRTestResult(testResult, log));
            } finally {
                HELPER_POOL.returnHelper(helper);
                helper = null;
            }
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * @return the repository helper instance that is associated with this test.
     */
    protected RepositoryHelper getHelper() {
        return helper;
    }

    /**
     * Returns the value of the configuration property with propName.
     * The sequence how configuration properties are read is the follwoing:
     * 
    *
  1. javax.jcr.tck.<testClassName>.<testCaseName>.<propName>
  2. *
  3. javax.jcr.tck.<testClassName>.<propName>
  4. *
  5. javax.jcr.tck.<packageName>.<propName>
  6. *
  7. javax.jcr.tck.<propName>
  8. *
* Where: *
    *
  • <testClassName> is the name of the test class without package prefix.
  • *
  • <testMethodName> is the name of the test method
  • *
  • <packageName> is the name of the package of the test class. * Example: packageName for org.apache.jackrabbit.test.api.BooleanPropertyTest: api
  • *
* @param propName the propName of the configration property. * @return the value of the property or null if the property * does not exist. * @throws RepositoryException if an error occurs while reading from * the configuration. */ public String getProperty(String propName) throws RepositoryException { String testCaseName = getName(); String testClassName = getClass().getName(); String testPackName = ""; int idx; if ((idx = testClassName.lastIndexOf('.')) > -1) { testPackName = testClassName.substring(testClassName.lastIndexOf('.', idx - 1) + 1, idx); testClassName = testClassName.substring(idx + 1); } // 1) test case specific property first String value = getHelper().getProperty(RepositoryStub.PROP_PREFIX + "." + testClassName + "." + testCaseName + "." + propName); if (value != null) { return value; } // 2) check test class property value = getHelper().getProperty(RepositoryStub.PROP_PREFIX + "." + testClassName + "." + propName); if (value != null) { return value; } // 3) check package property value = getHelper().getProperty(RepositoryStub.PROP_PREFIX + "." + testPackName + "." + propName); if (value != null) { return value; } // finally try global property return getHelper().getProperty(RepositoryStub.PROP_PREFIX + "." + propName); } /** * Returns the value of the configuration property with specified * name. If the property does not exist defaultValue is * returned. *

* Configuration properties are defined in the file: * repositoryStubImpl.properties. * * @param name the name of the property to retrieve. * @param defaultValue the default value if the property does not exist. * @return the value of the property or defaultValue if non existent. * @throws RepositoryException if the configuration file cannot be found. */ public String getProperty(String name, String defaultValue) throws RepositoryException { String val = getProperty(name); if (val == null) { val = defaultValue; } return val; } /** * Create a JCR value based on the configuration. * * @param s * @param valueProp Name of the config property that contains the property value. * @param typeProp Name of the config property that contains the property type. * If the config parameter is missing, {@link PropertyType#STRING} is used * to create the JCR value. * @param defaultValue Default value to be used if the config does not define * the value property. * @return JCR value to be used for a test. * @throws RepositoryException */ public Value getJcrValue(Session s, String valueProp, String typeProp, String defaultValue) throws RepositoryException { ValueFactory vf = s.getValueFactory(); String val = getProperty(valueProp, defaultValue); int type = PropertyType.valueFromName(getProperty(typeProp, PropertyType.TYPENAME_STRING)); return vf.createValue(val, type); } /** * Returns the size of the RangeIterator it. * Note, that the RangeIterator might get consumed, because * {@link RangeIterator#getSize()} might return -1 (information unavailable). * @param it a RangeIterator. * @return the size of the iterator (number of elements). */ protected long getSize(RangeIterator it) { long size = it.getSize(); if (size != -1) { return size; } size = 0; while (it.hasNext()) { it.next(); size++; } return size; } /** * Returns the local name for the given jcrName. * * @param jcrName * the name. * @return the local name part. */ protected static String getLocalName(String jcrName) { int idx = jcrName.indexOf(':'); if (idx != -1) { return jcrName.substring(idx + 1); } else { return jcrName; } } /** * Returns the prefix for the given jcrName. * * @param jcrName * the name. * @return the prefix part (empty string when not prefixed) */ protected static String getPrefix(String jcrName) { int idx = jcrName.indexOf(':'); if (idx != -1) { return jcrName.substring(0, idx); } else { return ""; } } /** * Returns the expanded name for the given jcrName. * * @param jcrName * the name. * @return the expanded name representation * @throws RepositoryException * @throws NamespaceException */ protected static String getQualifiedName(Session session, String jcrName) throws RepositoryException { String prefix = getPrefix(jcrName); String namespace = session.getNamespaceURI(prefix); String localname = getLocalName(jcrName); return (namespace.length() > 0 ? "{" + namespace + "}" : "{}") + localname; } /** * Returns the name of a workspace that is not accessible from * session. * @param session the session. * @return name of a non existing workspace. * @throws RepositoryException if an error occurs. */ protected String getNonExistingWorkspaceName(Session session) throws RepositoryException { List names = Arrays.asList(session.getWorkspace().getAccessibleWorkspaceNames()); String nonExisting = null; while (nonExisting == null) { String name = createRandomString(10); if (!names.contains(name)) { nonExisting = name; } } return nonExisting; } /** * Creates a String with a random sequence of characters * using 'a' - 'z'. * @param numChars number of characters. * @return the generated String. */ protected String createRandomString(int numChars) { Random rand = new Random(System.currentTimeMillis()); StringBuffer tmp = new StringBuffer(numChars); for (int i = 0; i < numChars; i++) { char c = (char) (rand.nextInt(('z' + 1) - 'a') + 'a'); tmp.append(c); } return tmp.toString(); } /** * Returns true if this repository support a certain optional * feature; otherwise false is returned. If there is no * such descriptorKey present in the repository, this method * also returns false. * * @param descriptorKey the descriptor key. * @return true if the option is supported. * @throws RepositoryException if an error occurs. */ protected boolean isSupported(String descriptorKey) throws RepositoryException { return "true".equals(getHelper().getRepository().getDescriptor(descriptorKey)); } /** * Throws a NotExecutableException if the repository does * not support the feature identified by the given discriptorKey. * * @param descriptorKey the descriptor key. * @throws RepositoryException if an error occurs. * @throws NotExecutableException If the feature is not supported. */ protected void checkSupportedOption(String descriptorKey) throws RepositoryException, NotExecutableException { String value = getHelper().getRepository().getDescriptor(descriptorKey); if (value == null || ! Boolean.valueOf(value).booleanValue()) { throw new NotExecutableException ( "Repository feature not supported: " + descriptorKey); } } /** * Checks that the repository supports multiple workspace, otherwise aborts with * {@link NotExecutableException}. * @throws NotExecutableException when the repository only supports a single * workspace */ protected void ensureMultipleWorkspacesSupported() throws RepositoryException, NotExecutableException { String workspacenames[] = superuser.getWorkspace().getAccessibleWorkspaceNames(); if (workspacenames == null || workspacenames.length < 2) { throw new NotExecutableException("This repository does not seem to support multiple workspaces."); } } /** * Checks that the repository supports locking, otherwise aborts with * {@link NotExecutableException}. * @throws NotExecutableException when the repository does not support locking */ protected void ensureLockingSupported() throws RepositoryException, NotExecutableException { if (!isSupported(Repository.OPTION_LOCKING_SUPPORTED)) { throw new NotExecutableException("This repository does not support locking."); } } private boolean canSetProperty(NodeType nodeType, String propertyName, int propertyType, boolean isMultiple) { PropertyDefinition propDefs[] = nodeType.getPropertyDefinitions(); for (int i = 0; i < propDefs.length; i++) { if (propDefs[i].getName().equals(propertyName) || propDefs[i].getName().equals("*")) { if ((propDefs[i].getRequiredType() == propertyType || propDefs[i].getRequiredType() == PropertyType.UNDEFINED) && propDefs[i].isMultiple() == isMultiple) { return true; } } } return false; } private boolean canSetProperty(Node node, String propertyName, int propertyType, boolean isMultiple) throws RepositoryException { if (canSetProperty(node.getPrimaryNodeType(), propertyName, propertyType, isMultiple)) { return true; } else { NodeType mixins[] = node.getMixinNodeTypes(); boolean canSetIt = false; for (int i = 0; i < mixins.length && !canSetIt; i++) { canSetIt |= canSetProperty(mixins[i], propertyName, propertyType, isMultiple); } return canSetIt; } } /** * Checks that the repository can set the property to the required type, otherwise aborts with * {@link NotExecutableException}. * @throws NotExecutableException when setting the property to the required * type is not supported */ protected void ensureCanSetProperty(Node node, String propertyName, int propertyType, boolean isMultiple) throws NotExecutableException, RepositoryException { if (! canSetProperty(node, propertyName, propertyType, isMultiple)) { throw new NotExecutableException("configured property name " + propertyName + " can not be set on node " + node.getPath()); } } /** * Checks that the repository can set the property to the required type, otherwise aborts with * {@link NotExecutableException}. * @throws NotExecutableException when setting the property to the required * type is not supported */ protected void ensureCanSetProperty(Node node, String propertyName, Value value) throws NotExecutableException, RepositoryException { ensureCanSetProperty(node, propertyName, value.getType(), false); } /** * Checks that the repository can set the property to the required type, otherwise aborts with * {@link NotExecutableException}. * @throws NotExecutableException when setting the property to the required * type is not supported */ protected void ensureCanSetProperty(Node node, String propertyName, Value[] values) throws NotExecutableException, RepositoryException { int propertyType = values.length == 0 ? PropertyType.UNDEFINED : values[0].getType(); if (! canSetProperty(node, propertyName, propertyType, true)) { throw new NotExecutableException("configured property name " + propertyName + " can not be set on node " + node.getPath()); } } /** * Checks that the repository supports the specified node type, otherwise aborts with * {@link NotExecutableException} * @throws NotExecutableException when the specified node type is unknown */ protected void ensureKnowsNodeType(Session session, String nodetype) throws NotExecutableException, RepositoryException { try { session.getWorkspace().getNodeTypeManager().getNodeType(nodetype); } catch (NoSuchNodeTypeException ex) { throw new NotExecutableException("Repository does not support node type " + nodetype); } } /** * Ensures that the given node is of the given mixin type. * * @param node a node. * @param mixin the name of a mixin type. * @throws NotExecutableException if the node is not of type mixin and the * mixin cannot be added. * @throws RepositoryException if an error occurs. */ protected void ensureMixinType(Node node, String mixin) throws NotExecutableException, RepositoryException { if (!node.isNodeType(mixin)) { if (node.canAddMixin(mixin)) { node.addMixin(mixin); } else { throw new NotExecutableException(node.getPath() + " does not support adding " + mixin); } } } /** * Checks whether the node already has the specified mixin node type */ protected boolean needsMixin(Node node, String mixin) throws RepositoryException { return ! node.getSession().getWorkspace().getNodeTypeManager().getNodeType(node.getPrimaryNodeType().getName()).isNodeType(mixin); } /** * Reverts any pending changes made by s and deletes any nodes * under {@link #testRoot}. If there is no node at {@link #testRoot} then * the necessary nodes are created. * * @param s the session to clean up. * @return the {@link javax.jcr.Node} that represents the test root. * @throws RepositoryException if an error occurs. */ protected Node cleanUpTestRoot(Session s) throws RepositoryException { // do a 'rollback' s.refresh(false); Node root = s.getRootNode(); Node testRootNode; if (root.hasNode(testPath)) { RetentionManager rm; try { rm = s.getRetentionManager(); } catch (UnsupportedRepositoryOperationException e) { rm = null; } // clean test root testRootNode = root.getNode(testPath); NodeIterator children = testRootNode.getNodes(); while (children.hasNext()) { Node child = children.nextNode(); // Remove retention policy if needed String childPath = child.getPath(); if (rm != null && rm.getRetentionPolicy(childPath) != null) { rm.removeRetentionPolicy(childPath); s.save(); } NodeDefinition nodeDef = child.getDefinition(); if (!nodeDef.isMandatory() && !nodeDef.isProtected()) { // try to remove child try { child.remove(); } catch (ConstraintViolationException e) { log.println("unable to remove node: " + child.getPath()); } } } } else { // create nodes to testPath StringTokenizer names = new StringTokenizer(testPath, "/"); Node currentNode = root; while (names.hasMoreTokens()) { String name = names.nextToken(); if (currentNode.hasNode(name)) { currentNode = currentNode.getNode(name); } else { currentNode = currentNode.addNode(name, testNodeTypeTestRoot); } } testRootNode = currentNode; } s.save(); return testRootNode; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy