Search in sources :

Example 16 with NodeDefinition

use of javax.jcr.nodetype.NodeDefinition in project jackrabbit-oak by apache.

the class NodeTypeImpl method internalGetChildDefinitions.

Collection<NodeDefinition> internalGetChildDefinitions() {
    // TODO distinguish between additive and overriding node definitions. See 3.7.6.8 Item Definitions in Subtypes
    Collection<NodeDefinition> definitions = new ArrayList<NodeDefinition>();
    definitions.addAll(Arrays.asList(getDeclaredChildNodeDefinitions()));
    for (NodeType type : getSupertypes()) {
        definitions.addAll(Arrays.asList(type.getDeclaredChildNodeDefinitions()));
    }
    return definitions;
}
Also used : NodeType(javax.jcr.nodetype.NodeType) Lists.newArrayList(com.google.common.collect.Lists.newArrayList) ArrayList(java.util.ArrayList) NodeDefinition(javax.jcr.nodetype.NodeDefinition)

Example 17 with NodeDefinition

use of javax.jcr.nodetype.NodeDefinition in project jackrabbit by apache.

the class ItemSaveOperation method validateTransientItems.

/**
     * the following validations/checks are performed on transient items:
     *
     * for every transient item:
     * - if it is 'modified' or 'new' check the corresponding write permission.
     * - if it is 'removed' check the REMOVE permission
     *
     * for every transient node:
     * - if it is 'new' check that its node type satisfies the
     *   'required node type' constraint specified in its definition
     * - check if 'mandatory' child items exist
     *
     * for every transient property:
     * - check if the property value satisfies the value constraints
     *   specified in the property's definition
     *
     * note that the protected flag is checked in Node.addNode/Node.remove
     * (for adding/removing child entries of a node), in
     * Node.addMixin/removeMixin/setPrimaryType (for type changes on nodes)
     * and in Property.setValue (for properties to be modified).
     */
