Package org.apache.jackrabbit.core.state

Examples of org.apache.jackrabbit.core.state.SessionItemStateManager


    public ItemSaveOperation(ItemState state) {
        this.state = state;
    }

    public Object perform(SessionContext context) throws RepositoryException {
        SessionItemStateManager stateMgr = context.getItemStateManager();

        /**
         * build list of transient (i.e. new & modified) states that
         * should be persisted
         */
        Collection<ItemState> dirty;
        try {
            dirty = getTransientStates(context.getItemStateManager());
        } catch (ConcurrentModificationException e) {
            String msg = "Concurrent modification; session is closed";
            log.error(msg, e);
            context.getSessionImpl().logout();
            throw e;
        }
        if (dirty.size() == 0) {
            // no transient items, nothing to do here
            return this;
        }

        /**
         * build list of transient descendants in the attic
         * (i.e. those marked as 'removed')
         */
        Collection<ItemState> removed =
            getRemovedStates(context.getItemStateManager());

        // All affected item states. The keys are used to look up whether
        // an item is affected, and the values are iterated through below
        Map<ItemId, ItemState> affected =
            new HashMap<ItemId, ItemState>(dirty.size() + removed.size());
        for (ItemState state : dirty) {
            affected.put(state.getId(), state);
        }
        for (ItemState state : removed) {
            affected.put(state.getId(), state);
        }

        /**
         * make sure that this save operation is totally 'self-contained'
         * and independent; items within the scope of this save operation
         * must not have 'external' dependencies;
         * (e.g. moving a node requires that the target node including both
         * old and new parents are saved)
         */
        for (ItemState transientState : affected.values()) {
            if (transientState.isNode()) {
                NodeState nodeState = (NodeState) transientState;
                Set<NodeId> dependentIDs = new HashSet<NodeId>();
                if (nodeState.hasOverlayedState()) {
                    NodeState overlayedState =
                            (NodeState) nodeState.getOverlayedState();
                    NodeId oldParentId = overlayedState.getParentId();
                    NodeId newParentId = nodeState.getParentId();
                    if (oldParentId != null) {
                        if (newParentId == null) {
                            // node has been removed, add old parents
                            // to dependencies
                            if (overlayedState.isShareable()) {
                                dependentIDs.addAll(overlayedState.getSharedSet());
                            } else {
                                dependentIDs.add(oldParentId);
                            }
                        } else {
                            if (!oldParentId.equals(newParentId)) {
                                // node has been moved to a new location,
                                // add old and new parent to dependencies
                                dependentIDs.add(oldParentId);
                                dependentIDs.add(newParentId);
                            } else {
                                // parent id hasn't changed, check whether
                                // the node has been renamed (JCR-1034)
                                if (!affected.containsKey(newParentId)
                                        && stateMgr.hasTransientItemState(newParentId)) {
                                    try {
                                        NodeState parent = (NodeState) stateMgr.getTransientItemState(newParentId);
                                        // check parent's renamed child node entries
                                        for (ChildNodeEntry cne : parent.getRenamedChildNodeEntries()) {
                                            if (cne.getId().equals(nodeState.getId())) {
                                                // node has been renamed,
                                                // add parent to dependencies
                                                dependentIDs.add(newParentId);
                                            }
                                        }
                                    } catch (ItemStateException ise) {
                                        // should never get here
                                        log.warn("failed to retrieve transient state: " + newParentId, ise);
                                    }
                                }
                            }
                        }
                    }
                }

                // removed child node entries
                for (ChildNodeEntry cne : nodeState.getRemovedChildNodeEntries()) {
                    dependentIDs.add(cne.getId());
                }
                // added child node entries
                for (ChildNodeEntry cne : nodeState.getAddedChildNodeEntries()) {
                    dependentIDs.add(cne.getId());
                }

                // now walk through dependencies and check whether they
                // are within the scope of this save operation
                for (NodeId id : dependentIDs) {
                    if (!affected.containsKey(id)) {
                        // JCR-1359 workaround: check whether unresolved
                        // dependencies originate from 'this' session;
                        // otherwise ignore them
                        if (stateMgr.hasTransientItemState(id)
                                || stateMgr.hasTransientItemStateInAttic(id)) {
                            // need to save dependency as well
                            String msg =
                                context.getItemManager().safeGetJCRPath(id)
                                + " needs to be saved as well.";
                            log.debug(msg);
                            throw new ConstraintViolationException(msg);
                        }
                    }
                }
            }
        }

        // validate access and node type constraints
        // (this will also validate child removals)
        validateTransientItems(context, dirty, removed);

        // start the update operation
        try {
            stateMgr.edit();
        } catch (IllegalStateException e) {
            throw new RepositoryException("Unable to start edit operation", e);
        }

        boolean succeeded = false;
        try {
            // process transient items marked as 'removed'
            removeTransientItems(context.getItemStateManager(), removed);

            // process transient items that have change in mixins
            processShareableNodes(
                    context.getRepositoryContext().getNodeTypeRegistry(),
                    dirty);

            // initialize version histories for new nodes (might generate new transient state)
            if (initVersionHistories(context, dirty)) {
                // re-build the list of transient states because the previous call
                // generated new transient state
                dirty = getTransientStates(context.getItemStateManager());
            }

            // process 'new' or 'modified' transient states
            persistTransientItems(context.getItemManager(), dirty);

            // dispose the transient states marked 'new' or 'modified'
            // at this point item state data is pushed down one level,
            // node instances are disconnected from the transient
            // item state and connected to the 'overlayed' item state.
            // transient item states must be removed now. otherwise
            // the session item state provider will return an orphaned
            // item state which is not referenced by any node instance.
            for (ItemState transientState : dirty) {
                // dispose the transient state, it is no longer used
                stateMgr.disposeTransientItemState(transientState);
            }

            // end update operation
            stateMgr.update();
            // update operation succeeded
            succeeded = true;
        } catch (StaleItemStateException e) {
            throw new InvalidItemStateException(
                    "Unable to update a stale item: " + this, e);
        } catch (ItemStateException e) {
            throw new RepositoryException(
                    "Unable to update item: " + this, e);
        } finally {
            if (!succeeded) {
                // update operation failed, cancel all modifications
                stateMgr.cancel();

                // JCR-288: if an exception has been thrown during
                // update() the transient changes have already been
                // applied by persistTransientItems() and we need to
                // restore transient state, i.e. undo the effect of
                // persistTransientItems()
                restoreTransientItems(context, dirty);
            }
        }

        // now it is safe to dispose the transient states:
        // dispose the transient states marked 'removed'.
        // item states in attic are removed after store, because
        // the observation mechanism needs to build paths of removed
        // items in store().
        for (ItemState transientState : removed) {
            // dispose the transient state, it is no longer used
            stateMgr.disposeTransientItemStateInAttic(transientState);
        }

        return this;
    }
