shareditemstatemanager.java
来自「jsr170接口的java实现。是个apache的开源项目。」· Java 代码 · 共 1,450 行 · 第 1/4 页
JAVA
1,450 行
/** * Checks if this item state manager has the given item state without * considering the virtual item state managers. */ private boolean hasNonVirtualItemState(ItemId id) { if (cache.isCached(id)) { return true; } try { if (id.denotesNode()) { return persistMgr.exists((NodeId) id); } else { return persistMgr.exists((PropertyId) id); } } catch (ItemStateException ise) { return false; } } /** * Create a new item state instance * * @param other other state associated with new instance * @return new node state instance */ private ItemState createInstance(ItemState other) { if (other.isNode()) { NodeState ns = (NodeState) other; return createInstance(ns.getNodeId(), ns.getNodeTypeName(), ns.getParentId()); } else { PropertyState ps = (PropertyState) other; return createInstance(ps.getName(), ps.getParentId()); } } /** * Create a new property state instance * * @param propName property name * @param parentId parent Id * @return new property state instance */ private PropertyState createInstance(QName propName, NodeId parentId) { PropertyState state = persistMgr.createNew(new PropertyId(parentId, propName)); state.setStatus(ItemState.STATUS_NEW); state.setContainer(this); return state; } /** * Load item state from persistent storage. * * @param id item id * @return item state */ private ItemState loadItemState(ItemId id) throws NoSuchItemStateException, ItemStateException { ItemState state; if (id.denotesNode()) { state = persistMgr.load((NodeId) id); } else { state = persistMgr.load((PropertyId) id); } return state; } /** * Determines whether the specified node is <i>referenceable</i>, i.e. * whether the mixin type <code>mix:referenceable</code> is either * directly assigned or indirectly inherited. * * @param state node state to check * @return true if the specified node is <i>referenceable</i>, false otherwise. * @throws ItemStateException if an error occurs */ private boolean isReferenceable(NodeState state) throws ItemStateException { // shortcut: check some wellknown built-in types first QName primary = state.getNodeTypeName(); Set mixins = state.getMixinTypeNames(); if (mixins.contains(QName.MIX_REFERENCEABLE) || mixins.contains(QName.MIX_VERSIONABLE) || primary.equals(QName.NT_RESOURCE)) { return true; } // build effective node type QName[] types = new QName[mixins.size() + 1]; mixins.toArray(types); // primary type types[types.length - 1] = primary; try { return ntReg.getEffectiveNodeType(types).includesNodeType(QName.MIX_REFERENCEABLE); } catch (NodeTypeConflictException ntce) { String msg = "internal error: failed to build effective node type for node " + state.getNodeId(); log.debug(msg); throw new ItemStateException(msg, ntce); } catch (NoSuchNodeTypeException nsnte) { String msg = "internal error: failed to build effective node type for node " + state.getNodeId(); log.debug(msg); throw new ItemStateException(msg, nsnte); } } /** * Updates the target node references collections based on the modifications * in the change log (i.e. added/removed/modified <code>REFERENCE</code> * properties). * <p/> * <b>Important node:</b> For consistency reasons this method must only be * called <i>once</i> per change log and the change log should not be modified * anymore afterwards. * * @param changes change log * @param virtualProvider virtual provider that may already contain a * node references object * @throws ItemStateException if an error occurs */ protected void updateReferences(ChangeLog changes, VirtualItemStateProvider virtualProvider) throws ItemStateException { // process added REFERENCE properties for (Iterator iter = changes.addedStates(); iter.hasNext();) { ItemState state = (ItemState) iter.next(); if (!state.isNode()) { PropertyState prop = (PropertyState) state; if (prop.getType() == PropertyType.REFERENCE) { // this is a new REFERENCE property: // add the new 'reference' InternalValue[] vals = prop.getValues(); for (int i = 0; vals != null && i < vals.length; i++) { NodeReferencesId refsId = new NodeReferencesId( (UUID) vals[i].internalValue()); if (virtualProvider != null && virtualProvider.hasNodeReferences(refsId)) { continue; } NodeReferences refs = getOrCreateNodeReferences(refsId, changes); // add reference refs.addReference(prop.getPropertyId()); // update change log changes.modified(refs); } } } } // process modified REFERENCE properties for (Iterator iter = changes.modifiedStates(); iter.hasNext();) { ItemState state = (ItemState) iter.next(); if (!state.isNode()) { PropertyState newProp = (PropertyState) state; PropertyState oldProp = (PropertyState) getItemState(state.getId()); // check old type if (oldProp.getType() == PropertyType.REFERENCE) { // this is a modified REFERENCE property: // remove the old 'reference' from the target InternalValue[] vals = oldProp.getValues(); for (int i = 0; vals != null && i < vals.length; i++) { NodeReferencesId refsId = new NodeReferencesId( (UUID) vals[i].internalValue()); if (virtualProvider != null && virtualProvider.hasNodeReferences(refsId)) { continue; } // either get node references from change log or load from // persistence manager NodeReferences refs = changes.get(refsId); if (refs == null) { refs = getNodeReferences(refsId); } // remove reference refs.removeReference(oldProp.getPropertyId()); // update change log changes.modified(refs); } } // check new type if (newProp.getType() == PropertyType.REFERENCE) { // this is a modified REFERENCE property: // add the new 'reference' to the target InternalValue[] vals = newProp.getValues(); for (int i = 0; vals != null && i < vals.length; i++) { NodeReferencesId refsId = new NodeReferencesId( (UUID) vals[i].internalValue()); if (virtualProvider != null && virtualProvider.hasNodeReferences(refsId)) { continue; } NodeReferences refs = getOrCreateNodeReferences(refsId, changes); // add reference refs.addReference(newProp.getPropertyId()); // update change log changes.modified(refs); } } } } // process removed REFERENCE properties for (Iterator iter = changes.deletedStates(); iter.hasNext();) { ItemState state = (ItemState) iter.next(); if (!state.isNode()) { PropertyState prop = (PropertyState) state; if (prop.getType() == PropertyType.REFERENCE) { // this is a removed REFERENCE property: // remove the 'reference' from the target InternalValue[] vals = prop.getValues(); for (int i = 0; vals != null && i < vals.length; i++) { NodeReferencesId refsId = new NodeReferencesId( (UUID) vals[i].internalValue()); if (virtualProvider != null && virtualProvider.hasNodeReferences(refsId)) { continue; } // either get node references from change log or // load from persistence manager NodeReferences refs = changes.get(refsId); if (refs == null) { refs = getNodeReferences(refsId); } // remove reference refs.removeReference(prop.getPropertyId()); // update change log changes.modified(refs); } } } } } /** * Returns a node references object using the following rules:<p/> * <ul> * <li>1. return a modified instance from the change log (if one exists)</li> * <li>2. return an existing instance from <i>this</i> item state manager * (if one exists)</li> * <li>3. create and return a new instance</li> * </ul> * * @param refsId node references id * @param changes change log * @return a node references object * @throws ItemStateException if an error occurs */ private NodeReferences getOrCreateNodeReferences(NodeReferencesId refsId, ChangeLog changes) throws ItemStateException { // check change log NodeReferences refs = changes.get(refsId); if (refs == null) { // not yet in change log: // either load existing or create new if (hasNodeReferences(refsId)) { refs = getNodeReferences(refsId); } else { refs = new NodeReferences(refsId); } } return refs; } /** * Verifies that * <ul> * <li>no referenceable nodes are deleted if they are still being referenced</li> * <li>targets of modified node references exist</li> * </ul> * * @param changes change log * @throws ReferentialIntegrityException if a new or modified REFERENCE * property refers to a non-existent * target or if a removed node is still * being referenced * @throws ItemStateException if another error occurs */ protected void checkReferentialIntegrity(ChangeLog changes) throws ReferentialIntegrityException, ItemStateException { // check whether removed referenceable nodes are still being referenced for (Iterator iter = changes.deletedStates(); iter.hasNext();) { ItemState state = (ItemState) iter.next(); if (state.isNode()) { NodeState node = (NodeState) state; if (isReferenceable(node)) { NodeReferencesId refsId = new NodeReferencesId(node.getNodeId()); // either get node references from change log or // load from persistence manager NodeReferences refs = changes.get(refsId); if (refs == null) { if (!hasNodeReferences(refsId)) { continue; } refs = getNodeReferences(refsId); } // in some versioning operations (such as restore) a node // may actually be deleted and then again added with the // same UUID, i.e. the node is still referenceable. if (refs.hasReferences() && !changes.has(node.getNodeId())) { String msg = node.getNodeId() + ": the node cannot be removed because it is still being referenced."; log.debug(msg); throw new ReferentialIntegrityException(msg); } } } } // check whether targets of modified node references exist for (Iterator iter = changes.modifiedRefs(); iter.hasNext();) { NodeReferences refs = (NodeReferences) iter.next(); NodeId id = refs.getTargetId(); // no need to check existence of target if there are no references if (refs.hasReferences()) { // please note: // virtual providers are indirectly checked via 'hasItemState()' if (!changes.has(id) && !hasItemState(id)) { String msg = "Target node " + id + " of REFERENCE property does not exist"; log.debug(msg); throw new ReferentialIntegrityException(msg); } } } } /** * Acquires the read lock on this item state manager. * * @throws ItemStateException if the read lock cannot be acquired. */ private void acquireReadLock() throws ItemStateException { try { rwLock.readLock().acquire(); } catch (InterruptedException e) { throw new ItemStateException("Interrupted while acquiring read lock"); } } /** * Acquires the write lock on this item state manager. * * @throws ItemStateException if the write lock cannot be acquired. */ private void acquireWriteLock() throws ItemStateException { try { rwLock.writeLock().acquire(); } catch (InterruptedException e) { throw new ItemStateException("Interrupted while acquiring write lock"); } }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?