/* * Copyright 2000-2013 Enonic AS * http://www.enonic.com/license */ package com.enonic.cms.framework.cache.standard; import java.lang.ref.SoftReference; import java.util.Collection; import java.util.HashSet; import java.util.Set; import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap; import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap.Builder; /** * Our standard cache that uses the LRU eviction method. */ final class StandardCache { private final int maxEntries; private final ConcurrentLinkedHashMap<String, SoftReference<CacheEntry>> map; public StandardCache( final int maxEntries ) { this.map = new Builder<String, SoftReference<CacheEntry>>().maximumWeightedCapacity( maxEntries ).build(); this.maxEntries = maxEntries; } public int getMaxEntries() { return maxEntries; } public int numberOfEntries() { return map.size(); } protected Set<String> getKeys() { // this method is only used in tests return map.keySet(); } public CacheEntry get( String key ) { SoftReference referenceWrapper = doGet( key ); if ( referenceWrapper == null ) { return null; } CacheEntry entry = (CacheEntry) referenceWrapper.get(); if ( entry == null || entry.isExpired() ) { doRemove( key ); return null; } entry.updateLastAccessTime(); return entry; } public void put( CacheEntry entry ) { doPut( entry ); } public void removeAll() { doRemoveAll(); } public void remove( String key ) { doRemove( key ); } public void removeGroup( String group ) { String prefix = group + ":"; Set<String> keys = doGetByPrefix( prefix ); doRemoveKeys( keys ); } public void removeGroupByPrefix( String prefix ) { Set<String> keys = doGetByPrefix( prefix ); doRemoveKeys( keys ); } private void doRemoveKeys( Collection<String> keys ) { for ( String key : keys ) { doRemove( key ); } } private SoftReference doGet( String key ) { return map.get( key ); } private void doPut( CacheEntry entry ) { map.put( entry.getKey(), new SoftReference<CacheEntry>( entry ) ); } private void doRemove( String key ) { map.remove( key ); } private void doRemoveAll() { map.clear(); } private Set<String> doGetByPrefix( String prefix ) { HashSet<String> keys = new HashSet<String>(); for ( String key : map.keySet() ) { if ( key.startsWith( prefix ) ) { keys.add( key ); } } return keys; } }