Search in sources :

Example 1 with Name

use of org.apache.jackrabbit.spi.Name 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 Name

use of org.apache.jackrabbit.spi.Name in project jackrabbit by apache.

the class RepositoryChecker method checkVersionHistory.

private void checkVersionHistory(NodeState node) {
    String message = null;
    NodeId nid = node.getNodeId();
    boolean isVersioned = node.hasPropertyName(JCR_VERSIONHISTORY);
    NodeId vhid = null;
    try {
        String type = isVersioned ? "in-use" : "candidate";
        log.debug("Checking " + type + " version history of node {}", nid);
        String intro = "Removing references to an inconsistent " + type + " version history of node " + nid;
        message = intro + " (getting the VersionInfo)";
        VersionHistoryInfo vhi = versionManager.getVersionHistoryInfoForNode(node);
        if (vhi != null) {
            // get the version history's node ID as early as possible
            // so we can attempt a fixup even when the next call fails
            vhid = vhi.getVersionHistoryId();
        }
        message = intro + " (getting the InternalVersionHistory)";
        InternalVersionHistory vh = null;
        try {
            vh = versionManager.getVersionHistoryOfNode(nid);
        } catch (ItemNotFoundException ex) {
            // it's ok if we get here if the node didn't claim to be versioned
            if (isVersioned) {
                throw ex;
            }
        }
        if (vh == null) {
            if (isVersioned) {
                message = intro + "getVersionHistoryOfNode returned null";
                throw new InconsistentVersioningState(message);
            }
        } else {
            vhid = vh.getId();
            // additional checks, see JCR-3101
            message = intro + " (getting the version names failed)";
            Name[] versionNames = vh.getVersionNames();
            boolean seenRoot = false;
            for (Name versionName : versionNames) {
                seenRoot |= JCR_ROOTVERSION.equals(versionName);
                log.debug("Checking version history of node {}, version {}", nid, versionName);
                message = intro + " (getting version " + versionName + "  failed)";
                InternalVersion v = vh.getVersion(versionName);
                message = intro + "(frozen node of root version " + v.getId() + " missing)";
                if (null == v.getFrozenNode()) {
                    throw new InconsistentVersioningState(message);
                }
            }
            if (!seenRoot) {
                message = intro + " (root version is missing)";
                throw new InconsistentVersioningState(message);
            }
        }
    } catch (InconsistentVersioningState e) {
        log.info(message, e);
        NodeId nvhid = e.getVersionHistoryNodeId();
        if (nvhid != null) {
            if (vhid != null && !nvhid.equals(vhid)) {
                log.error("vhrid returned with InconsistentVersioningState does not match the id we already had: " + vhid + " vs " + nvhid);
            }
            vhid = nvhid;
        }
        removeVersionHistoryReferences(node, vhid);
    } catch (Exception e) {
        log.info(message, e);
        removeVersionHistoryReferences(node, vhid);
    }
}
Also used : VersionHistoryInfo(org.apache.jackrabbit.core.version.VersionHistoryInfo) InconsistentVersioningState(org.apache.jackrabbit.core.version.InconsistentVersioningState) NodeId(org.apache.jackrabbit.core.id.NodeId) InternalVersionHistory(org.apache.jackrabbit.core.version.InternalVersionHistory) RepositoryException(javax.jcr.RepositoryException) ItemStateException(org.apache.jackrabbit.core.state.ItemStateException) ItemNotFoundException(javax.jcr.ItemNotFoundException) ItemNotFoundException(javax.jcr.ItemNotFoundException) Name(org.apache.jackrabbit.spi.Name) InternalVersion(org.apache.jackrabbit.core.version.InternalVersion)

Example 3 with Name

use of org.apache.jackrabbit.spi.Name in project jackrabbit by apache.

the class BundleReader method readBundleOld.

