Search in sources :

Example 1 with NodeTypeImpl

use of org.apache.jackrabbit.core.nodetype.NodeTypeImpl 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 2 with NodeTypeImpl

use of org.apache.jackrabbit.core.nodetype.NodeTypeImpl in project jackrabbit by apache.

the class RemoveMixinOperation method perform.

public Object perform(SessionContext context) throws RepositoryException {
    SessionImpl session = context.getSessionImpl();
    ItemManager itemMgr = context.getItemManager();
    SessionItemStateManager stateMgr = context.getItemStateManager();
    context.getItemValidator().checkModify(node, CHECK_LOCK | CHECK_CHECKED_OUT | CHECK_CONSTRAINTS | CHECK_HOLD, Permission.NODE_TYPE_MNGMT);
    // check if mixin is assigned
    NodeState state = node.getNodeState();
    if (!state.getMixinTypeNames().contains(mixinName)) {
        throw new NoSuchNodeTypeException("Mixin " + context.getJCRName(mixinName) + " not included in " + node);
    }
    NodeTypeManagerImpl ntMgr = context.getNodeTypeManager();
    NodeTypeRegistry ntReg = context.getNodeTypeRegistry();
    // build effective node type of remaining mixin's & primary type
    Set<Name> remainingMixins = new HashSet<Name>(state.getMixinTypeNames());
    // remove name of target mixin
    remainingMixins.remove(mixinName);
    EffectiveNodeType entResulting;
    try {
        // build effective node type representing primary type
        // including remaining mixin's
        entResulting = ntReg.getEffectiveNodeType(state.getNodeTypeName(), remainingMixins);
    } catch (NodeTypeConflictException e) {
        throw new ConstraintViolationException(e.getMessage(), e);
    }
    // mix:referenceable needs special handling because it has
    // special semantics:
    // it can only be removed if there no more references to this node
    NodeTypeImpl mixin = ntMgr.getNodeType(mixinName);
    if (isReferenceable(mixin) && !entResulting.includesNodeType(MIX_REFERENCEABLE)) {
        if (node.getReferences().hasNext()) {
            throw new ConstraintViolationException(mixinName + " can not be removed:" + " the node is being referenced through at least" + " one property of type REFERENCE");
        }
    }
    // currently locked even if the editing session is the lock holder.
    if ((NameConstants.MIX_LOCKABLE.equals(mixinName) || mixin.isDerivedFrom(NameConstants.MIX_LOCKABLE)) && !entResulting.includesNodeType(NameConstants.MIX_LOCKABLE) && node.isLocked()) {
        throw new ConstraintViolationException(mixinName + " can not be removed: the node is locked.");
    }
    NodeState thisState = (NodeState) node.getOrCreateTransientItemState();
    // collect information about properties and nodes which require further
    // action as a result of the mixin removal; we need to do this *before*
    // actually changing the assigned mixin types, otherwise we wouldn't
    // be able to retrieve the current definition of an item.
    Map<PropertyId, PropertyDefinition> affectedProps = new HashMap<PropertyId, PropertyDefinition>();
    Map<ChildNodeEntry, NodeDefinition> affectedNodes = new HashMap<ChildNodeEntry, NodeDefinition>();
    try {
        Set<Name> names = thisState.getPropertyNames();
        for (Name propName : names) {
            PropertyId propId = new PropertyId(thisState.getNodeId(), propName);
            PropertyState propState = (PropertyState) stateMgr.getItemState(propId);
            PropertyDefinition oldDef = itemMgr.getDefinition(propState);
            // check if property has been defined by mixin type
            // (or one of its supertypes)
            NodeTypeImpl declaringNT = (NodeTypeImpl) oldDef.getDeclaringNodeType();
            if (!entResulting.includesNodeType(declaringNT.getQName())) {
                // the resulting effective node type doesn't include the
                // node type that declared this property
                affectedProps.put(propId, oldDef);
            }
        }
        List<ChildNodeEntry> entries = thisState.getChildNodeEntries();
        for (ChildNodeEntry entry : entries) {
            NodeState nodeState = (NodeState) stateMgr.getItemState(entry.getId());
            NodeDefinition oldDef = itemMgr.getDefinition(nodeState);
            // check if node has been defined by mixin type
            // (or one of its supertypes)
            NodeTypeImpl declaringNT = (NodeTypeImpl) oldDef.getDeclaringNodeType();
            if (!entResulting.includesNodeType(declaringNT.getQName())) {
                // the resulting effective node type doesn't include the
                // node type that declared this child node
                affectedNodes.put(entry, oldDef);
            }
        }
    } catch (ItemStateException e) {
        throw new RepositoryException("Failed to determine effect of removing mixin " + context.getJCRName(mixinName), e);
    }
    // modify the state of this node
    thisState.setMixinTypeNames(remainingMixins);
    // set jcr:mixinTypes property
    node.setMixinTypesProperty(remainingMixins);
    // process affected nodes & properties:
    // 1. try to redefine item based on the resulting
    // new effective node type (see JCR-2130)
    // 2. remove item if 1. fails
    boolean success = false;
    try {
        for (Map.Entry<PropertyId, PropertyDefinition> entry : affectedProps.entrySet()) {
            PropertyId id = entry.getKey();
            PropertyImpl prop = (PropertyImpl) itemMgr.getItem(id);
            PropertyDefinition oldDef = entry.getValue();
            if (oldDef.isProtected()) {
                // remove 'orphaned' protected properties immediately
                node.removeChildProperty(id.getName());
                continue;
            }
            // redefine property if possible (JCR-2130)
            try {
                PropertyDefinitionImpl newDef = node.getApplicablePropertyDefinition(id.getName(), prop.getType(), oldDef.isMultiple(), false);
                if (newDef.getRequiredType() != PropertyType.UNDEFINED && newDef.getRequiredType() != prop.getType()) {
                    // value conversion required
                    if (oldDef.isMultiple()) {
                        // convert value
                        Value[] values = ValueHelper.convert(prop.getValues(), newDef.getRequiredType(), session.getValueFactory());
                        // redefine property
                        prop.onRedefine(newDef.unwrap());
                        // set converted values
                        prop.setValue(values);
                    } else {
                        // convert value
                        Value value = ValueHelper.convert(prop.getValue(), newDef.getRequiredType(), session.getValueFactory());
                        // redefine property
                        prop.onRedefine(newDef.unwrap());
                        // set converted values
                        prop.setValue(value);
                    }
                } else {
                    // redefine property
                    prop.onRedefine(newDef.unwrap());
                }
            } catch (ValueFormatException vfe) {
                // value conversion failed, remove it
                node.removeChildProperty(id.getName());
            } catch (ConstraintViolationException cve) {
                // no suitable definition found for this property,
                // remove it
                node.removeChildProperty(id.getName());
            }
        }
        for (ChildNodeEntry entry : affectedNodes.keySet()) {
            NodeState nodeState = (NodeState) stateMgr.getItemState(entry.getId());
            NodeImpl childNode = (NodeImpl) itemMgr.getItem(entry.getId());
            NodeDefinition oldDef = affectedNodes.get(entry);
            if (oldDef.isProtected()) {
                // remove 'orphaned' protected child node immediately
                node.removeChildNode(entry.getId());
                continue;
            }
            // redefine node if possible (JCR-2130)
            try {
                NodeDefinitionImpl newDef = node.getApplicableChildNodeDefinition(entry.getName(), nodeState.getNodeTypeName());
                // redefine node
                childNode.onRedefine(newDef.unwrap());
            } catch (ConstraintViolationException cve) {
                // no suitable definition found for this child node,
                // remove it
                node.removeChildNode(entry.getId());
            }
        }
        success = true;
    } catch (ItemStateException e) {
        throw new RepositoryException("Failed to clean up child items defined by removed mixin " + context.getJCRName(mixinName), e);
    } finally {
        if (!success) {
        // TODO JCR-1914: revert any changes made so far
        }
    }
    return this;
}
Also used : NodeState(org.apache.jackrabbit.core.state.NodeState) NodeTypeImpl(org.apache.jackrabbit.core.nodetype.NodeTypeImpl) HashMap(java.util.HashMap) NodeTypeConflictException(org.apache.jackrabbit.core.nodetype.NodeTypeConflictException) NodeDefinition(javax.jcr.nodetype.NodeDefinition) Name(org.apache.jackrabbit.spi.Name) NodeDefinitionImpl(org.apache.jackrabbit.spi.commons.nodetype.NodeDefinitionImpl) ConstraintViolationException(javax.jcr.nodetype.ConstraintViolationException) NodeTypeManagerImpl(org.apache.jackrabbit.core.nodetype.NodeTypeManagerImpl) HashSet(java.util.HashSet) ChildNodeEntry(org.apache.jackrabbit.core.state.ChildNodeEntry) PropertyDefinitionImpl(org.apache.jackrabbit.spi.commons.nodetype.PropertyDefinitionImpl) RepositoryException(javax.jcr.RepositoryException) PropertyDefinition(javax.jcr.nodetype.PropertyDefinition) NoSuchNodeTypeException(javax.jcr.nodetype.NoSuchNodeTypeException) PropertyId(org.apache.jackrabbit.core.id.PropertyId) PropertyState(org.apache.jackrabbit.core.state.PropertyState) ItemStateException(org.apache.jackrabbit.core.state.ItemStateException) EffectiveNodeType(org.apache.jackrabbit.core.nodetype.EffectiveNodeType) Value(javax.jcr.Value) ValueFormatException(javax.jcr.ValueFormatException) NodeTypeRegistry(org.apache.jackrabbit.core.nodetype.NodeTypeRegistry) SessionItemStateManager(org.apache.jackrabbit.core.state.SessionItemStateManager) HashMap(java.util.HashMap) Map(java.util.Map)

