1 package org.apache.torque.manager;
2
3 /*
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
19 * under the License.
20 */
21
22 import java.io.Serializable;
23 import java.util.HashMap;
24 import java.util.Map;
25
26 import org.apache.commons.logging.Log;
27 import org.apache.commons.logging.LogFactory;
28 import org.apache.jcs.access.GroupCacheAccess;
29 import org.apache.jcs.access.exception.CacheException;
30 import org.apache.torque.TorqueException;
31
32 /**
33 * This class provides a cache for convenient storage of method
34 * results.
35 *
36 * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
37 * @version $Id: MethodResultCache.java 1379317 2012-08-31 06:56:48Z tfischer $
38 */
39 public class MethodResultCache
40 {
41 /** The underlying jcs cache. */
42 private GroupCacheAccess jcsCache;
43
44 /** All chache groups which are currently filled. */
45 private Map<String, Object> groups;
46
47 /** Logging */
48 private static Log log = LogFactory.getLog(MethodResultCache.class);
49
50 /**
51 * Constructor
52 *
53 * @param cache the cache instance to use
54 */
55 public MethodResultCache(GroupCacheAccess cache)
56 {
57 this.jcsCache = cache;
58 groups = new HashMap<String, Object>();
59 }
60
61 /**
62 * Allows subclasses to have ctors that do not require a cache.
63 * This is used by NullMethodResultCache which has no-op versions
64 * of all methods.
65 */
66 protected MethodResultCache()
67 {
68 //empty
69 }
70
71 /**
72 * Clear the cache
73 */
74 public void clear()
75 {
76 if (jcsCache != null)
77 {
78 try
79 {
80 jcsCache.clear();
81 groups.clear();
82 }
83 catch (CacheException ce)
84 {
85 log.error(new TorqueException(
86 "Could not clear cache due to internal JCS error.", ce));
87 }
88 }
89 }
90
91 protected Object getImpl(MethodCacheKey key)
92 {
93 Object result = null;
94 if (jcsCache != null)
95 {
96 synchronized (this)
97 {
98 result = jcsCache.getFromGroup(key, key.getGroupKey());
99 }
100 }
101
102 if (result != null && log.isDebugEnabled())
103 {
104 log.debug("MethodResultCache saved expensive operation: " + key);
105 }
106
107 return result;
108 }
109
110
111 protected Object putImpl(MethodCacheKey key, Object value)
112 throws TorqueException
113 {
114 //register the group, if this is the first occurrence
115 String group = key.getGroupKey();
116 if (!groups.containsKey(group))
117 {
118 groups.put(group, null);
119 }
120
121 Object old = null;
122 if (jcsCache != null)
123 {
124 try
125 {
126 synchronized (this)
127 {
128 old = jcsCache.getFromGroup(key, group);
129 jcsCache.putInGroup(key, group, value);
130 }
131 }
132 catch (CacheException ce)
133 {
134 throw new TorqueException
135 ("Could not cache due to internal JCS error", ce);
136 }
137 }
138 return old;
139 }
140
141 protected Object removeImpl(MethodCacheKey key)
142 {
143 Object old = null;
144 if (jcsCache != null)
145 {
146 synchronized (this)
147 {
148 old = jcsCache.getFromGroup(key, key.getGroupKey());
149 jcsCache.remove(key, key.getGroupKey());
150 }
151 }
152 return old;
153 }
154
155 /**
156 * Get an object from the method cache
157 *
158 * @param instanceOrClass the Object on which the method is invoked. if
159 * the method is static, a String representing the class name is used.
160 * @param method the method name
161 * @param arg optional arguments for the method
162 *
163 * @return the object or null if it does not exist
164 */
165 @SuppressWarnings("unchecked")
166 public <T> T get(Serializable instanceOrClass, String method, Serializable ... arg)
167 {
168 T result = null;
169 if (jcsCache != null)
170 {
171 try
172 {
173 MethodCacheKey key = new MethodCacheKey(instanceOrClass, method, arg);
174 result = (T) getImpl(key);
175 }
176 catch (Exception e)
177 {
178 log.error("Problem getting object from cache", e);
179 }
180 }
181
182 return result;
183 }
184
185 /**
186 * Put an object into the method cache
187 *
188 * @param value the object to put into the cache
189 * @param instanceOrClass the Object on which the method is invoked. if
190 * the method is static, a String representing the class name is used.
191 * @param method the method name
192 * @param arg optional arguments for the method
193 */
194 public <T> void put(T value, Serializable instanceOrClass, String method, Serializable ... arg)
195 {
196 try
197 {
198 MethodCacheKey key = new MethodCacheKey(instanceOrClass, method, arg);
199 putImpl(key, value);
200 }
201 catch (Exception e)
202 {
203 log.error("Problem putting object into cache", e);
204 }
205 }
206
207 /**
208 * Remove all objects of the same group
209 *
210 * @param instanceOrClass the Object on which the method is invoked. if
211 * the method is static, a String representing the class name is used.
212 * @param method the method name
213 */
214 public void removeAll(Serializable instanceOrClass, String method)
215 {
216 if (jcsCache != null)
217 {
218 try
219 {
220 MethodCacheKey key = new MethodCacheKey(instanceOrClass, method);
221 String groupName = key.getGroupKey();
222 jcsCache.invalidateGroup(groupName);
223 groups.remove(groupName);
224 }
225 catch (Exception e)
226 {
227 log.error("Problem removing all", e);
228 }
229 }
230 }
231
232 /**
233 * Remove object from method cache
234 *
235 * @param instanceOrClass the Object on which the method is invoked. if
236 * the method is static, a String representing the class name is used.
237 * @param method the method name
238 * @param arg optional arguments for the method
239 *
240 * @return the removed object
241 */
242 @SuppressWarnings("unchecked")
243 public <T> T remove(Serializable instanceOrClass, String method, Serializable ... arg)
244 {
245 T result = null;
246 if (jcsCache != null)
247 {
248 try
249 {
250 MethodCacheKey key = new MethodCacheKey(instanceOrClass, method, arg);
251 result = (T) removeImpl(key);
252 }
253 catch (Exception e)
254 {
255 log.error("Problem removing object from cache", e);
256 }
257 }
258
259 return result;
260 }
261 }