01: /*
02: * Copyright 2006, 2007 Odysseus Software GmbH
03: *
04: * Licensed under the Apache License, Version 2.0 (the "License");
05: * you may not use this file except in compliance with the License.
06: * You may obtain a copy of the License at
07: *
08: * http://www.apache.org/licenses/LICENSE-2.0
09: *
10: * Unless required by applicable law or agreed to in writing, software
11: * distributed under the License is distributed on an "AS IS" BASIS,
12: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13: * See the License for the specific language governing permissions and
14: * limitations under the License.
15: */
16: package de.odysseus.el.tree.impl;
17:
18: import java.util.Collections;
19: import java.util.LinkedHashMap;
20: import java.util.Map;
21: import java.util.WeakHashMap;
22: import java.util.Map.Entry;
23:
24: import de.odysseus.el.tree.Tree;
25: import de.odysseus.el.tree.TreeCache;
26:
27: /**
28: * Simple (thread-safe) LRU cache.
29: * After the cache size reached a certain limit, the least recently used entry is removed,
30: * when adding a new entry.
31: *
32: * @author Christoph Beck
33: */
34: public final class Cache implements TreeCache {
35: private final Map<String, Tree> primary;
36: private final Map<String, Tree> secondary;
37:
38: /**
39: * Constructor.
40: * Use a {@link WeakHashMap} as secondary map.
41: * @param size maximum primary cache size
42: */
43: public Cache(int size) {
44: this (size, new WeakHashMap<String, Tree>());
45: }
46:
47: /**
48: * Constructor.
49: * If the least recently used entry is removed from the primary cache, it is added to
50: * the secondary map.
51: * @param size maximum primary cache size
52: * @param secondary the secondary map (may be <code>null</code>)
53: */
54: @SuppressWarnings("serial")
55: public Cache(final int size, Map<String, Tree> secondary) {
56: this .primary = Collections
57: .synchronizedMap(new LinkedHashMap<String, Tree>(16,
58: 0.75f, true) {
59: @Override
60: protected boolean removeEldestEntry(
61: Entry<String, Tree> eldest) {
62: if (size() > size) {
63: if (Cache.this .secondary != null) { // move to secondary cache
64: Cache.this .secondary.put(eldest
65: .getKey(), eldest.getValue());
66: }
67: return true;
68: }
69: return false;
70: }
71: });
72: this .secondary = secondary == null ? null : Collections
73: .synchronizedMap(secondary);
74: }
75:
76: public Tree get(String expression) {
77: if (secondary == null) {
78: return primary.get(expression);
79: } else {
80: Tree tree = primary.get(expression);
81: if (tree == null) {
82: tree = secondary.get(expression);
83: }
84: return tree;
85: }
86: }
87:
88: public void put(String expression, Tree tree) {
89: primary.put(expression, tree);
90: }
91: }
|