private void readBundleOld(NodePropBundle bundle) throws IOException {
    // read primary type...special handling
    int a = in.readUnsignedByte();
    int b = in.readUnsignedByte();
    int c = in.readUnsignedByte();
    String uri = binding.nsIndex.indexToString(a << 16 | b << 8 | c);
    String local = binding.nameIndex.indexToString(in.readInt());
    bundle.setNodeTypeName(NameFactoryImpl.getInstance().create(uri, local));
    // parentUUID
    bundle.setParentId(readNodeId());
    // definitionId
    in.readUTF();
    // mixin types
    Name name = readIndexedQName();
    if (name != null) {
        Set<Name> mixinTypeNames = new HashSet<Name>();
        do {
            mixinTypeNames.add(name);
            name = readIndexedQName();
        } while (name != null);
        bundle.setMixinTypeNames(mixinTypeNames);
    } else {
        bundle.setMixinTypeNames(Collections.<Name>emptySet());
    }
    // properties
    name = readIndexedQName();
    while (name != null) {
        PropertyId pId = new PropertyId(bundle.getId(), name);
        NodePropBundle.PropertyEntry pState = readPropertyEntry(pId);
        // skip redundant primaryType, mixinTypes and uuid properties
        if (!name.equals(NameConstants.JCR_PRIMARYTYPE) && !name.equals(NameConstants.JCR_UUID)) {
            bundle.addProperty(pState);
        }
        name = readIndexedQName();
    }
    // set referenceable flag
    bundle.setReferenceable(in.readBoolean());
    // child nodes (list of uuid/name pairs)
    NodeId childId = readNodeId();
    while (childId != null) {
        bundle.addChildNodeEntry(readQName(), childId);
        childId = readNodeId();
    }
    // read modcount, since version 1.0
    if (version >= BundleBinding.VERSION_1) {
        bundle.setModCount(in.readShort());
    }
    // read shared set, since version 2.0
    if (version >= BundleBinding.VERSION_2) {
        // shared set (list of parent uuids)
        NodeId parentId = readNodeId();
        if (parentId != null) {
            Set<NodeId> shared = new HashSet<NodeId>();
            do {
                shared.add(parentId);
                parentId = readNodeId();
            } while (parentId != null);
            bundle.setSharedSet(shared);
        } else {
            bundle.setSharedSet(Collections.<NodeId>emptySet());
        }
    } else {
        bundle.setSharedSet(Collections.<NodeId>emptySet());
    }
}
Also used : NodeId(org.apache.jackrabbit.core.id.NodeId) Name(org.apache.jackrabbit.spi.Name) HashSet(java.util.HashSet) PropertyId(org.apache.jackrabbit.core.id.PropertyId)

Example 4 with Name

use of org.apache.jackrabbit.spi.Name in project jackrabbit by apache.

the class BundleWriter method writeBundle.

/**
     * Serializes a <code>NodePropBundle</code> to a data output stream
     *
     * @param bundle the bundle to serialize
     * @throws IOException if an I/O error occurs.
     */
public void writeBundle(NodePropBundle bundle) throws IOException {
    long size = out.size();
    // primaryType
    writeName(bundle.getNodeTypeName());
    // parentUUID
    NodeId parentId = bundle.getParentId();
    if (parentId == null) {
        parentId = BundleBinding.NULL_PARENT_ID;
    }
    writeNodeId(parentId);
    // write mod count
    writeVarInt(bundle.getModCount());
    Collection<Name> mixins = bundle.getMixinTypeNames();
    Collection<PropertyEntry> properties = bundle.getPropertyEntries();
    Collection<ChildNodeEntry> nodes = bundle.getChildNodeEntries();
    Collection<NodeId> shared = bundle.getSharedSet();
    int mn = mixins.size();
    int pn = properties.size();
    int nn = nodes.size();
    int sn = shared.size();
    int referenceable = 0;
    if (bundle.isReferenceable()) {
        referenceable = 1;
    }
    out.writeByte(Math.min(mn, 1) << 7 | Math.min(pn, 7) << 4 | Math.min(nn, 3) << 2 | Math.min(sn, 1) << 1 | referenceable);
    // mixin types
    writeVarInt(mn, 1);
    for (Name name : mixins) {
        writeName(name);
    }
    // properties
    writeVarInt(pn, 7);
    for (PropertyEntry property : properties) {
        writeState(property);
    }
    // child nodes (list of name/uuid pairs)
    writeVarInt(nn, 3);
    for (ChildNodeEntry child : nodes) {
        // name
        writeName(child.getName());
        // uuid
        writeNodeId(child.getId());
    }
    // write shared set
    writeVarInt(sn, 1);
    for (NodeId nodeId : shared) {
        writeNodeId(nodeId);
    }
    // set size of bundle
    bundle.setSize(out.size() - size);
}
Also used : PropertyEntry(org.apache.jackrabbit.core.persistence.util.NodePropBundle.PropertyEntry) ChildNodeEntry(org.apache.jackrabbit.core.persistence.util.NodePropBundle.ChildNodeEntry) NodeId(org.apache.jackrabbit.core.id.NodeId) Name(org.apache.jackrabbit.spi.Name)

