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.memory;
17  
18  import com.ibatis.sqlmap.engine.cache.CacheController;
19  import com.ibatis.sqlmap.engine.cache.CacheModel;
20  
21  import java.lang.ref.SoftReference;
22  import java.lang.ref.WeakReference;
23  import java.util.Collections;
24  import java.util.HashMap;
25  import java.util.Map;
26  import java.util.Properties;
27  
28  /**
29   * Memory-based implementation of CacheController.
30   */
31  public class MemoryCacheController implements CacheController {
32  
33    /** The reference type. */
34    private MemoryCacheLevel referenceType = MemoryCacheLevel.WEAK;
35  
36    /** The cache. */
37    private Map cache = Collections.synchronizedMap(new HashMap<>());
38  
39    /**
40     * Configures the cache
41     *
42     * @param props
43     *          Optionally can contain properties [reference-type=WEAK|SOFT|STRONG]
44     */
45    @Override
46    public void setProperties(Properties props) {
47      String refType = props.getProperty("reference-type");
48      if (refType == null) {
49        refType = props.getProperty("referenceType");
50      }
51      if (refType != null) {
52        referenceType = MemoryCacheLevel.getByReferenceType(refType);
53      }
54    }
55  
56    /**
57     * Gets the reference type.
58     *
59     * @return the reference type
60     */
61    public MemoryCacheLevel getReferenceType() {
62      return referenceType;
63    }
64  
65    /**
66     * Sets the reference type.
67     *
68     * @param referenceType
69     *          the new reference type
70     */
71    public void setReferenceType(MemoryCacheLevel referenceType) {
72      this.referenceType = referenceType;
73    }
74  
75    /**
76     * Add an object to the cache
77     *
78     * @param cacheModel
79     *          The cacheModel
80     * @param key
81     *          The key of the object to be cached
82     * @param value
83     *          The object to be cached
84     */
85    @Override
86    public void putObject(CacheModel cacheModel, Object key, Object value) {
87      Object reference = null;
88      if (referenceType.equals(MemoryCacheLevel.WEAK)) {
89        reference = new WeakReference(value);
90      } else if (referenceType.equals(MemoryCacheLevel.SOFT)) {
91        reference = new SoftReference(value);
92      } else if (referenceType.equals(MemoryCacheLevel.STRONG)) {
93        reference = new StrongReference(value);
94      }
95      cache.put(key, reference);
96    }
97  
98    /**
99     * Get an object out of the cache.
100    *
101    * @param cacheModel
102    *          The cache model
103    * @param key
104    *          The key of the object to be returned
105    *
106    * @return The cached object (or null)
107    */
108   @Override
109   public Object getObject(CacheModel cacheModel, Object key) {
110     Object value = null;
111     Object ref = cache.get(key);
112     if (ref != null) {
113       if (ref instanceof StrongReference) {
114         value = ((StrongReference) ref).get();
115       } else if (ref instanceof SoftReference) {
116         value = ((SoftReference) ref).get();
117       } else if (ref instanceof WeakReference) {
118         value = ((WeakReference) ref).get();
119       }
120     }
121     return value;
122   }
123 
124   @Override
125   public Object removeObject(CacheModel cacheModel, Object key) {
126     Object value = null;
127     Object ref = cache.remove(key);
128     if (ref != null) {
129       if (ref instanceof StrongReference) {
130         value = ((StrongReference) ref).get();
131       } else if (ref instanceof SoftReference) {
132         value = ((SoftReference) ref).get();
133       } else if (ref instanceof WeakReference) {
134         value = ((WeakReference) ref).get();
135       }
136     }
137     return value;
138   }
139 
140   /**
141    * Flushes the cache.
142    *
143    * @param cacheModel
144    *          The cache model
145    */
146   @Override
147   public void flush(CacheModel cacheModel) {
148     cache.clear();
149   }
150 
151   /**
152    * Class to implement a strong (permanent) reference.
153    */
154   private static class StrongReference {
155 
156     /** The object. */
157     private Object object;
158 
159     /**
160      * StrongReference constructor for an object.
161      *
162      * @param object
163      *          - the Object to store
164      */
165     public StrongReference(Object object) {
166       this.object = object;
167     }
168 
169     /**
170      * Getter to get the object stored in the StrongReference.
171      *
172      * @return - the stored Object
173      */
174     public Object get() {
175       return object;
176     }
177   }
178 
179 }