View Javadoc

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 }