View Javadoc
1   /*
2    * Copyright 2004-2025 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *    https://www.apache.org/licenses/LICENSE-2.0
9    *
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 com.ibatis.sqlmap.engine.cache.lru;
17  
18  import com.ibatis.sqlmap.engine.cache.CacheController;
19  import com.ibatis.sqlmap.engine.cache.CacheModel;
20  
21  import java.util.Collections;
22  import java.util.HashMap;
23  import java.util.LinkedList;
24  import java.util.List;
25  import java.util.Map;
26  import java.util.Properties;
27  
28  /**
29   * LRU (least recently used) cache controller implementation.
30   */
31  public class LruCacheController implements CacheController {
32  
33    /** The cache size. */
34    private int cacheSize;
35  
36    /** The cache. */
37    private Map cache;
38  
39    /** The key list. */
40    private List keyList;
41  
42    /**
43     * Default constructor.
44     */
45    public LruCacheController() {
46      this.cacheSize = 100;
47      this.cache = Collections.synchronizedMap(new HashMap<>());
48      this.keyList = Collections.synchronizedList(new LinkedList());
49    }
50  
51    /**
52     * Gets the cache size.
53     *
54     * @return the cache size
55     */
56    public int getCacheSize() {
57      return cacheSize;
58    }
59  
60    /**
61     * Sets the cache size.
62     *
63     * @param cacheSize
64     *          the new cache size
65     */
66    public void setCacheSize(int cacheSize) {
67      this.cacheSize = cacheSize;
68    }
69  
70    /**
71     * Configures the cache
72     *
73     * @param props
74     *          Optionally can contain properties [reference-type=WEAK|SOFT|STRONG]
75     */
76    @Override
77    public void setProperties(Properties props) {
78      String size = props.getProperty("cache-size");
79      if (size == null) {
80        size = props.getProperty("size");
81      }
82      if (size != null) {
83        cacheSize = Integer.parseInt(size);
84      }
85    }
86  
87    /**
88     * Add an object to the cache
89     *
90     * @param cacheModel
91     *          The cacheModel
92     * @param key
93     *          The key of the object to be cached
94     * @param value
95     *          The object to be cached
96     */
97    @Override
98    public void putObject(CacheModel cacheModel, Object key, Object value) {
99      cache.put(key, value);
100     keyList.add(key);
101     if (keyList.size() > cacheSize) {
102       try {
103         Object oldestKey = keyList.remove(0);
104         cache.remove(oldestKey);
105       } catch (IndexOutOfBoundsException e) {
106         // ignore
107       }
108     }
109   }
110 
111   /**
112    * Get an object out of the cache.
113    *
114    * @param cacheModel
115    *          The cache model
116    * @param key
117    *          The key of the object to be returned
118    *
119    * @return The cached object (or null)
120    */
121   @Override
122   public Object getObject(CacheModel cacheModel, Object key) {
123     Object result = cache.get(key);
124     keyList.remove(key);
125     if (result != null) {
126       keyList.add(key);
127     }
128     return result;
129   }
130 
131   @Override
132   public Object removeObject(CacheModel cacheModel, Object key) {
133     keyList.remove(key);
134     return cache.remove(key);
135   }
136 
137   /**
138    * Flushes the cache.
139    *
140    * @param cacheModel
141    *          The cache model
142    */
143   @Override
144   public void flush(CacheModel cacheModel) {
145     cache.clear();
146     keyList.clear();
147   }
148 
149 }