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 + -
显示快捷键?