Example 3 with NodeTypeImpl

use of org.apache.jackrabbit.core.nodetype.NodeTypeImpl in project jackrabbit by apache.

the class NodeImpl method canAddMixin.

/**
 * {@inheritDoc}
 */
public boolean canAddMixin(String mixinName) throws NoSuchNodeTypeException, RepositoryException {
    // check state of this instance
    sanityCheck();
    Name ntName = sessionContext.getQName(mixinName);
    NodeTypeManagerImpl ntMgr = sessionContext.getNodeTypeManager();
    NodeTypeImpl mixin = ntMgr.getNodeType(ntName);
    if (!mixin.isMixin()) {
        return false;
    }
    int options = ItemValidator.CHECK_LOCK | ItemValidator.CHECK_CHECKED_OUT | ItemValidator.CHECK_CONSTRAINTS | ItemValidator.CHECK_HOLD;
    int permissions = Permission.NODE_TYPE_MNGMT;
    // in addition.
    if (NameConstants.MIX_VERSIONABLE.equals(ntName) || NameConstants.MIX_SIMPLE_VERSIONABLE.equals(ntName)) {
        permissions |= Permission.VERSION_MNGMT;
    }
    if (!sessionContext.getItemValidator().canModify(this, options, permissions)) {
        return false;
    }
    final Name primaryTypeName = data.getNodeState().getNodeTypeName();
    NodeTypeImpl primaryType = ntMgr.getNodeType(primaryTypeName);
    if (primaryType.isDerivedFrom(ntName)) {
        // mixin already inherited -> addMixin is allowed but has no effect.
        return true;
    }
    // build effective node type of mixins & primary type
    // in order to detect conflicts
    NodeTypeRegistry ntReg = ntMgr.getNodeTypeRegistry();
    EffectiveNodeType entExisting;
    try {
        // existing mixin's
        Set<Name> mixins = new HashSet<Name>(data.getNodeState().getMixinTypeNames());
        // build effective node type representing primary type including existing mixin's
        entExisting = ntReg.getEffectiveNodeType(primaryTypeName, mixins);
        if (entExisting.includesNodeType(ntName)) {
            // addMixin would succeed without modifying the node.
            return true;
        }
        // add new mixin
        mixins.add(ntName);
        // try to build new effective node type (will throw in case of conflicts)
        ntReg.getEffectiveNodeType(primaryTypeName, mixins);
    } catch (NodeTypeConflictException ntce) {
        return false;
    }
    return true;
}
Also used : EffectiveNodeType(org.apache.jackrabbit.core.nodetype.EffectiveNodeType) NodeTypeImpl(org.apache.jackrabbit.core.nodetype.NodeTypeImpl) NodeTypeConflictException(org.apache.jackrabbit.core.nodetype.NodeTypeConflictException) NodeTypeRegistry(org.apache.jackrabbit.core.nodetype.NodeTypeRegistry) NodeTypeManagerImpl(org.apache.jackrabbit.core.nodetype.NodeTypeManagerImpl) Name(org.apache.jackrabbit.spi.Name) HashSet(java.util.HashSet)