private void validateTransientItems(SessionContext context, Iterable<ItemState> dirty, Iterable<ItemState> removed) throws RepositoryException {
    SessionImpl session = context.getSessionImpl();
    ItemManager itemMgr = context.getItemManager();
    SessionItemStateManager stateMgr = context.getItemStateManager();
    AccessManager accessMgr = context.getAccessManager();
    NodeTypeManagerImpl ntMgr = context.getNodeTypeManager();
    // walk through list of dirty transient items and validate each
    for (ItemState itemState : dirty) {
        ItemDefinition def;
        if (itemState.isNode()) {
            def = itemMgr.getDefinition((NodeState) itemState);
        } else {
            def = itemMgr.getDefinition((PropertyState) itemState);
        }
        /* check permissions for non-protected items. protected items are
               only added through API methods which need to assert that
               permissions are not violated.
             */
        if (!def.isProtected()) {
            /* detect the effective set of modification:
                   - new added node -> add_node perm on the child
                   - new property added -> set_property permission
                   - property modified -> set_property permission
                   - modified nodes can be ignored for changes only included
                     child-item addition or removal or changes of protected
                     properties such as mixin-types which are covered separately
                   note: removed items are checked later on.
                   note: reordering of child nodes has been covered upfront as
                         this information isn't available here.
                */
            Path path = stateMgr.getHierarchyMgr().getPath(itemState.getId());
            boolean isGranted = true;
            if (itemState.isNode()) {
                if (itemState.getStatus() == ItemState.STATUS_NEW) {
                    isGranted = accessMgr.isGranted(path, Permission.ADD_NODE);
                }
            // else: modified node (see comment above)
            } else {
                // modified or new property: set_property permission
                isGranted = accessMgr.isGranted(path, Permission.SET_PROPERTY);
            }
            if (!isGranted) {
                String msg = itemMgr.safeGetJCRPath(path) + ": not allowed to add or modify item";
                log.debug(msg);
                throw new AccessDeniedException(msg);
            }
        }
        if (itemState.isNode()) {
            // the transient item is a node
            NodeState nodeState = (NodeState) itemState;
            ItemId id = nodeState.getNodeId();
            NodeDefinition nodeDef = (NodeDefinition) def;
            // primary type
            NodeTypeImpl pnt = ntMgr.getNodeType(nodeState.getNodeTypeName());
            // effective node type (primary type incl. mixins)
            EffectiveNodeType ent = getEffectiveNodeType(context.getRepositoryContext().getNodeTypeRegistry(), nodeState);
            /**
                 * if the transient node was added (i.e. if it is 'new') or if
                 * its primary type has changed, check its node type against the
                 * required node type in its definition
                 */
            boolean primaryTypeChanged = nodeState.getStatus() == ItemState.STATUS_NEW;
            if (!primaryTypeChanged) {
                NodeState overlaid = (NodeState) nodeState.getOverlayedState();
                if (overlaid != null) {
                    Name newName = nodeState.getNodeTypeName();
                    Name oldName = overlaid.getNodeTypeName();
                    primaryTypeChanged = !newName.equals(oldName);
                }
            }
            if (primaryTypeChanged) {
                for (NodeType ntReq : nodeDef.getRequiredPrimaryTypes()) {
                    Name ntName = ((NodeTypeImpl) ntReq).getQName();
                    if (!(pnt.getQName().equals(ntName) || pnt.isDerivedFrom(ntName))) {
                        /**
                             * the transient node's primary node type does not
                             * satisfy the 'required primary types' constraint
                             */
                        String msg = itemMgr.safeGetJCRPath(id) + " must be of node type " + ntReq.getName();
                        log.debug(msg);
                        throw new ConstraintViolationException(msg);
                    }
                }
            }
            // mandatory child properties
            for (QPropertyDefinition pd : ent.getMandatoryPropDefs()) {
                if (pd.getDeclaringNodeType().equals(NameConstants.MIX_VERSIONABLE) || pd.getDeclaringNodeType().equals(NameConstants.MIX_SIMPLE_VERSIONABLE)) {
                    /**
                         * todo FIXME workaround for mix:versionable:
                         * the mandatory properties are initialized at a
                         * later stage and might not exist yet
                         */
                    continue;
                }
                String msg = itemMgr.safeGetJCRPath(id) + ": mandatory property " + pd.getName() + " does not exist";
                if (!nodeState.hasPropertyName(pd.getName())) {
                    log.debug(msg);
                    throw new ConstraintViolationException(msg);
                } else {
                    /*
                        there exists a property with the mandatory-name.
                        make sure the property really has the expected mandatory
                        property definition (and not another non-mandatory def,
                        such as e.g. multivalued residual instead of single-value
                        mandatory, named def).
                        */
                    PropertyId pi = new PropertyId(nodeState.getNodeId(), pd.getName());
                    ItemData childData = itemMgr.getItemData(pi, null, false);
                    if (!childData.getDefinition().isMandatory()) {
                        throw new ConstraintViolationException(msg);
                    }
                }
            }
            // mandatory child nodes
            for (QItemDefinition cnd : ent.getMandatoryNodeDefs()) {
                String msg = itemMgr.safeGetJCRPath(id) + ": mandatory child node " + cnd.getName() + " does not exist";
                if (!nodeState.hasChildNodeEntry(cnd.getName())) {
                    log.debug(msg);
                    throw new ConstraintViolationException(msg);
                } else {
                    /*
                        there exists a child node with the mandatory-name.
                        make sure the node really has the expected mandatory
                        node definition.
                        */
                    boolean hasMandatoryChild = false;
                    for (ChildNodeEntry cne : nodeState.getChildNodeEntries(cnd.getName())) {
                        ItemData childData = itemMgr.getItemData(cne.getId(), null, false);
                        if (childData.getDefinition().isMandatory()) {
                            hasMandatoryChild = true;
                            break;
                        }
                    }
                    if (!hasMandatoryChild) {
                        throw new ConstraintViolationException(msg);
                    }
                }
            }
        } else {
            // the transient item is a property
            PropertyState propState = (PropertyState) itemState;
            ItemId propId = propState.getPropertyId();
            org.apache.jackrabbit.spi.commons.nodetype.PropertyDefinitionImpl propDef = (org.apache.jackrabbit.spi.commons.nodetype.PropertyDefinitionImpl) def;
            /**
                 * check value constraints
                 * (no need to check value constraints of protected properties
                 * as those are set by the implementation only, i.e. they
                 * cannot be set by the user through the api)
                 */
            if (!def.isProtected()) {
                String[] constraints = propDef.getValueConstraints();
                if (constraints != null) {
                    InternalValue[] values = propState.getValues();
                    try {
                        EffectiveNodeType.checkSetPropertyValueConstraints(propDef.unwrap(), values);
                    } catch (RepositoryException e) {
                        // repack exception for providing more verbose error message
                        String msg = itemMgr.safeGetJCRPath(propId) + ": " + e.getMessage();
                        log.debug(msg);
                        throw new ConstraintViolationException(msg);
                    }
                    /**
                         * need to manually check REFERENCE value constraints
                         * as this requires a session (target node needs to
                         * be checked)
                         */
                    if (constraints.length > 0 && (propDef.getRequiredType() == PropertyType.REFERENCE || propDef.getRequiredType() == PropertyType.WEAKREFERENCE)) {
                        for (InternalValue internalV : values) {
                            boolean satisfied = false;
                            String constraintViolationMsg = null;
                            try {
                                NodeId targetId = internalV.getNodeId();
                                if (propDef.getRequiredType() == PropertyType.WEAKREFERENCE && !itemMgr.itemExists(targetId)) {
                                    // target of weakref doesn;t exist, skip
                                    continue;
                                }
                                Node targetNode = session.getNodeById(targetId);
                                /**
                                     * constraints are OR-ed, i.e. at least one
                                     * has to be satisfied
                                     */
                                for (String constrNtName : constraints) {
                                    /**
                                         * a [WEAK]REFERENCE value constraint specifies
                                         * the name of the required node type of
                                         * the target node
                                         */
                                    if (targetNode.isNodeType(constrNtName)) {
                                        satisfied = true;
                                        break;
                                    }
                                }
                                if (!satisfied) {
                                    NodeType[] mixinNodeTypes = targetNode.getMixinNodeTypes();
                                    String[] targetMixins = new String[mixinNodeTypes.length];
                                    for (int j = 0; j < mixinNodeTypes.length; j++) {
                                        targetMixins[j] = mixinNodeTypes[j].getName();
                                    }
                                    String targetMixinsString = Text.implode(targetMixins, ", ");
                                    String constraintsString = Text.implode(constraints, ", ");
                                    constraintViolationMsg = itemMgr.safeGetJCRPath(propId) + ": is constraint to [" + constraintsString + "] but references [primaryType=" + targetNode.getPrimaryNodeType().getName() + ", mixins=" + targetMixinsString + "]";
                                }
                            } catch (RepositoryException re) {
                                String msg = itemMgr.safeGetJCRPath(propId) + ": failed to check " + ((propDef.getRequiredType() == PropertyType.REFERENCE) ? "REFERENCE" : "WEAKREFERENCE") + " value constraint";
                                log.debug(msg);
                                throw new ConstraintViolationException(msg, re);
                            }
                            if (!satisfied) {
                                log.debug(constraintViolationMsg);
                                throw new ConstraintViolationException(constraintViolationMsg);
                            }
                        }
                    }
                }
            }
        /**
                 * no need to check the protected flag as this is checked
                 * in PropertyImpl.setValue(Value)
                 */
        }
    }
    // walk through list of removed transient items and check REMOVE permission
    for (ItemState itemState : removed) {
        QItemDefinition def;
        try {
            if (itemState.isNode()) {
                def = itemMgr.getDefinition((NodeState) itemState).unwrap();
            } else {
                def = itemMgr.getDefinition((PropertyState) itemState).unwrap();
            }
        } catch (ConstraintViolationException e) {
            // of a mixin (see also JCR-2130 & JCR-2408)
            continue;
        }
        if (!def.isProtected()) {
            Path path = stateMgr.getAtticAwareHierarchyMgr().getPath(itemState.getId());
            // check REMOVE permission
            int permission = (itemState.isNode()) ? Permission.REMOVE_NODE : Permission.REMOVE_PROPERTY;
            if (!accessMgr.isGranted(path, permission)) {
                String msg = itemMgr.safeGetJCRPath(path) + ": not allowed to remove item";
                log.debug(msg);
                throw new AccessDeniedException(msg);
            }
        }
    }
}
Also used : AccessManager(org.apache.jackrabbit.core.security.AccessManager) AccessDeniedException(javax.jcr.AccessDeniedException) NodeState(org.apache.jackrabbit.core.state.NodeState) NodeTypeImpl(org.apache.jackrabbit.core.nodetype.NodeTypeImpl) Node(javax.jcr.Node) QItemDefinition(org.apache.jackrabbit.spi.QItemDefinition) ItemDefinition(javax.jcr.nodetype.ItemDefinition) NodeDefinition(javax.jcr.nodetype.NodeDefinition) ItemId(org.apache.jackrabbit.core.id.ItemId) Name(org.apache.jackrabbit.spi.Name) QPropertyDefinition(org.apache.jackrabbit.spi.QPropertyDefinition) ConstraintViolationException(javax.jcr.nodetype.ConstraintViolationException) NodeTypeManagerImpl(org.apache.jackrabbit.core.nodetype.NodeTypeManagerImpl) Path(org.apache.jackrabbit.spi.Path) ChildNodeEntry(org.apache.jackrabbit.core.state.ChildNodeEntry) RepositoryException(javax.jcr.RepositoryException) QItemDefinition(org.apache.jackrabbit.spi.QItemDefinition) InternalValue(org.apache.jackrabbit.core.value.InternalValue) PropertyState(org.apache.jackrabbit.core.state.PropertyState) PropertyId(org.apache.jackrabbit.core.id.PropertyId) EffectiveNodeType(org.apache.jackrabbit.core.nodetype.EffectiveNodeType) ItemState(org.apache.jackrabbit.core.state.ItemState) NodeType(javax.jcr.nodetype.NodeType) EffectiveNodeType(org.apache.jackrabbit.core.nodetype.EffectiveNodeType) NodeId(org.apache.jackrabbit.core.id.NodeId) SessionItemStateManager(org.apache.jackrabbit.core.state.SessionItemStateManager)

