001package org.apache.commons.jcs.access; 002 003/* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022import java.io.IOException; 023import java.util.HashMap; 024import java.util.Map; 025import java.util.Set; 026 027import org.apache.commons.jcs.access.behavior.ICacheAccess; 028import org.apache.commons.jcs.access.exception.CacheException; 029import org.apache.commons.jcs.access.exception.InvalidArgumentException; 030import org.apache.commons.jcs.access.exception.InvalidHandleException; 031import org.apache.commons.jcs.access.exception.ObjectExistsException; 032import org.apache.commons.jcs.engine.CacheElement; 033import org.apache.commons.jcs.engine.behavior.ICacheElement; 034import org.apache.commons.jcs.engine.behavior.IElementAttributes; 035import org.apache.commons.jcs.engine.control.CompositeCache; 036import org.apache.commons.logging.Log; 037import org.apache.commons.logging.LogFactory; 038 039/** 040 * This class provides an interface for all types of access to the cache. 041 * <p> 042 * An instance of this class is tied to a specific cache region. Static methods are provided to get 043 * such instances. 044 * <p> 045 * Using this class you can retrieve an item, the item's wrapper, and the element's configuration. You can also put an 046 * item in the cache, remove an item, and clear a region. 047 * <p> 048 * The JCS class is the preferred way to access these methods. 049 */ 050public class CacheAccess<K, V> 051 extends AbstractCacheAccess<K, V> 052 implements ICacheAccess<K, V> 053{ 054 /** The logger. */ 055 private static final Log log = LogFactory.getLog( CacheAccess.class ); 056 057 /** 058 * Constructor for the CacheAccess object. 059 * <p> 060 * @param cacheControl The cache which the created instance accesses 061 */ 062 public CacheAccess( CompositeCache<K, V> cacheControl ) 063 { 064 super(cacheControl); 065 } 066 067 /** 068 * Retrieve an object from the cache region this instance provides access to. 069 * <p> 070 * @param name Key the object is stored as 071 * @return The object if found or null 072 */ 073 @Override 074 public V get( K name ) 075 { 076 ICacheElement<K, V> element = this.getCacheControl().get( name ); 077 078 return ( element != null ) ? element.getVal() : null; 079 } 080 081 /** 082 * Retrieve matching objects from the cache region this instance provides access to. 083 * <p> 084 * @param pattern - a key pattern for the objects stored 085 * @return A map of key to values. These are stripped from the wrapper. 086 */ 087 @Override 088 public Map<K, V> getMatching( String pattern ) 089 { 090 HashMap<K, V> unwrappedResults = new HashMap<K, V>(); 091 092 Map<K, ICacheElement<K, V>> wrappedResults = this.getCacheControl().getMatching( pattern ); 093 if ( wrappedResults != null ) 094 { 095 for (Map.Entry<K, ICacheElement<K, V>> entry : wrappedResults.entrySet()) 096 { 097 ICacheElement<K, V> element = entry.getValue(); 098 if ( element != null ) 099 { 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}