Search in sources :

Example 1 with AccessManager

use of org.apache.jackrabbit.core.security.AccessManager 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 AccessManager

use of org.apache.jackrabbit.core.security.AccessManager 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 3 with AccessManager

use of org.apache.jackrabbit.core.security.AccessManager in project jackrabbit by apache.

the class ProtectedItemModifier method checkPermission.

private void checkPermission(ItemImpl item, int perm) throws RepositoryException {
    if (perm > Permission.NONE) {
        SessionImpl sImpl = (SessionImpl) item.getSession();
        AccessManager acMgr = sImpl.getAccessManager();
        Path path = item.getPrimaryPath();
        acMgr.checkPermission(path, perm);
    }
}
Also used : AccessManager(org.apache.jackrabbit.core.security.AccessManager) Path(org.apache.jackrabbit.spi.Path)

Example 4 with AccessManager

use of org.apache.jackrabbit.core.security.AccessManager in project jackrabbit by apache.

the class NodeImpl method orderBefore.

/**
     * Same as <code>{@link Node#orderBefore(String, String)}</code> except that
     * this method takes a <code>Path.Element</code> arguments instead of
     * <code>String</code>s.
     *
     * @param srcName
     * @param dstName
     * @throws UnsupportedRepositoryOperationException
     * @throws VersionException
     * @throws ConstraintViolationException
     * @throws ItemNotFoundException
     * @throws LockException
     * @throws RepositoryException
     */
public synchronized void orderBefore(Path.Element srcName, Path.Element dstName) throws UnsupportedRepositoryOperationException, VersionException, ConstraintViolationException, ItemNotFoundException, LockException, RepositoryException {
    // check state of this instance
    sanityCheck();
    if (!getPrimaryNodeType().hasOrderableChildNodes()) {
        throw new UnsupportedRepositoryOperationException("child node ordering not supported on " + this);
    }
    // check arguments
    if (srcName.equals(dstName)) {
        // there's nothing to do
        return;
    }
    // check existence
    if (!hasNode(srcName.getName(), srcName.getIndex())) {
        String name;
        try {
            Path.Element[] path = new Path.Element[] { srcName };
            name = sessionContext.getJCRPath(new PathBuilder(path).getPath());
        } catch (NameException e) {
            name = srcName.toString();
        } catch (NamespaceException e) {
            name = srcName.toString();
        }
        throw new ItemNotFoundException(this + " has no child node with name " + name);
    }
    if (dstName != null && !hasNode(dstName.getName(), dstName.getIndex())) {
        String name;
        try {
            Path.Element[] path = new Path.Element[] { dstName };
            name = sessionContext.getJCRPath(new PathBuilder(path).getPath());
        } catch (NameException e) {
            name = dstName.toString();
        } catch (NamespaceException e) {
            name = dstName.toString();
        }
        throw new ItemNotFoundException(this + " has no child node with name " + name);
    }
    // make sure this node is checked-out and neither protected nor locked
    int options = ItemValidator.CHECK_LOCK | ItemValidator.CHECK_CHECKED_OUT | ItemValidator.CHECK_CONSTRAINTS;
    sessionContext.getItemValidator().checkModify(this, options, Permission.NONE);
    /*
        make sure the session is allowed to reorder child nodes.
        since there is no specific privilege for reordering child nodes,
        test if the the node to be reordered can be removed and added,
        i.e. treating reorder similar to a move.
        TODO: properly deal with sns in which case the index would change upon reorder.
        */
    AccessManager acMgr = sessionContext.getAccessManager();
    PathBuilder pb = new PathBuilder(getPrimaryPath());
    pb.addLast(srcName.getName(), srcName.getIndex());
    Path childPath = pb.getPath();
    if (!acMgr.isGranted(childPath, Permission.MODIFY_CHILD_NODE_COLLECTION)) {
        String msg = "Not allowed to reorder child node " + sessionContext.getJCRPath(childPath) + ".";
        log.debug(msg);
        throw new AccessDeniedException(msg);
    }
    ArrayList<ChildNodeEntry> list = new ArrayList<ChildNodeEntry>(data.getNodeState().getChildNodeEntries());
    int srcInd = -1, destInd = -1;
    for (int i = 0; i < list.size(); i++) {
        ChildNodeEntry entry = list.get(i);
        if (srcInd == -1) {
            if (entry.getName().equals(srcName.getName()) && (entry.getIndex() == srcName.getIndex() || srcName.getIndex() == 0 && entry.getIndex() == 1)) {
                srcInd = i;
            }
        }
        if (destInd == -1 && dstName != null) {
            if (entry.getName().equals(dstName.getName()) && (entry.getIndex() == dstName.getIndex() || dstName.getIndex() == 0 && entry.getIndex() == 1)) {
                destInd = i;
                if (srcInd != -1) {
                    break;
                }
            }
        } else {
            if (srcInd != -1) {
                break;
            }
        }
    }
    // check if resulting order would be different to current order
    if (destInd == -1) {
        if (srcInd == list.size() - 1) {
            // no change, we're done
            return;
        }
    } else {
        if ((destInd - srcInd) == 1) {
            // no change, we're done
            return;
        }
    }
    // reorder list
    if (destInd == -1) {
        list.add(list.remove(srcInd));
    } else {
        if (srcInd < destInd) {
            list.add(destInd, list.get(srcInd));
            list.remove(srcInd);
        } else {
            list.add(destInd, list.remove(srcInd));
        }
    }
    // modify the state of 'this', i.e. the parent node
    NodeState thisState = (NodeState) getOrCreateTransientItemState();
    thisState.setChildNodeEntries(list);
}
Also used : AccessManager(org.apache.jackrabbit.core.security.AccessManager) Path(org.apache.jackrabbit.spi.Path) UnsupportedRepositoryOperationException(javax.jcr.UnsupportedRepositoryOperationException) AccessDeniedException(javax.jcr.AccessDeniedException) NodeState(org.apache.jackrabbit.core.state.NodeState) ChildNodeEntry(org.apache.jackrabbit.core.state.ChildNodeEntry) ArrayList(java.util.ArrayList) PathBuilder(org.apache.jackrabbit.spi.commons.name.PathBuilder) NameException(org.apache.jackrabbit.spi.commons.conversion.NameException) NamespaceException(javax.jcr.NamespaceException) ItemNotFoundException(javax.jcr.ItemNotFoundException)