Example 18 with NodeDefinition

use of javax.jcr.nodetype.NodeDefinition in project jackrabbit by apache.

the class NodeTypesReport method toXml.

/**
     * Returns a Xml representation of the node type definition(s) according
     * to the info object.
     *
     * @param document
     * @return Xml representation of the node type definition(s)
     * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document)
     */
public Element toXml(Document document) {
    Element report = document.createElement(NODETYPES_ELEMENT);
    // loop over the nodetypes to be returned in the report
    while (ntIter.hasNext()) {
        NodeType nt = ntIter.nextNodeType();
        Element ntDef = document.createElement(NODETYPE_ELEMENT);
        ntDef.setAttribute(NAME_ATTRIBUTE, nt.getName());
        ntDef.setAttribute(ISMIXIN_ATTRIBUTE, Boolean.toString(nt.isMixin()));
        ntDef.setAttribute(HASORDERABLECHILDNODES_ATTRIBUTE, Boolean.toString(nt.hasOrderableChildNodes()));
        // JCR 2.0 extension
        ntDef.setAttribute(ISABSTRACT_ATTRIBUTE, Boolean.toString(nt.isAbstract()));
        // JCR 2.0 extension
        ntDef.setAttribute(ISQUERYABLE_ATTRIBUTE, Boolean.toString(nt.isQueryable()));
        // declared supertypes
        Element supertypes = DomUtil.addChildElement(ntDef, SUPERTYPES_ELEMENT, null);
        for (NodeType snt : nt.getDeclaredSupertypes()) {
            DomUtil.addChildElement(supertypes, SUPERTYPE_ELEMENT, null, snt.getName());
        }
        // declared child node definitions
        for (NodeDefinition aCnd : nt.getChildNodeDefinitions()) {
            if (aCnd.getDeclaringNodeType().getName().equals(nt.getName())) {
                ntDef.appendChild(NodeDefinitionImpl.create(aCnd).toXml(document));
            }
        }
        // declared property definitions
        for (PropertyDefinition aPd : nt.getPropertyDefinitions()) {
            if (aPd.getDeclaringNodeType().getName().equals(nt.getName())) {
                ntDef.appendChild(PropertyDefinitionImpl.create(aPd).toXml(document));
            }
        }
        String primaryItemName = nt.getPrimaryItemName();
        if (primaryItemName != null) {
            ntDef.setAttribute(PRIMARYITEMNAME_ATTRIBUTE, primaryItemName);
        }
        report.appendChild(ntDef);
    }
    return report;
}
Also used : Element(org.w3c.dom.Element) NodeType(javax.jcr.nodetype.NodeType) NodeDefinition(javax.jcr.nodetype.NodeDefinition) PropertyDefinition(javax.jcr.nodetype.PropertyDefinition)

