org.apache.jackrabbit.spi.commons.ItemInfoCacheImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of org.apache.sling.feature.analyser Show documentation
Show all versions of org.apache.sling.feature.analyser Show documentation
A feature describes an OSGi system
/*
* 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.spi.commons;
import org.apache.commons.collections.map.LinkedMap;
import org.apache.jackrabbit.spi.ItemId;
import org.apache.jackrabbit.spi.ItemInfo;
import org.apache.jackrabbit.spi.ItemInfoCache;
import org.apache.jackrabbit.spi.NodeId;
import org.apache.jackrabbit.spi.NodeInfo;
import org.apache.jackrabbit.spi.PropertyId;
import org.apache.jackrabbit.spi.PropertyInfo;
import org.apache.jackrabbit.spi.RepositoryService;
/**
* This implementation of {@link ItemInfoCache} has a default size of 5000 items.
* Item infos are put into the cache after they have been read from the {@link RepositoryService}.
* If the cache is full, the oldest item is discarded. Reading items removes them
* from the cache.
*
* The underlying idea here is, that {@link ItemInfo}s which are supplied by the
* RepositoryService
but not immediately needed are put into the
* cache to avoid further round trips to RepositoryService
.
* When they are needed later, they are read from the cache. There is no need to
* keep them in this cache after that point since they are present in the
* hierarchy from then on.
*/
public class ItemInfoCacheImpl implements ItemInfoCache {
/**
* Default size of the cache.
*/
public static final int DEFAULT_CACHE_SIZE = 5000;
private final int cacheSize;
private final LinkedMap entries;
/**
* Create a new instance with the default cache size.
* @see #DEFAULT_CACHE_SIZE
*/
public ItemInfoCacheImpl() {
this(DEFAULT_CACHE_SIZE);
}
/**
* Create a new instance with a given cache size.
* @param cacheSize
*/
public ItemInfoCacheImpl(int cacheSize) {
super();
this.cacheSize = cacheSize;
entries = new LinkedMap(cacheSize);
}
/**
* This implementation removes the item from the cache
* if it is present. Furthermore if the nodeId
* id uuid based, and no item is found by the nodeId
* a second lookup is done by the path.
*/
public Entry getNodeInfo(NodeId nodeId) {
Object entry = entries.remove(nodeId);
if (entry == null) {
entry = entries.remove(nodeId.getPath());
} else {
// there might be a corresponding path-indexed entry, clear it as well
entries.remove(node(entry).info.getPath());
}
return node(entry);
}
/**
* This implementation removes the item from the cache
* if it is present. Furthermore if the propertyId
* id uuid based, and no item is found by the propertyId
* a second lookup is done by the path.
*/
public Entry getPropertyInfo(PropertyId propertyId) {
Object entry = entries.remove(propertyId);
if (entry == null) {
entry = entries.remove(propertyId.getPath());
} else {
// there might be a corresponding path-indexed entry, clear it as well
entries.remove(property(entry).info.getPath());
}
return property(entry);
}
/**
* This implementation cached the item by its id and if the id
* is uuid based but has no path, also by its path.
*/
public void put(ItemInfo info, long generation) {
ItemId id = info.getId();
Entry extends ItemInfo> entry = info.denotesNode()
? new Entry((NodeInfo) info, generation)
: new Entry((PropertyInfo) info, generation);
put(id, entry);
if (id.getUniqueID() != null && id.getPath() == null) {
put(info.getPath(), entry);
}
}
public void dispose() {
entries.clear();
}
// -----------------------------------------------------< private >---
private void put(Object key, Entry extends ItemInfo> entry) {
entries.remove(key);
if (entries.size() >= cacheSize) {
entries.remove(entries.firstKey()); // xxx AbstractLinkedMap#firstKey() Javadoc is wrong. See COLLECTIONS-353
}
entries.put(key, entry);
}
@SuppressWarnings("unchecked")
private static Entry node(Object entry) {
if (entry != null && ((Entry extends ItemInfo>) entry).info.denotesNode()) {
return (Entry) entry;
}
else {
return null;
}
}
@SuppressWarnings("unchecked")
private static Entry property(Object entry) {
if (entry != null && !((Entry extends ItemInfo>) entry).info.denotesNode()) {
return (Entry) entry;
}
else {
return null;
}
}
}