Example 4 with NodeTypeImpl

use of org.apache.jackrabbit.core.nodetype.NodeTypeImpl in project jackrabbit by apache.

the class NodeImpl method rename.

// -------------------------------------------------------< JackrabbitNode >
/**
 * {@inheritDoc}
 */
public void rename(String newName) throws RepositoryException {
    // check if this is the root node
    if (getDepth() == 0) {
        throw new RepositoryException("Cannot rename the root node");
    }
    Name qName;
    try {
        qName = sessionContext.getQName(newName);
    } catch (NameException e) {
        throw new RepositoryException("invalid node name: " + newName, e);
    }
    NodeImpl parent = (NodeImpl) getParent();
    // check for name collisions
    NodeImpl existing = null;
    try {
        existing = parent.getNode(qName);
        // check same-name sibling setting of existing node
        if (!existing.getDefinition().allowsSameNameSiblings()) {
            throw new ItemExistsException("Same name siblings are not allowed: " + existing);
        }
    } catch (AccessDeniedException ade) {
        // FIXME by throwing ItemExistsException we're disclosing too much information
        throw new ItemExistsException();
    } catch (ItemNotFoundException infe) {
    // no name collision, fall through
    }
    // verify that parent node
    // - is checked-out
    // - is not protected neither by node type constraints nor by retention/hold
    int options = ItemValidator.CHECK_CHECKED_OUT | ItemValidator.CHECK_LOCK | ItemValidator.CHECK_CONSTRAINTS | ItemValidator.CHECK_HOLD | ItemValidator.CHECK_RETENTION;
    sessionContext.getItemValidator().checkRemove(parent, options, Permission.NONE);
    sessionContext.getItemValidator().checkModify(parent, options, Permission.NONE);
    // check constraints
    // get applicable definition of renamed target node
    NodeTypeImpl nt = (NodeTypeImpl) getPrimaryNodeType();
    org.apache.jackrabbit.spi.commons.nodetype.NodeDefinitionImpl newTargetDef;
    try {
        newTargetDef = parent.getApplicableChildNodeDefinition(qName, nt.getQName());
    } catch (RepositoryException re) {
        String msg = safeGetJCRPath() + ": no definition found in parent node's node type for renamed node";
        log.debug(msg);
        throw new ConstraintViolationException(msg, re);
    }
    // necessarily have identical definitions
    if (existing != null && !newTargetDef.allowsSameNameSiblings()) {
        throw new ItemExistsException("Same name siblings not allowed: " + existing);
    }
    // check permissions:
    // 1. on the parent node the session must have permission to manipulate the child-entries
    AccessManager acMgr = sessionContext.getAccessManager();
    if (!acMgr.isGranted(parent.getPrimaryPath(), qName, Permission.MODIFY_CHILD_NODE_COLLECTION)) {
        String msg = "Not allowed to rename node " + safeGetJCRPath() + " to " + newName;
        log.debug(msg);
        throw new AccessDeniedException(msg);
    }
    // the primary node type on this node itself.
    if (!nt.getName().equals(newTargetDef.getName()) && !(acMgr.isGranted(getPrimaryPath(), Permission.NODE_TYPE_MNGMT))) {
        String msg = "Not allowed to rename node " + safeGetJCRPath() + " to " + newName;
        log.debug(msg);
        throw new AccessDeniedException(msg);
    }
    // change definition
    onRedefine(newTargetDef.unwrap());
    // delegate to parent
    parent.renameChildNode(getNodeId(), qName, true);
}
Also used : AccessManager(org.apache.jackrabbit.core.security.AccessManager) AccessDeniedException(javax.jcr.AccessDeniedException) NodeDefinitionImpl(org.apache.jackrabbit.spi.commons.nodetype.NodeDefinitionImpl) NodeTypeImpl(org.apache.jackrabbit.core.nodetype.NodeTypeImpl) RepositoryException(javax.jcr.RepositoryException) Name(org.apache.jackrabbit.spi.Name) NameException(org.apache.jackrabbit.spi.commons.conversion.NameException) ItemExistsException(javax.jcr.ItemExistsException) ConstraintViolationException(javax.jcr.nodetype.ConstraintViolationException) ItemNotFoundException(javax.jcr.ItemNotFoundException)

