Search in sources :

Example 1 with PropertyId

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

use of org.apache.jackrabbit.core.id.PropertyId in project jackrabbit by apache.

the class LockManagerImpl method removeLockProperties.

/**
     *
     * @param node
     * @throws RepositoryException
     */
protected void removeLockProperties(NodeImpl node) throws RepositoryException {
    boolean success = false;
    SessionImpl editingSession = (SessionImpl) node.getSession();
    WorkspaceImpl wsp = (WorkspaceImpl) editingSession.getWorkspace();
    UpdatableItemStateManager stateMgr = wsp.getItemStateManager();
    try {
        acquireLockPropertiesLock();
        // add properties to content
        if (stateMgr.inEditMode()) {
            throw new RepositoryException("Unable to remove lock properties.");
        }
        stateMgr.edit();
        try {
            NodeId nodeId = node.getNodeId();
            NodeState nodeState = (NodeState) stateMgr.getItemState(nodeId);
            if (nodeState.hasPropertyName(NameConstants.JCR_LOCKOWNER)) {
                PropertyState propState = (PropertyState) stateMgr.getItemState(new PropertyId(nodeId, NameConstants.JCR_LOCKOWNER));
                nodeState.removePropertyName(NameConstants.JCR_LOCKOWNER);
                stateMgr.destroy(propState);
                stateMgr.store(nodeState);
            }
            if (nodeState.hasPropertyName(NameConstants.JCR_LOCKISDEEP)) {
                PropertyState propState = (PropertyState) stateMgr.getItemState(new PropertyId(nodeId, NameConstants.JCR_LOCKISDEEP));
                nodeState.removePropertyName(NameConstants.JCR_LOCKISDEEP);
                stateMgr.destroy(propState);
                stateMgr.store(nodeState);
            }
            stateMgr.update();
            success = true;
        } catch (ItemStateException e) {
            throw new RepositoryException("Error while removing lock.", e);
        } finally {
            if (!success) {
                // failed to set lock meta-data content, cleanup
                stateMgr.cancel();
            }
        }
    } finally {
        releaseLockPropertiesLock();
    }
}
Also used : UpdatableItemStateManager(org.apache.jackrabbit.core.state.UpdatableItemStateManager) WorkspaceImpl(org.apache.jackrabbit.core.WorkspaceImpl) NodeState(org.apache.jackrabbit.core.state.NodeState) NodeId(org.apache.jackrabbit.core.id.NodeId) RepositoryException(javax.jcr.RepositoryException) SessionImpl(org.apache.jackrabbit.core.SessionImpl) PropertyState(org.apache.jackrabbit.core.state.PropertyState) PropertyId(org.apache.jackrabbit.core.id.PropertyId) ItemStateException(org.apache.jackrabbit.core.state.ItemStateException)

Example 3 with PropertyId

use of org.apache.jackrabbit.core.id.PropertyId in project jackrabbit by apache.

the class LockManagerImpl method writeLockProperties.

/**
     * Add the lock related properties to the target node.
     *
     * @param node
     * @param lockOwner
     * @param isDeep
     */
protected void writeLockProperties(NodeImpl node, String lockOwner, boolean isDeep) throws RepositoryException {
    boolean success = false;
    SessionImpl editingSession = (SessionImpl) node.getSession();
    WorkspaceImpl wsp = (WorkspaceImpl) editingSession.getWorkspace();
    UpdatableItemStateManager stateMgr = wsp.getItemStateManager();
    try {
        acquireLockPropertiesLock();
        if (stateMgr.inEditMode()) {
            throw new RepositoryException("Unable to write lock properties.");
        }
        stateMgr.edit();
        try {
            // add properties to content
            NodeId nodeId = node.getNodeId();
            NodeState nodeState = (NodeState) stateMgr.getItemState(nodeId);
            PropertyState propState;
            if (!nodeState.hasPropertyName(NameConstants.JCR_LOCKOWNER)) {
                propState = stateMgr.createNew(NameConstants.JCR_LOCKOWNER, nodeId);
                propState.setType(PropertyType.STRING);
                propState.setMultiValued(false);
            } else {
                propState = (PropertyState) stateMgr.getItemState(new PropertyId(nodeId, NameConstants.JCR_LOCKOWNER));
            }
            propState.setValues(new InternalValue[] { InternalValue.create(lockOwner) });
            nodeState.addPropertyName(NameConstants.JCR_LOCKOWNER);
            stateMgr.store(nodeState);
            if (!nodeState.hasPropertyName(NameConstants.JCR_LOCKISDEEP)) {
                propState = stateMgr.createNew(NameConstants.JCR_LOCKISDEEP, nodeId);
                propState.setType(PropertyType.BOOLEAN);
                propState.setMultiValued(false);
            } else {
                propState = (PropertyState) stateMgr.getItemState(new PropertyId(nodeId, NameConstants.JCR_LOCKISDEEP));
            }
            propState.setValues(new InternalValue[] { InternalValue.create(isDeep) });
            nodeState.addPropertyName(NameConstants.JCR_LOCKISDEEP);
            stateMgr.store(nodeState);
            stateMgr.update();
            success = true;
        } catch (ItemStateException e) {
            throw new RepositoryException("Error while creating lock.", e);
        } finally {
            if (!success) {
                // failed to set lock meta-data content, cleanup
                stateMgr.cancel();
                try {
                    unlock(node);
                } catch (RepositoryException e) {
                    // cleanup failed
                    log.error("error while cleaning up after failed lock attempt", e);
                }
            }
        }
    } finally {
        releaseLockPropertiesLock();
    }
}
Also used : UpdatableItemStateManager(org.apache.jackrabbit.core.state.UpdatableItemStateManager) WorkspaceImpl(org.apache.jackrabbit.core.WorkspaceImpl) NodeState(org.apache.jackrabbit.core.state.NodeState) NodeId(org.apache.jackrabbit.core.id.NodeId) RepositoryException(javax.jcr.RepositoryException) SessionImpl(org.apache.jackrabbit.core.SessionImpl) PropertyState(org.apache.jackrabbit.core.state.PropertyState) PropertyId(org.apache.jackrabbit.core.id.PropertyId) ItemStateException(org.apache.jackrabbit.core.state.ItemStateException)