Example 5 with AccessManager

use of org.apache.jackrabbit.core.security.AccessManager in project jackrabbit by apache.

the class SessionMoveOperation method perform.

public Object perform(SessionContext context) throws RepositoryException {
    // Get node instances
    NodeImpl targetNode = getNode(context, srcPath, srcAbsPath);
    NodeImpl srcParentNode = getNode(context, srcPath.getAncestor(1), srcAbsPath);
    NodeImpl destParentNode = getNode(context, destPath.getAncestor(1), destAbsPath);
    if (context.getHierarchyManager().isShareAncestor(targetNode.getNodeId(), destParentNode.getNodeId())) {
        throw new RepositoryException("Move not possible because of a share cycle between " + srcAbsPath + " and " + destAbsPath);
    }
    // check for name collisions
    NodeImpl existing = null;
    try {
        existing = context.getItemManager().getNode(destPath);
        // 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(destAbsPath);
    } catch (PathNotFoundException pnfe) {
    // no name collision, fall through
    }
    // verify that the targetNode can be removed
    int options = ItemValidator.CHECK_HOLD | ItemValidator.CHECK_RETENTION;
    context.getItemValidator().checkRemove(targetNode, options, Permission.NONE);
    // verify for both source and destination parent nodes that
    // - they are checked-out
    // - are not protected neither by node type constraints nor by retention/hold
    options = ItemValidator.CHECK_CHECKED_OUT | ItemValidator.CHECK_LOCK | ItemValidator.CHECK_CONSTRAINTS | ItemValidator.CHECK_HOLD | ItemValidator.CHECK_RETENTION;
    context.getItemValidator().checkModify(srcParentNode, options, Permission.NONE);
    context.getItemValidator().checkModify(destParentNode, options, Permission.NONE);
    // check constraints
    // get applicable definition of target node at new location
    NodeTypeImpl nt = (NodeTypeImpl) targetNode.getPrimaryNodeType();
    org.apache.jackrabbit.spi.commons.nodetype.NodeDefinitionImpl newTargetDef;
    try {
        newTargetDef = destParentNode.getApplicableChildNodeDefinition(destPath.getName(), nt.getQName());
    } catch (RepositoryException re) {
        String msg = destAbsPath + ": no definition found in parent node's node type for new 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);
    }
    NodeId targetId = targetNode.getNodeId();
    // check permissions
    AccessManager acMgr = context.getAccessManager();
    if (!(acMgr.isGranted(srcPath, Permission.REMOVE_NODE) && acMgr.isGranted(destPath, Permission.ADD_NODE | Permission.NODE_TYPE_MNGMT))) {
        String msg = "Not allowed to move node " + srcAbsPath + " to " + destAbsPath;
        log.debug(msg);
        throw new AccessDeniedException(msg);
    }
    if (srcParentNode.isSame(destParentNode)) {
        // change definition of target
        targetNode.onRedefine(newTargetDef.unwrap());
        // do rename
        destParentNode.renameChildNode(targetId, destPath.getName(), false);
    } else {
        // check shareable case
        if (targetNode.getNodeState().isShareable()) {
            String msg = "Moving a shareable node is not supported.";
            log.debug(msg);
            throw new UnsupportedRepositoryOperationException(msg);
        }
        // change definition of target
        targetNode.onRedefine(newTargetDef.unwrap());
        // Get the transient states
        NodeState srcParentState = (NodeState) srcParentNode.getOrCreateTransientItemState();
        NodeState targetState = (NodeState) targetNode.getOrCreateTransientItemState();
        NodeState destParentState = (NodeState) destParentNode.getOrCreateTransientItemState();
        // 1. remove child node entry from old parent
        if (srcParentState.removeChildNodeEntry(targetId)) {
            // 2. re-parent target node
            targetState.setParentId(destParentNode.getNodeId());
            // 3. add child node entry to new parent
            destParentState.addChildNodeEntry(destPath.getName(), targetId);
        }
    }
    return this;
}
Also used : AccessManager(org.apache.jackrabbit.core.security.AccessManager) UnsupportedRepositoryOperationException(javax.jcr.UnsupportedRepositoryOperationException) AccessDeniedException(javax.jcr.AccessDeniedException) NodeTypeImpl(org.apache.jackrabbit.core.nodetype.NodeTypeImpl) NodeState(org.apache.jackrabbit.core.state.NodeState) RepositoryException(javax.jcr.RepositoryException) ItemExistsException(javax.jcr.ItemExistsException) NodeId(org.apache.jackrabbit.core.id.NodeId) ConstraintViolationException(javax.jcr.nodetype.ConstraintViolationException) PathNotFoundException(javax.jcr.PathNotFoundException)