View Full Code Here


     * Create the session item state manager.
     *
     * @return session item state manager
     */
    protected SessionItemStateManager createSessionItemStateManager() {
        SessionItemStateManager mgr = new SessionItemStateManager(
                context.getRootNodeId(),
                context.getWorkspace().getItemStateManager());
        context.getWorkspace().getItemStateManager().addListener(mgr);
        return mgr;
    }
View Full Code Here

            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) {
                // since identifier of assigned definition is not stored anymore
                // with item state (see JCR-2170), correct definition cannot be
                // determined for items which have been removed due to removal
                // 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";
View Full Code Here

     * walk through list of transient states and re-apply transient changes
     */
    private void restoreTransientItems(
            SessionContext context, Iterable<ItemState> items) {
        ItemManager itemMgr = context.getItemManager();
        SessionItemStateManager stateMgr = context.getItemStateManager();

        for (ItemState itemState : items) {
            ItemId id = itemState.getId();
            ItemImpl item;

            try {
                if (stateMgr.isItemStateInAttic(id)) {
                    // If an item has been removed and then again created, the
                    // item is lost after persistTransientItems() and the
                    // TransientItemStateManager will bark because of a deleted
                    // state in its attic. We therefore have to forge a new item
                    // instance ourself.
View Full Code Here

     * Create the session item state manager.
     *
     * @return session item state manager
     */
    protected SessionItemStateManager createSessionItemStateManager() {
        SessionItemStateManager mgr = new SessionItemStateManager(
                context.getRootNodeId(),
                context.getWorkspace().getItemStateManager());
        context.getWorkspace().getItemStateManager().addListener(mgr);
        return mgr;
    }
View Full Code Here

     * Create the session item state manager.
     *
     * @return session item state manager
     */
    protected SessionItemStateManager createSessionItemStateManager(LocalItemStateManager manager) {
        return new SessionItemStateManager(rep.getRootNodeId(),
                manager, getNamespaceResolver());
    }
View Full Code Here

     * Create the session item state manager.
     *
     * @return session item state manager
     */
    protected SessionItemStateManager createSessionItemStateManager(LocalItemStateManager manager) {
        return new SessionItemStateManager(
                rep.getRootNodeId(), manager, rep.getNodeTypeRegistry());
    }
View Full Code Here

                    /**
                     * the state is a transient wrapper for the underlying
                     * persistent state, therefore restore the persistent state
                     * and resurrect this item instance if necessary
                     */
                    SessionItemStateManager stateMgr = session.getItemStateManager();
                    stateMgr.disconnectTransientItemState(discarded);
                    data.setState(persistentState);
                    return;

                    /**
                     * persistent item that has been transiently modified or
View Full Code Here

                case ItemState.STATUS_EXISTING_MODIFIED:
                    ItemState persistentState = discarded.getOverlayedState();
                    // the state is a transient wrapper for the underlying
                    // persistent state, therefore restore the persistent state
                    // and resurrect this item instance if necessary
                    SessionItemStateManager stateMgr =
                        sessionContext.getItemStateManager();
                    stateMgr.disconnectTransientItemState(discarded);
                    data.setState(persistentState);
                    return;

                    /**
                     * persistent item that has been transiently modified or
View Full Code Here

    public ItemSaveOperation(ItemState state) {
        this.state = state;
    }

    public Object perform(SessionContext context) throws RepositoryException {
        SessionItemStateManager stateMgr = context.getItemStateManager();

        /**
         * build list of transient (i.e. new & modified) states that
         * should be persisted
         */
        Collection<ItemState> dirty;
        try {
            dirty = getTransientStates(context.getItemStateManager());
        } catch (ConcurrentModificationException e) {
            String msg = "Concurrent modification; session is closed";
            log.error(msg, e);
            context.getSessionImpl().logout();
            throw e;
        }
        if (dirty.size() == 0) {
            // no transient items, nothing to do here
            return this;
        }

        /**
         * build list of transient descendants in the attic
         * (i.e. those marked as 'removed')
         */
        Collection<ItemState> removed =
            getRemovedStates(context.getItemStateManager());

        // All affected item states. The keys are used to look up whether
        // an item is affected, and the values are iterated through below
        Map<ItemId, ItemState> affected =
            new HashMap<ItemId, ItemState>(dirty.size() + removed.size());
        for (ItemState state : dirty) {
            affected.put(state.getId(), state);
        }
        for (ItemState state : removed) {
            affected.put(state.getId(), state);
        }

        /**
         * make sure that this save operation is totally 'self-contained'
         * and independent; items within the scope of this save operation
         * must not have 'external' dependencies;
         * (e.g. moving a node requires that the target node including both
         * old and new parents are saved)
         */
        for (ItemState transientState : affected.values()) {
            if (transientState.isNode()) {
                NodeState nodeState = (NodeState) transientState;
                Set<NodeId> dependentIDs = new HashSet<NodeId>();
                if (nodeState.hasOverlayedState()) {
                    NodeState overlayedState =
                            (NodeState) nodeState.getOverlayedState();
                    NodeId oldParentId = overlayedState.getParentId();
                    NodeId newParentId = nodeState.getParentId();
                    if (oldParentId != null) {
                        if (newParentId == null) {
                            // node has been removed, add old parents
                            // to dependencies
                            if (overlayedState.isShareable()) {
                                dependentIDs.addAll(overlayedState.getSharedSet());
                            } else {
                                dependentIDs.add(oldParentId);
                            }
                        } else {
                            if (!oldParentId.equals(newParentId)) {
                                // node has been moved to a new location,
                                // add old and new parent to dependencies
                                dependentIDs.add(oldParentId);
                                dependentIDs.add(newParentId);
                            } else {
                                // parent id hasn't changed, check whether
                                // the node has been renamed (JCR-1034)
                                if (!affected.containsKey(newParentId)
                                        && stateMgr.hasTransientItemState(newParentId)) {
                                    try {
                                        NodeState parent = (NodeState) stateMgr.getTransientItemState(newParentId);
                                        // check parent's renamed child node entries
                                        for (ChildNodeEntry cne : parent.getRenamedChildNodeEntries()) {
                                            if (cne.getId().equals(nodeState.getId())) {
                                                // node has been renamed,
                                                // add parent to dependencies
                                                dependentIDs.add(newParentId);
                                            }
                                        }
                                    } catch (ItemStateException ise) {
                                        // should never get here
                                        log.warn("failed to retrieve transient state: " + newParentId, ise);
                                    }
                                }
                            }
                        }
                    }
                }

                // removed child node entries
                for (ChildNodeEntry cne : nodeState.getRemovedChildNodeEntries()) {
                    dependentIDs.add(cne.getId());
                }
                // added child node entries
                for (ChildNodeEntry cne : nodeState.getAddedChildNodeEntries()) {
                    dependentIDs.add(cne.getId());
                }

                // now walk through dependencies and check whether they
                // are within the scope of this save operation
                for (NodeId id : dependentIDs) {
                    if (!affected.containsKey(id)) {
                        // JCR-1359 workaround: check whether unresolved
                        // dependencies originate from 'this' session;
                        // otherwise ignore them
                        if (stateMgr.hasTransientItemState(id)
                                || stateMgr.hasTransientItemStateInAttic(id)) {
                            // need to save dependency as well
                            String msg =
                                context.getItemManager().safeGetJCRPath(id)
                                + " needs to be saved as well.";
                            log.debug(msg);
                            throw new ConstraintViolationException(msg);
                        }
                    }
                }
            }
        }

        // validate access and node type constraints
        // (this will also validate child removals)
        validateTransientItems(context, dirty, removed);

        // start the update operation
        try {
            stateMgr.edit();
        } catch (IllegalStateException e) {
            throw new RepositoryException("Unable to start edit operation", e);
        }

        boolean succeeded = false;
        try {
            // process transient items marked as 'removed'
            removeTransientItems(context.getItemStateManager(), removed);

            // process transient items that have change in mixins
            processShareableNodes(
                    context.getRepositoryContext().getNodeTypeRegistry(),
                    dirty);

            // initialize version histories for new nodes (might generate new transient state)
            if (initVersionHistories(context, dirty)) {
                // re-build the list of transient states because the previous call
                // generated new transient state
                dirty = getTransientStates(context.getItemStateManager());
            }

            // process 'new' or 'modified' transient states
            persistTransientItems(context.getItemManager(), dirty);

            // dispose the transient states marked 'new' or 'modified'
            // at this point item state data is pushed down one level,
            // node instances are disconnected from the transient
            // item state and connected to the 'overlayed' item state.
            // transient item states must be removed now. otherwise
            // the session item state provider will return an orphaned
            // item state which is not referenced by any node instance.
            for (ItemState transientState : dirty) {
                // dispose the transient state, it is no longer used
                stateMgr.disposeTransientItemState(transientState);
            }

            // end update operation
            stateMgr.update();
            // update operation succeeded
            succeeded = true;
        } catch (StaleItemStateException e) {
            throw new InvalidItemStateException(e.getMessage());
        } catch (ItemStateException e) {
            throw new RepositoryException(
                    "Unable to update item: " + this, e);
        } finally {
            if (!succeeded) {
                // update operation failed, cancel all modifications
                stateMgr.cancel();

                // JCR-288: if an exception has been thrown during
                // update() the transient changes have already been
                // applied by persistTransientItems() and we need to
                // restore transient state, i.e. undo the effect of
                // persistTransientItems()
                restoreTransientItems(context, dirty);
            }
        }

        // now it is safe to dispose the transient states:
        // dispose the transient states marked 'removed'.
        // item states in attic are removed after store, because
        // the observation mechanism needs to build paths of removed
        // items in store().
        for (ItemState transientState : removed) {
            // dispose the transient state, it is no longer used
            stateMgr.disposeTransientItemStateInAttic(transientState);
        }

        return this;
    }
View Full Code Here

TOP

Related Classes of org.apache.jackrabbit.core.state.SessionItemStateManager

Copyright © 2018 www.massapicom. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.