Example 4 with PropertyId

use of org.apache.jackrabbit.core.id.PropertyId in project jackrabbit by apache.

the class SharedItemStateManager method createInstance.

/**
     * Create a new property state instance
     *
     * @param propName   property name
     * @param parentId parent Id
     * @return new property state instance
     */
private PropertyState createInstance(Name propName, NodeId parentId) {
    PropertyState state = persistMgr.createNew(new PropertyId(parentId, propName));
    state.setStatus(ItemState.STATUS_NEW);
    state.setContainer(this);
    return state;
}
Also used : PropertyId(org.apache.jackrabbit.core.id.PropertyId)

Example 5 with PropertyId

use of org.apache.jackrabbit.core.id.PropertyId in project jackrabbit by apache.

the class NodeStateMerger method conflicts.

/**
     *
     * @param state The state of the node to be saved.
     * @param addedMixins The added mixins to be used for testing
     * @param ctx
     * @param compareToOverlayed
     * @return true if a conflict can be determined, false otherwise.
     */
private static boolean conflicts(NodeState state, Set<Name> addedMixins, MergeContext ctx, boolean compareToOverlayed) {
    try {
        // if the mixin defines residual item definitions -> return false.
        for (Name mixinName : addedMixins) {
            EffectiveNodeType ent = ctx.getEffectiveNodeType(mixinName);
            if (ent.getUnnamedItemDefs().length > 0) {
                // easily determine conflicts
                return false;
            }
            NodeState overlayed = (NodeState) state.getOverlayedState();
            for (ChildNodeEntry cne : state.getChildNodeEntries()) {
                if (ent.getNamedNodeDefs(cne.getName()).length > 0) {
                    if (ctx.isAdded(cne.getId()) || isAutoCreated(cne, ent)) {
                        if (!compareToOverlayed || overlayed.hasChildNodeEntry(cne.getName())) {
                            return true;
                        }
                    }
                // else: neither added nor autocreated in 'state' .
                }
            // else: child node not defined by the added mixin type
            }
            for (Name propName : state.getPropertyNames()) {
                if (ent.getNamedPropDefs(propName).length > 0) {
                    PropertyId pid = new PropertyId(state.getNodeId(), propName);
                    if (ctx.isAdded(pid) || isAutoCreated(propName, ent)) {
                        if (!compareToOverlayed || overlayed.hasPropertyName(propName)) {
                            return true;
                        }
                    }
                // else: neither added nor autocreated in 'state'
                }
            // else: property not defined by added mixin
            }
        }
    } catch (NoSuchNodeTypeException e) {
        // unable to determine collision
        return true;
    }
    // no conflict detected
    return false;
}
Also used : EffectiveNodeType(org.apache.jackrabbit.core.nodetype.EffectiveNodeType) Name(org.apache.jackrabbit.spi.Name) PropertyId(org.apache.jackrabbit.core.id.PropertyId) NoSuchNodeTypeException(javax.jcr.nodetype.NoSuchNodeTypeException)

Aggregations

PropertyId (org.apache.jackrabbit.core.id.PropertyId)59 Name (org.apache.jackrabbit.spi.Name)29 PropertyState (org.apache.jackrabbit.core.state.PropertyState)25 NodeState (org.apache.jackrabbit.core.state.NodeState)23 RepositoryException (javax.jcr.RepositoryException)22 ItemStateException (org.apache.jackrabbit.core.state.ItemStateException)22 NodeId (org.apache.jackrabbit.core.id.NodeId)16 InternalValue (org.apache.jackrabbit.core.value.InternalValue)14 NoSuchItemStateException (org.apache.jackrabbit.core.state.NoSuchItemStateException)12 ChildNodeEntry (org.apache.jackrabbit.core.state.ChildNodeEntry)11 HashSet (java.util.HashSet)10 InvalidItemStateException (javax.jcr.InvalidItemStateException)9 ArrayList (java.util.ArrayList)7 EffectiveNodeType (org.apache.jackrabbit.core.nodetype.EffectiveNodeType)6 ConstraintViolationException (javax.jcr.nodetype.ConstraintViolationException)5 NodeReferences (org.apache.jackrabbit.core.state.NodeReferences)5 PropertyDefinitionImpl (org.apache.jackrabbit.spi.commons.nodetype.PropertyDefinitionImpl)5 ItemId (org.apache.jackrabbit.core.id.ItemId)4 NodeTypeManagerImpl (org.apache.jackrabbit.core.nodetype.NodeTypeManagerImpl)4 PropertyEntry (org.apache.jackrabbit.core.persistence.util.NodePropBundle.PropertyEntry)4