Example 5 with NodeTypeImpl

use of org.apache.jackrabbit.core.nodetype.NodeTypeImpl in project jackrabbit by apache.

the class NodeImpl method addNode.

/**
 * Same as <code>{@link Node#addNode(String, String)}</code> except that
 * this method takes <code>Name</code> arguments instead of
 * <code>String</code>s and has an additional <code>uuid</code> argument.
 * <p>
 * <b>Important Notice:</b> This method is for internal use only! Passing
 * already assigned uuid's might lead to unexpected results and
 * data corruption in the worst case.
 *
 * @param nodeName     name of the new node
 * @param nodeTypeName name of the new node's node type or <code>null</code>
 *                     if it should be determined automatically
 * @param id           id of the new node or <code>null</code> if a new
 *                     id should be assigned
 * @return the newly added node
 * @throws RepositoryException if the node can not added
 */
// FIXME: This method should not be public
public synchronized NodeImpl addNode(Name nodeName, Name nodeTypeName, NodeId id) throws RepositoryException {
    // check state of this instance
    sanityCheck();
    Path nodePath = PathFactoryImpl.getInstance().create(getPrimaryPath(), nodeName, true);
    // Check the explicitly specified node type (if any)
    NodeTypeImpl nt = null;
    if (nodeTypeName != null) {
        nt = sessionContext.getNodeTypeManager().getNodeType(nodeTypeName);
        if (nt.isMixin()) {
            throw new ConstraintViolationException("Unable to add a node with a mixin node type: " + sessionContext.getJCRName(nodeTypeName));
        } else if (nt.isAbstract()) {
            throw new ConstraintViolationException("Unable to add a node with an abstract node type: " + sessionContext.getJCRName(nodeTypeName));
        } else {
            // adding a node with explicit specifying the node type name
            // requires the editing session to have nt_management privilege.
            sessionContext.getAccessManager().checkPermission(nodePath, Permission.NODE_TYPE_MNGMT);
        }
    }
    // Get the applicable child node definition for this node.
    NodeDefinitionImpl def;
    try {
        def = getApplicableChildNodeDefinition(nodeName, nodeTypeName);
    } catch (RepositoryException e) {
        throw new ConstraintViolationException("No child node definition for " + sessionContext.getJCRName(nodeName) + " found in " + this, e);
    }
    // Use default node type from child node definition if needed
    if (nt == null) {
        nt = (NodeTypeImpl) def.getDefaultPrimaryType();
    }
    // check the new name
    NodeNameNormalizer.check(nodeName);
    // check for name collisions
    NodeState thisState = data.getNodeState();
    ChildNodeEntry cne = thisState.getChildNodeEntry(nodeName, 1);
    if (cne != null) {
        // check same-name sibling setting of new node
        if (!def.allowsSameNameSiblings()) {
            throw new ItemExistsException("This node already exists: " + itemMgr.safeGetJCRPath(nodePath));
        }
        // check same-name sibling setting of existing node
        NodeImpl existing = itemMgr.getNode(cne.getId(), getNodeId());
        if (!existing.getDefinition().allowsSameNameSiblings()) {
            throw new ItemExistsException("Same-name siblings not allowed for " + existing);
        }
    }
    // check protected flag of parent (i.e. this) node and retention/hold
    // make sure this node is checked-out and not locked by another session.
    int options = ItemValidator.CHECK_LOCK | ItemValidator.CHECK_CHECKED_OUT | ItemValidator.CHECK_CONSTRAINTS | ItemValidator.CHECK_HOLD | ItemValidator.CHECK_RETENTION;
    sessionContext.getItemValidator().checkModify(this, options, Permission.NONE);
    // now do create the child node
    return createChildNode(nodeName, nt, id);
}
Also used : Path(org.apache.jackrabbit.spi.Path) NodeDefinitionImpl(org.apache.jackrabbit.spi.commons.nodetype.NodeDefinitionImpl) NodeTypeImpl(org.apache.jackrabbit.core.nodetype.NodeTypeImpl) NodeState(org.apache.jackrabbit.core.state.NodeState) ItemExistsException(javax.jcr.ItemExistsException) ChildNodeEntry(org.apache.jackrabbit.core.state.ChildNodeEntry) ConstraintViolationException(javax.jcr.nodetype.ConstraintViolationException) RepositoryException(javax.jcr.RepositoryException)