Example 19 with NodeDefinition

use of javax.jcr.nodetype.NodeDefinition in project jackrabbit by apache.

the class NodeTypeTest method testGetDeclaredChildNodeDefs.

/**
     * Test if all node defs returned by getDeclaredChildNodeDefs() are also
     * returned by getChildNodeDefs(). All existing node types are tested.
     */
public void testGetDeclaredChildNodeDefs() throws RepositoryException {
    NodeTypeIterator types = manager.getAllNodeTypes();
    while (types.hasNext()) {
        NodeType type = types.nextNodeType();
        NodeDefinition[] declaredDefs = type.getDeclaredChildNodeDefinitions();
        NodeDefinition[] defs = type.getChildNodeDefinitions();
        try {
            for (int i = 0; i < declaredDefs.length; i++) {
                boolean exists = false;
                for (int j = 0; j < defs.length; j++) {
                    if (defs[j].getName().equals(declaredDefs[i].getName())) {
                        exists = true;
                        break;
                    }
                }
                assertTrue("All node defs returned by " + "getDeclaredChildNodeDefs() must also be " + "returned by getChildNodeDefs().", exists);
            }
        } catch (ArrayIndexOutOfBoundsException e) {
            fail("The array returned by " + "getDeclaredChildNodeDefs() must not exceed " + "the one returned by getChildNodeDefs()");
        }
    }
}
Also used : NodeType(javax.jcr.nodetype.NodeType) NodeDefinition(javax.jcr.nodetype.NodeDefinition) NodeTypeIterator(javax.jcr.nodetype.NodeTypeIterator)

