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<K, V> 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<K, V> 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<K, V> 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<K, V> 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<K, V> 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<K, V> 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 }