Aggregations

NodeTypeImpl (org.apache.jackrabbit.core.nodetype.NodeTypeImpl)15 RepositoryException (javax.jcr.RepositoryException)9 Name (org.apache.jackrabbit.spi.Name)8 NodeId (org.apache.jackrabbit.core.id.NodeId)7 NodeState (org.apache.jackrabbit.core.state.NodeState)7 ConstraintViolationException (javax.jcr.nodetype.ConstraintViolationException)6 NodeTypeManagerImpl (org.apache.jackrabbit.core.nodetype.NodeTypeManagerImpl)5 ChildNodeEntry (org.apache.jackrabbit.core.state.ChildNodeEntry)5 Path (org.apache.jackrabbit.spi.Path)5 ItemExistsException (javax.jcr.ItemExistsException)4 EffectiveNodeType (org.apache.jackrabbit.core.nodetype.EffectiveNodeType)4 NodeDefinitionImpl (org.apache.jackrabbit.spi.commons.nodetype.NodeDefinitionImpl)4 HashSet (java.util.HashSet)3 AccessDeniedException (javax.jcr.AccessDeniedException)3 NodeDefinition (javax.jcr.nodetype.NodeDefinition)3 PropertyDefinition (javax.jcr.nodetype.PropertyDefinition)3 NodeImpl (org.apache.jackrabbit.core.NodeImpl)3 NodeTypeConflictException (org.apache.jackrabbit.core.nodetype.NodeTypeConflictException)3 NodeTypeRegistry (org.apache.jackrabbit.core.nodetype.NodeTypeRegistry)3 AccessManager (org.apache.jackrabbit.core.security.AccessManager)3