Example 20 with NodeDefinition

use of javax.jcr.nodetype.NodeDefinition in project jackrabbit by apache.

the class WorkspaceRestoreTest method testWorkspaceRestoreWithUUIDConflict.

/**
     * Tests if restoring the <code>Version</code> of an existing node throws an
     * <code>ItemExistsException</code> if removeExisting is set to FALSE.
     */
@SuppressWarnings("deprecation")
public void testWorkspaceRestoreWithUUIDConflict() throws RepositoryException, NotExecutableException {
    try {
        // Verify that nodes used for the test are indeed versionable
        NodeDefinition nd = wVersionableNode.getDefinition();
        if (nd.getOnParentVersion() != OnParentVersionAction.COPY && nd.getOnParentVersion() != OnParentVersionAction.VERSION) {
            throw new NotExecutableException("Nodes must be versionable in order to run this test.");
        }
        Version v = wVersionableNode.checkin();
        wVersionableNode.checkout();
        wSuperuser.move(wVersionableChildNode.getPath(), wVersionableNode2.getPath() + "/" + wVersionableChildNode.getName());
        wSuperuser.save();
        wSuperuser.getWorkspace().restore(new Version[] { v }, false);
        fail("Node.restore( Version, boolean ): An ItemExistsException must be thrown if the node to be restored already exsits and removeExisting was set to false.");
    } catch (ItemExistsException e) {
    // success
    }
}
Also used : NotExecutableException(org.apache.jackrabbit.test.NotExecutableException) Version(javax.jcr.version.Version) ItemExistsException(javax.jcr.ItemExistsException) NodeDefinition(javax.jcr.nodetype.NodeDefinition)

Aggregations

NodeDefinition (javax.jcr.nodetype.NodeDefinition)77 NodeType (javax.jcr.nodetype.NodeType)44 NotExecutableException (org.apache.jackrabbit.test.NotExecutableException)29 Node (javax.jcr.Node)17 ItemExistsException (javax.jcr.ItemExistsException)14 NodeTypeIterator (javax.jcr.nodetype.NodeTypeIterator)13 PropertyDefinition (javax.jcr.nodetype.PropertyDefinition)13 Version (javax.jcr.version.Version)12 Test (org.junit.Test)11 NodeTypeManager (javax.jcr.nodetype.NodeTypeManager)8 RepositoryException (javax.jcr.RepositoryException)7 HashSet (java.util.HashSet)5 ConstraintViolationException (javax.jcr.nodetype.ConstraintViolationException)5 Name (org.apache.jackrabbit.spi.Name)5 QNodeDefinition (org.apache.jackrabbit.spi.QNodeDefinition)5 NodeDefinitionImpl (org.apache.jackrabbit.spi.commons.nodetype.NodeDefinitionImpl)5 ArrayList (java.util.ArrayList)4 NodeState (org.apache.jackrabbit.core.state.NodeState)4 QPropertyDefinition (org.apache.jackrabbit.spi.QPropertyDefinition)4 Session (javax.jcr.Session)3