Index: src/main/java/org/apache/jackrabbit/core/state/LocalItemStateManager.java =================================================================== --- src/main/java/org/apache/jackrabbit/core/state/LocalItemStateManager.java (revision 602118) +++ src/main/java/org/apache/jackrabbit/core/state/LocalItemStateManager.java (working copy) @@ -35,7 +35,7 @@ * cache of weak references to ItemState objects issued by this * ItemStateManager */ - private final ItemStateReferenceCache cache; + private final ItemStateCache cache; /** * Shared item state manager @@ -69,7 +69,8 @@ */ public LocalItemStateManager(SharedItemStateManager sharedStateMgr, EventStateCollectionFactory factory, ItemStateCacheFactory cacheFactory) { - cache = new ItemStateReferenceCache(cacheFactory); + cache = new SynchronizedItemStateCache( + new ItemStateReferenceCache(cacheFactory)); this.sharedStateMgr = sharedStateMgr; this.factory = factory; @@ -140,7 +141,7 @@ } // check cache. synchronized to ensure an entry is not created twice. - synchronized (cache) { + synchronized (this) { state = cache.retrieve(id); if (state == null) { // regular behaviour @@ -336,8 +337,11 @@ // JCR-798: copy cached item states to array // to avoid ConcurrentModificationException - ItemState[] isa = (ItemState[]) cache.values().toArray( - new ItemState[cache.size()]); + ItemState[] isa; + synchronized (cache) { + isa = (ItemState[]) cache.values().toArray( + new ItemState[cache.size()]); + } for (int i = 0; i < isa.length; i++) { ItemState state = isa[i]; if (state != null) { Index: src/main/java/org/apache/jackrabbit/core/state/SynchronizedItemStateCache.java =================================================================== --- src/main/java/org/apache/jackrabbit/core/state/SynchronizedItemStateCache.java (revision 0) +++ src/main/java/org/apache/jackrabbit/core/state/SynchronizedItemStateCache.java (revision 0) @@ -0,0 +1,189 @@ +/* + * 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 org.apache.jackrabbit.core.ItemId; + +import java.util.Set; +import java.util.Collection; +import java.util.Collections; + +/** + * SynchronizedItemStateCache implements a wrapper for a {@link + * ItemStateCache} and turns it into a synchronized item state cache. + */ +class SynchronizedItemStateCache implements ItemStateCache { + + /** + * The underlying item state cache (not thread-safe). + */ + private final ItemStateCache cache; + + /** + * The mutex on which to synchronize access. + */ + private final Object mutex; + + /** + * Wraps the item state cache and provides synchronized access + * to it. Access to the cache is synchronized on this object. + * + * @param cache the item state cache. + */ + SynchronizedItemStateCache(ItemStateCache cache) { + this.cache = cache; + this.mutex = this; + } + + /** + * Wraps the item state cache and provides synchronized access + * to it. Access to the cache is synchronized on + * mutex. + * + * @param cache the item state cache. + * @param mutex the object on which to synchronize access. + */ + SynchronizedItemStateCache(ItemStateCache cache, Object mutex) { + this.cache = cache; + this.mutex = mutex; + } + + /** + * {@inheritDoc} + */ + public boolean isCached(ItemId id) { + synchronized (mutex) { + return cache.isCached(id); + } + } + + /** + * {@inheritDoc} + */ + public ItemState retrieve(ItemId id) { + synchronized (mutex) { + return cache.retrieve(id); + } + } + + /** + * {@inheritDoc} + */ + public void cache(ItemState state) { + synchronized (mutex) { + cache.cache(state); + } + } + + /** + * {@inheritDoc} + */ + public void evict(ItemId id) { + synchronized (mutex) { + cache.evict(id); + } + } + + /** + * {@inheritDoc} + */ + public void evictAll() { + synchronized (mutex) { + cache.evictAll(); + } + } + + /** + * {@inheritDoc} + */ + public boolean isEmpty() { + synchronized (mutex) { + return cache.isEmpty(); + } + } + + /** + * {@inheritDoc} + */ + public int size() { + synchronized (mutex) { + return cache.size(); + } + } + + /** + * {@inheritDoc} + *

+ * The returned Set is not synchronized. The caller must ensure that + * it manually synchronizes access to the Set. Example: + *

+     * ItemStateCache cache = new SynchronizedItemStateCache(...);
+     * synchronized (cache) {
+     *     Set keys = cache.keySet();
+     *     for (Iterator it = keys.iterator(); it.hasNext(); ) {
+     *         Object item = it.next();
+     *         // do something with item
+     *     }
+     * }
+     * 
+ */ + public Set keySet() { + synchronized (mutex) { + return cache.keySet(); + } + } + + /** + * {@inheritDoc} + *

+ * The returned collection is not synchronized. The caller must ensure that + * it manually synchronizes access to the collection. Example: + *

+     * ItemStateCache cache = new SynchronizedItemStateCache(...);
+     * synchronized (cache) {
+     *     Collection values = cache.values();
+     *     for (Iterator it = values.iterator(); it.hasNext(); ) {
+     *         Object item = it.next();
+     *         // do something with item
+     *     }
+     * }
+     * 
+ */ + public Collection values() { + synchronized (mutex) { + return cache.values(); + } + } + + /** + * {@inheritDoc} + */ + public void update(ItemId id) { + synchronized (mutex) { + cache.update(id); + } + } + + /** + * {@inheritDoc} + */ + public void dispose() { + synchronized (mutex) { + cache.dispose(); + } + } +} Property changes on: src\main\java\org\apache\jackrabbit\core\state\SynchronizedItemStateCache.java ___________________________________________________________________ Name: svn:eol-style + native