View Javadoc
1   package org.apache.commons.jcs.access;
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.IOException;
23  import java.util.HashMap;
24  import java.util.Map;
25  import java.util.Set;
26  
27  import org.apache.commons.jcs.access.behavior.ICacheAccess;
28  import org.apache.commons.jcs.access.exception.CacheException;
29  import org.apache.commons.jcs.access.exception.InvalidArgumentException;
30  import org.apache.commons.jcs.access.exception.InvalidHandleException;
31  import org.apache.commons.jcs.access.exception.ObjectExistsException;
32  import org.apache.commons.jcs.engine.CacheElement;
33  import org.apache.commons.jcs.engine.behavior.ICacheElement;
34  import org.apache.commons.jcs.engine.behavior.IElementAttributes;
35  import org.apache.commons.jcs.engine.control.CompositeCache;
36  import org.apache.commons.logging.Log;
37  import org.apache.commons.logging.LogFactory;
38  
39  /**
40   * This class provides an interface for all types of access to the cache.
41   * <p>
42   * An instance of this class is tied to a specific cache region. Static methods are provided to get
43   * such instances.
44   * <p>
45   * Using this class you can retrieve an item, the item's wrapper, and the element's configuration.  You can also put an
46   * item in the cache, remove an item, and clear a region.
47   * <p>
48   * The JCS class is the preferred way to access these methods.
49   */
50  public class CacheAccess<K, V>
51      extends AbstractCacheAccess<K, V>
52      implements ICacheAccess<K, V>
53  {
54      /** The logger. */
55      private static final Log log = LogFactory.getLog( CacheAccess.class );
56  
57      /**
58       * Constructor for the CacheAccess object.
59       * <p>
60       * @param cacheControl The cache which the created instance accesses
61       */
62      public CacheAccess( CompositeCache<K, V> cacheControl )
63      {
64          super(cacheControl);
65      }
66  
67      /**
68       * Retrieve an object from the cache region this instance provides access to.
69       * <p>
70       * @param name Key the object is stored as
71       * @return The object if found or null
72       */
73      @Override
74      public V get( K name )
75      {
76          ICacheElement<K, V> element = this.getCacheControl().get( name );
77  
78          return ( element != null ) ? element.getVal() : null;
79      }
80  
81      /**
82       * Retrieve matching objects from the cache region this instance provides access to.
83       * <p>
84       * @param pattern - a key pattern for the objects stored
85       * @return A map of key to values.  These are stripped from the wrapper.
86       */
87      @Override
88      public Map<K, V> getMatching( String pattern )
89      {
90          HashMap<K, V> unwrappedResults = new HashMap<K, V>();
91  
92          Map<K, ICacheElement<K, V>> wrappedResults = this.getCacheControl().getMatching( pattern );
93          if ( wrappedResults != null )
94          {
95              for (Map.Entry<K, ICacheElement<K, V>> entry : wrappedResults.entrySet())
96              {
97                  ICacheElement<K, V> element = entry.getValue();
98                  if ( element != null )
99                  {
100                     unwrappedResults.put( entry.getKey(), element.getVal() );
101                 }
102             }
103         }
104         return unwrappedResults;
105     }
106 
107     /**
108      * This method returns the ICacheElement&lt;K, V&gt; wrapper which provides access to element info and other
109      * attributes.
110      * <p>
111      * This returns a reference to the wrapper. Any modifications will be reflected in the cache. No
112      * defensive copy is made.
113      * <p>
114      * This method is most useful if you want to determine things such as the how long the element
115      * has been in the cache.
116      * <p>
117      * The last access time in the ElementAttributes should be current.
118      * <p>
119      * @param name Key the Serializable is stored as
120      * @return The ICacheElement&lt;K, V&gt; if the object is found or null
121      */
122     @Override
123     public ICacheElement<K, V> getCacheElement( K name )
124     {
125         return this.getCacheControl().get( name );
126     }
127 
128     /**
129      * Get multiple elements from the cache based on a set of cache keys.
130      * <p>
131      * This method returns the ICacheElement&lt;K, V&gt; wrapper which provides access to element info and other
132      * attributes.
133      * <p>
134      * This returns a reference to the wrapper. Any modifications will be reflected in the cache. No
135      * defensive copy is made.
136      * <p>
137      * This method is most useful if you want to determine things such as the how long the element
138      * has been in the cache.
139      * <p>
140      * The last access time in the ElementAttributes should be current.
141      * <p>
142      * @param names set of Serializable cache keys
143      * @return a map of K key to ICacheElement&lt;K, V&gt; element, or empty map if none of the keys are present
144      */
145     @Override
146     public Map<K, ICacheElement<K, V>> getCacheElements( Set<K> names )
147     {
148         return this.getCacheControl().getMultiple( names );
149     }
150 
151     /**
152      * Get multiple elements from the cache based on a set of cache keys.
153      * <p>
154      * This method returns the ICacheElement&lt;K, V&gt; wrapper which provides access to element info and other
155      * attributes.
156      * <p>
157      * This returns a reference to the wrapper. Any modifications will be reflected in the cache. No
158      * defensive copy is made.
159      * <p>
160      * This method is most useful if you want to determine things such as the how long the element
161      * has been in the cache.
162      * <p>
163      * The last access time in the ElementAttributes should be current.
164      * <p>
165      * @param pattern key search pattern
166      * @return a map of K key to ICacheElement&lt;K, V&gt; element, or empty map if no keys match the pattern
167      */
168     @Override
169     public Map<K, ICacheElement<K, V>> getMatchingCacheElements( String pattern )
170     {
171         return this.getCacheControl().getMatching( pattern );
172     }
173 
174     /**
175      * Place a new object in the cache, associated with key name. If there is currently an object
176      * associated with name in the region an ObjectExistsException is thrown. Names are scoped to a
177      * region so they must be unique within the region they are placed.
178      * <p>
179      * @param key Key object will be stored with
180      * @param value Object to store
181      * @throws CacheException and ObjectExistsException is thrown if the item is already in the
182      *                cache.
183      */
184     @Override
185     public void putSafe( K key, V value )
186     {
187         if ( this.getCacheControl().get( key ) != null )
188         {
189             throw new ObjectExistsException( "putSafe failed.  Object exists in the cache for key [" + key
190                 + "].  Remove first or use a non-safe put to override the value." );
191         }
192         put( key, value );
193     }
194 
195     /**
196      * Place a new object in the cache, associated with key name. If there is currently an object
197      * associated with name in the region it is replaced. Names are scoped to a region so they must
198      * be unique within the region they are placed.
199      * @param name Key object will be stored with
200      * @param obj Object to store
201      */
202     @Override
203     public void put( K name, V obj )
204     {
205         // Call put with a copy of the contained caches default attributes.
206         // the attributes are copied by the cacheControl
207         put( name, obj, this.getCacheControl().getElementAttributes() );
208     }
209 
210     /**
211      * Constructs a cache element with these attributes, and puts it into the cache.
212      * <p>
213      * If the key or the value is null, and InvalidArgumentException is thrown.
214      * <p>
215      * @see org.apache.commons.jcs.access.behavior.ICacheAccess#put(Object, Object, IElementAttributes)
216      */
217     @Override
218     public void put( K key, V val, IElementAttributes attr )
219     {
220         if ( key == null )
221         {
222             throw new InvalidArgumentException( "Key must not be null" );
223         }
224 
225         if ( val == null )
226         {
227             throw new InvalidArgumentException( "Value must not be null" );
228         }
229 
230         // Create the element and update. This may throw an IOException which
231         // should be wrapped by cache access.
232         try
233         {
234             CacheElement<K, V> ce = new CacheElement<K, V>( this.getCacheControl().getCacheName(), key,
235                                                 val );
236 
237             ce.setElementAttributes( attr );
238 
239             this.getCacheControl().update( ce );
240         }
241         catch ( IOException e )
242         {
243             throw new CacheException( e );
244         }
245     }
246 
247     /**
248      * Removes a single item by name.
249      * <p>
250      * @param name the name of the item to remove.
251      */
252     @Override
253     public void remove( K name )
254     {
255         this.getCacheControl().remove( name );
256     }
257 
258     /**
259      * Reset attributes for a particular element in the cache. NOTE: this method is currently not
260      * implemented.
261      * <p>
262      * @param name Key of object to reset attributes for
263      * @param attr New attributes for the object
264      * @throws InvalidHandleException if the item does not exist.
265      */
266     @Override
267     public void resetElementAttributes( K name, IElementAttributes attr )
268     {
269         ICacheElement<K, V> element = this.getCacheControl().get( name );
270 
271         if ( element == null )
272         {
273             throw new InvalidHandleException( "Object for name [" + name + "] is not in the cache" );
274         }
275 
276         // Although it will work currently, don't assume pass by reference here,
277         // i.e. don't do this:
278         // element.setElementAttributes( attr );
279         // Another reason to call put is to force the changes to be distributed.
280 
281         put( element.getKey(), element.getVal(), attr );
282     }
283 
284     /**
285      * GetElementAttributes will return an attribute object describing the current attributes
286      * associated with the object name. The name object must override the Object.equals and
287      * Object.hashCode methods.
288      * <p>
289      * @param name Key of object to get attributes for
290      * @return Attributes for the object, null if object not in cache
291      */
292     @Override
293     public IElementAttributes getElementAttributes( K name )
294     {
295         IElementAttributes attr = null;
296 
297         try
298         {
299             attr = this.getCacheControl().getElementAttributes( name );
300         }
301         catch ( IOException ioe )
302         {
303             log.error( "Failure getting element attributes", ioe );
304         }
305 
306         return attr;
307     }
308 }