blob: 383249137bbc79bd17b3b3a94e4b359992367917 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. 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. For additional information regarding
* copyright in this work, please see the NOTICE file in the top level
* directory of this distribution.
*/
package org.apache.roller.weblogger.util;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* LRU cache with per-entry timeout logic.
*
* @author Dave Johnson
*/
public class LRUCache2
{
private long timeout;
private Map<Object, CacheEntry> cache = null;
private Environment environment = null;
/**
* Create cache.
*
* @param maxsize
* Maximum number of entries in cache.
* @param timeout
* Entry timeout in milli-seconds.
*/
public LRUCache2(int maxsize, long timeout)
{
this.environment = new DefaultEnvironment();
this.timeout = timeout;
this.cache = new LRULinkedHashMap(maxsize);
}
/**
* Create cache that uses custom environment.
*
* @param maxsize
* Maximum number of entries in cache.
* @param timeout
* Entry timeout in milli-seconds.
*/
public LRUCache2(Environment environment, int maxsize, long timeout)
{
this.environment = environment;
this.timeout = timeout;
this.cache = new LRULinkedHashMap(maxsize);
}
public synchronized void put(Object key, Object value)
{
CacheEntry entry = new CacheEntry(value, environment
.getCurrentTimeInMillis());
cache.put(key, entry);
}
public Object get(Object key)
{
Object value = null;
CacheEntry entry;
synchronized(this)
{
entry = cache.get(key);
}
if (entry != null)
{
if (environment.getCurrentTimeInMillis() - entry.getTimeCached() < timeout)
{
value = entry.getValue();
}
else
{
cache.remove(entry);
}
}
return value;
}
public synchronized void purge()
{
cache.clear();
}
public synchronized void purge(String[] patterns)
{
List<String> purgeList = new ArrayList<String>();
for (Object objKey : cache.keySet()) {
String key = (String) objKey;
for (String s : patterns) {
if (key.contains(s)) {
purgeList.add(key);
break;
}
}
}
for (String s: purgeList) {
cache.remove(s);
}
}
public int size() {
return cache.size();
}
public interface Environment {
long getCurrentTimeInMillis();
}
public static class DefaultEnvironment implements Environment {
public long getCurrentTimeInMillis()
{
return System.currentTimeMillis();
}
}
private static class CacheEntry
{
private Object value;
private long timeCached = -1;
public CacheEntry(Object value, long timeCached)
{
this.timeCached = timeCached;
this.value = value;
}
public long getTimeCached()
{
return timeCached;
}
public Object getValue()
{
return value;
}
}
// David Flanaghan: http://www.davidflanagan.com/blog/000014.html
private static class LRULinkedHashMap extends LinkedHashMap<Object, CacheEntry>
{
protected int maxsize;
public LRULinkedHashMap(int maxsize)
{
super(maxsize * 4 / 3 + 1, 0.75f, true);
this.maxsize = maxsize;
}
protected boolean removeEldestEntry(Map.Entry eldest)
{
return this.size() > this.maxsize;
}
}
}