Aggregations

AccessManager (org.apache.jackrabbit.core.security.AccessManager)11 AccessDeniedException (javax.jcr.AccessDeniedException)9 RepositoryException (javax.jcr.RepositoryException)8 NodeState (org.apache.jackrabbit.core.state.NodeState)6 ConstraintViolationException (javax.jcr.nodetype.ConstraintViolationException)5 Path (org.apache.jackrabbit.spi.Path)5 ItemNotFoundException (javax.jcr.ItemNotFoundException)4 NodeId (org.apache.jackrabbit.core.id.NodeId)4 ItemExistsException (javax.jcr.ItemExistsException)3 PathNotFoundException (javax.jcr.PathNotFoundException)3 UnsupportedRepositoryOperationException (javax.jcr.UnsupportedRepositoryOperationException)3 EffectiveNodeType (org.apache.jackrabbit.core.nodetype.EffectiveNodeType)3 NodeTypeImpl (org.apache.jackrabbit.core.nodetype.NodeTypeImpl)3 RetentionRegistry (org.apache.jackrabbit.core.retention.RetentionRegistry)3 ChildNodeEntry (org.apache.jackrabbit.core.state.ChildNodeEntry)3 QItemDefinition (org.apache.jackrabbit.spi.QItemDefinition)3 AccessManagerConfig (org.apache.jackrabbit.core.config.AccessManagerConfig)2 AccessControlProvider (org.apache.jackrabbit.core.security.authorization.AccessControlProvider)2 WorkspaceAccessManager (org.apache.jackrabbit.core.security.authorization.WorkspaceAccessManager)2 ItemStateException (org.apache.jackrabbit.core.state.ItemStateException)2