shareditemstatemanager.java
来自「jsr170接口的java实现。是个apache的开源项目。」· Java 代码 · 共 1,450 行 · 第 1/4 页
JAVA
1,450 行
/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package org.apache.jackrabbit.core.state;import EDU.oswego.cs.dl.util.concurrent.ReadWriteLock;import EDU.oswego.cs.dl.util.concurrent.ReentrantWriterPreferenceReadWriteLock;import org.apache.jackrabbit.core.ItemId;import org.apache.jackrabbit.core.NodeId;import org.apache.jackrabbit.core.PropertyId;import org.apache.jackrabbit.core.RepositoryImpl;import org.apache.jackrabbit.core.cluster.UpdateEventChannel;import org.apache.jackrabbit.core.persistence.PersistenceManager;import org.apache.jackrabbit.core.persistence.bundle.CachingPersistenceManager;import org.apache.jackrabbit.core.version.XAVersionManager;import org.apache.jackrabbit.core.nodetype.EffectiveNodeType;import org.apache.jackrabbit.core.nodetype.NodeDefId;import org.apache.jackrabbit.core.nodetype.NodeTypeConflictException;import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;import org.apache.jackrabbit.core.nodetype.PropDef;import org.apache.jackrabbit.core.observation.EventStateCollection;import org.apache.jackrabbit.core.observation.EventStateCollectionFactory;import org.apache.jackrabbit.core.util.Dumpable;import org.apache.jackrabbit.core.value.InternalValue;import org.apache.jackrabbit.core.virtual.VirtualItemStateProvider;import org.apache.jackrabbit.name.QName;import org.apache.jackrabbit.uuid.UUID;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import javax.jcr.PropertyType;import javax.jcr.ReferentialIntegrityException;import javax.jcr.RepositoryException;import javax.jcr.nodetype.ConstraintViolationException;import javax.jcr.nodetype.NoSuchNodeTypeException;import java.io.PrintStream;import java.util.Iterator;import java.util.LinkedList;import java.util.List;import java.util.Set;import java.util.HashMap;/** * Shared <code>ItemStateManager</code> (SISM). Caches objects returned from a * <code>PersistenceManager</code>. Objects returned by this item state * manager are shared among all sessions. * <p/> * A shared item state manager operates on a <code>PersistenceManager</code> * (PM) that is used to load and store the item states. Additionally, a SISM can * have <code>VirtualItemStateProvider</code>s (VISP) that are used to provide * additional, non-persistent, read-only states. Examples of VISP are the * content representation of the NodeTypes (/jcr:system/jcr:nodeTypes) and the * version store (/jcr:system/jcr:versionStore). those 2 VISP are added to the * SISM during initialization of a workspace. i.e. they are 'mounted' to all * workspaces. we assume, that VISP cannot be added dynamically, neither during * runtime nor by configuration. * <p/> * The states from the VISP are readonly. by the exception for node references. * remember that the referrers are stored in a {@link NodeReferences} state, * having the ID of the target state. * <br/> * there are 5 types of referential relations to be distinguished: * <ol> * <li> normal --> normal (references from 'normal' states to 'normal' states) * this is the normal case and will be handled by the SISM. * * <li> normal --> virtual (references from 'normal' states to 'virtual' states) * those references should be handled by the VISP rather by the SISM. * * <li> virtual --> normal (references from 'virtual' states to 'normal' states) * such references are not supported. eg. references of versioned nodes do * not impose any constraints on the referenced nodes. * * <li> virtual --> virtual (references from 'virtual' states to 'virtual' * states of the same VISP). * intra-virtual references are handled by the item state manager of the VISP. * * <li> virtual --> virtual' (references from 'virtual' states to 'virtual' * states of different VISP). * those do currently not occurr and are therfor not supported. * </ol> * <p/> * if VISP are not dynamic, there is not risk that NV-type references can dangle * (since a VISP cannot be 'unmounted', leaving eventual references dangling). * although multi-workspace-referrers are not explicitelt supported, the * architecture of <code>NodeReferences</code> support multiple referrers with * the same PropertyId. So the number of references can be tracked (an example * of multi-workspace-refferres is a version referenced by the jcr:baseVersion * of several (corresponding) nodes in multiple workspaces). * <br/> * As mentioned, VN-type references should not impose any constraints on the * referrers (e.g. a normal node referenced by a versioned reference property). * In case of the version store, the VN-type references are not stored at * all, but reinforced as NN-type references in the normal states in case of a * checkout operation. * <br/> * VV-type references should be handled by the respective VISP. they look as * NN-type references in the scope if the VISP anyway...so no special treatment * should be neccessairy. * <br/> * VV'-type references are currently not possible, since the version store and * virtual nodetype representation don't allow such references. */public class SharedItemStateManager implements ItemStateManager, ItemStateListener, Dumpable { /** * Logger instance */ private static Logger log = LoggerFactory.getLogger(SharedItemStateManager.class); /** * cache of weak references to ItemState objects issued by this * ItemStateManager */ private final ItemStateReferenceCache cache; /** * Persistence Manager used for loading and storing items */ private final PersistenceManager persistMgr; /** * node type registry used for identifying referenceable nodes */ private final NodeTypeRegistry ntReg; /** * Flag indicating whether this item state manager uses node references to * verify integrity of its reference properties. */ private final boolean usesReferences; /** * id of root node */ private final NodeId rootNodeId; /** * Virtual item state providers */ private VirtualItemStateProvider[] virtualProviders = new VirtualItemStateProvider[0]; /** * JCR-447: deadlock might occur when this manager is still write-locked and events are dispatched. */ private boolean noLockHack = false; /** * State change dispatcher. */ private final transient StateChangeDispatcher dispatcher = new StateChangeDispatcher(); /** * Read-/Write-Lock to synchronize access on this item state manager. */ private final ReadWriteLock rwLock = new ReentrantWriterPreferenceReadWriteLock() { /** * Allow reader when there is no active writer, or current * thread owns the write lock (reentrant). * <p/> * the 'noLockHack' is only temporary (hopefully) */ protected boolean allowReader() { return activeWriter_ == null || activeWriter_ == Thread.currentThread() || noLockHack; } }; /** * Update event channel. */ private UpdateEventChannel eventChannel; /** * Creates a new <code>SharedItemStateManager</code> instance. * * @param persistMgr * @param rootNodeId * @param ntReg */ public SharedItemStateManager(PersistenceManager persistMgr, NodeId rootNodeId, NodeTypeRegistry ntReg, boolean usesReferences, ItemStateCacheFactory cacheFactory) throws ItemStateException { cache = new ItemStateReferenceCache(cacheFactory); this.persistMgr = persistMgr; this.ntReg = ntReg; this.usesReferences = usesReferences; this.rootNodeId = rootNodeId; // create root node state if it doesn't yet exist if (!hasNonVirtualItemState(rootNodeId)) { createRootNodeState(rootNodeId, ntReg); } } /** * enables or disables the write-lock hack. this should only be called by * the {@link XAVersionManager}. * * @param noLockHack */ public void setNoLockHack(boolean noLockHack) { this.noLockHack = noLockHack; } /** * Set an update event channel * * @param eventChannel update event channel */ public void setEventChannel(UpdateEventChannel eventChannel) { this.eventChannel = eventChannel; } //-----------------------------------------------------< ItemStateManager > /** * {@inheritDoc} */ public ItemState getItemState(ItemId id) throws NoSuchItemStateException, ItemStateException { acquireReadLock(); try { // check the virtual root ids (needed for overlay) for (int i = 0; i < virtualProviders.length; i++) { if (virtualProviders[i].isVirtualRoot(id)) { return virtualProviders[i].getItemState(id); } } // check internal first if (hasNonVirtualItemState(id)) { return getNonVirtualItemState(id); } // check if there is a virtual state for the specified item for (int i = 0; i < virtualProviders.length; i++) { if (virtualProviders[i].hasItemState(id)) { return virtualProviders[i].getItemState(id); } } } finally { rwLock.readLock().release(); } throw new NoSuchItemStateException(id.toString()); } /** * {@inheritDoc} */ public boolean hasItemState(ItemId id) { try { acquireReadLock(); } catch (ItemStateException e) { return false; } try { if (cache.isCached(id)) { return true; } // check the virtual root ids (needed for overlay) for (int i = 0; i < virtualProviders.length; i++) { if (virtualProviders[i].isVirtualRoot(id)) { return true; } } // check if this manager has the item state if (hasNonVirtualItemState(id)) { return true; } // otherwise check virtual ones for (int i = 0; i < virtualProviders.length; i++) { if (virtualProviders[i].hasItemState(id)) { return true; } } } finally { rwLock.readLock().release(); } return false; } /** * {@inheritDoc} */ public NodeReferences getNodeReferences(NodeReferencesId id) throws NoSuchItemStateException, ItemStateException { acquireReadLock(); try { // check persistence manager try { return persistMgr.load(id); } catch (NoSuchItemStateException e) { // ignore } // check virtual providers for (int i = 0; i < virtualProviders.length; i++) { try { return virtualProviders[i].getNodeReferences(id); } catch (NoSuchItemStateException e) { // ignore } } } finally { rwLock.readLock().release(); } // throw throw new NoSuchItemStateException(id.toString()); } /** * {@inheritDoc} */ public boolean hasNodeReferences(NodeReferencesId id) { try { acquireReadLock(); } catch (ItemStateException e) { return false; } try { // check persistence manager try { if (persistMgr.exists(id)) { return true; } } catch (ItemStateException e) { // ignore } // check virtual providers for (int i = 0; i < virtualProviders.length; i++) { if (virtualProviders[i].hasNodeReferences(id)) { return true; } } } finally { rwLock.readLock().release(); }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?