Example 5 with Name

use of org.apache.jackrabbit.spi.Name in project jackrabbit by apache.

the class Serializer method deserialize.

/**
     * Deserializes a <code>NodeState</code> object from the given binary
     * <code>stream</code>.
     *
     * @param state  <code>state</code> to deserialize
     * @param stream the stream where the <code>state</code> should be deserialized from
     * @throws Exception if an error occurs during the deserialization
     * @see #serialize(NodeState, OutputStream)
     */
public static void deserialize(NodeState state, InputStream stream) throws Exception {
    DataInputStream in = new DataInputStream(stream);
    // primaryType
    String s = in.readUTF();
    state.setNodeTypeName(NameFactoryImpl.getInstance().create(s));
    // parentUUID (may be null)
    byte[] uuidBytes = new byte[NodeId.UUID_BYTE_LENGTH];
    in.readFully(uuidBytes);
    if (!Arrays.equals(uuidBytes, NULL_UUID_PLACEHOLDER_BYTES)) {
        state.setParentId(new NodeId(uuidBytes));
    }
    // definitionId
    in.readUTF();
    // mixin types
    // count
    int count = in.readInt();
    Set<Name> set = new HashSet<Name>(count);
    for (int i = 0; i < count; i++) {
        set.add(NameFactoryImpl.getInstance().create(in.readUTF()));
    }
    if (set.size() > 0) {
        state.setMixinTypeNames(set);
    }
    // modCount
    short modCount = in.readShort();
    state.setModCount(modCount);
    // properties (names)
    // count
    count = in.readInt();
    for (int i = 0; i < count; i++) {
        // name
        state.addPropertyName(NameFactoryImpl.getInstance().create(in.readUTF()));
    }
    // child nodes (list of name/uuid pairs)
    // count
    count = in.readInt();
    for (int i = 0; i < count; i++) {
        // name
        Name name = NameFactoryImpl.getInstance().create(in.readUTF());
        // uuid
        in.readFully(uuidBytes);
        state.addChildNodeEntry(name, new NodeId(uuidBytes));
    }
}
Also used : NodeId(org.apache.jackrabbit.core.id.NodeId) DataInputStream(java.io.DataInputStream) HashSet(java.util.HashSet) Name(org.apache.jackrabbit.spi.Name)

Aggregations

Name (org.apache.jackrabbit.spi.Name)382 RepositoryException (javax.jcr.RepositoryException)101 ArrayList (java.util.ArrayList)57 QValue (org.apache.jackrabbit.spi.QValue)42 NameException (org.apache.jackrabbit.spi.commons.conversion.NameException)39 HashSet (java.util.HashSet)38 Path (org.apache.jackrabbit.spi.Path)38 NodeId (org.apache.jackrabbit.core.id.NodeId)37 QPropertyDefinition (org.apache.jackrabbit.spi.QPropertyDefinition)33 ConstraintViolationException (javax.jcr.nodetype.ConstraintViolationException)32 NodeId (org.apache.jackrabbit.spi.NodeId)32 PropertyId (org.apache.jackrabbit.core.id.PropertyId)29 HashMap (java.util.HashMap)28 NamespaceException (javax.jcr.NamespaceException)28 NodeState (org.apache.jackrabbit.core.state.NodeState)28 Value (javax.jcr.Value)25 QNodeDefinition (org.apache.jackrabbit.spi.QNodeDefinition)25 InternalValue (org.apache.jackrabbit.core.value.InternalValue)23 ChildNodeEntry (org.apache.jackrabbit.core.state.ChildNodeEntry)22 PropertyState (org.apache.jackrabbit.core.state.PropertyState)22