1 16 package org.apache.cocoon.components.store.impl; 17 18 import java.io.File ; 19 import java.io.IOException ; 20 import java.io.Serializable ; 21 import java.net.URL ; 22 import java.util.Collections ; 23 import java.util.Enumeration ; 24 import java.util.List ; 25 26 import net.sf.ehcache.Cache; 27 import net.sf.ehcache.CacheException; 28 import net.sf.ehcache.CacheManager; 29 import net.sf.ehcache.Element; 30 31 import org.apache.cocoon.Constants; 32 import org.apache.cocoon.util.IOUtils; 33 34 import org.apache.avalon.framework.activity.Disposable; 35 import org.apache.avalon.framework.activity.Initializable; 36 import org.apache.avalon.framework.context.Context; 37 import org.apache.avalon.framework.context.ContextException; 38 import org.apache.avalon.framework.context.Contextualizable; 39 import org.apache.avalon.framework.logger.AbstractLogEnabled; 40 import org.apache.avalon.framework.parameters.ParameterException; 41 import org.apache.avalon.framework.parameters.Parameterizable; 42 import org.apache.avalon.framework.parameters.Parameters; 43 import org.apache.avalon.framework.service.ServiceException; 44 import org.apache.avalon.framework.service.ServiceManager; 45 import org.apache.avalon.framework.service.Serviceable; 46 import org.apache.avalon.framework.thread.ThreadSafe; 47 import org.apache.excalibur.store.Store; 48 import org.apache.excalibur.store.StoreJanitor; 49 50 54 public class EHDefaultStore extends AbstractLogEnabled 55 implements Store, Contextualizable, Serviceable, Parameterizable, Initializable, Disposable, ThreadSafe { 56 57 59 private static final String CONFIG_FILE = "org/apache/cocoon/components/store/impl/ehcache.xml"; 60 61 private static int instanceCount = 0; 62 63 65 private Cache cache; 66 private CacheManager cacheManager; 67 68 private final String cacheName; 69 70 private int maxObjects; 72 private boolean overflowToDisk; 73 74 75 private ServiceManager manager; 76 77 78 private StoreJanitor storeJanitor; 79 80 private File workDir; 81 private File cacheDir; 82 83 85 public EHDefaultStore() { 86 instanceCount++; 87 this.cacheName = "cocoon-ehcache-" + instanceCount; 88 } 89 90 93 public void contextualize(Context context) throws ContextException { 94 this.workDir = (File )context.get(Constants.CONTEXT_WORK_DIR); 95 this.cacheDir = (File )context.get(Constants.CONTEXT_CACHE_DIR); 96 } 97 98 101 public void service(ServiceManager aManager) throws ServiceException { 102 this.manager = aManager; 103 this.storeJanitor = (StoreJanitor) this.manager.lookup(StoreJanitor.ROLE); 104 } 105 106 121 public void parameterize(Parameters parameters) throws ParameterException { 122 123 this.maxObjects = parameters.getParameterAsInteger("maxobjects", 10000); 124 this.overflowToDisk = parameters.getParameterAsBoolean("overflow-to-disk", true); 125 126 try { 127 if (parameters.getParameterAsBoolean("use-cache-directory", false)) { 128 if (this.getLogger().isDebugEnabled()) { 129 getLogger().debug("Using cache directory: " + cacheDir); 130 } 131 setDirectory(cacheDir); 132 } 133 else if (parameters.getParameterAsBoolean("use-work-directory", false)) { 134 if (this.getLogger().isDebugEnabled()) { 135 getLogger().debug("Using work directory: " + workDir); 136 } 137 setDirectory(workDir); 138 } 139 else if (parameters.getParameter("directory", null) != null) { 140 String dir = parameters.getParameter("directory"); 141 dir = IOUtils.getContextFilePath(workDir.getPath(), dir); 142 if (this.getLogger().isDebugEnabled()) { 143 getLogger().debug("Using directory: " + dir); 144 } 145 setDirectory(new File (dir)); 146 } 147 else { 148 try { 149 setDirectory(workDir); 151 } catch (IOException e) { 152 } 153 } 154 } catch (IOException e) { 155 throw new ParameterException("Unable to set directory", e); 156 } 157 158 } 159 160 163 private void setDirectory(final File directory) throws IOException { 164 165 166 String directoryPath = getFullFilename(directory); 167 directoryPath += File.separator; 168 169 170 if (!directory.exists()) { 171 if (!directory.mkdir()) { 172 throw new IOException ("Error creating store directory '" + directoryPath + "': "); 173 } 174 } 175 176 177 if (!directory.isDirectory()) { 178 throw new IOException ("'" + directoryPath + "' is not a directory"); 179 } 180 181 182 if (!(directory.canRead() && directory.canWrite())) { 183 throw new IOException ("Directory '" + directoryPath + "' is not readable/writable"); 184 } 185 186 System.setProperty("java.io.tmpdir", directoryPath); 187 } 188 189 199 private static String getFullFilename(File file) { 200 try { 201 return file.getCanonicalPath(); 202 } 203 catch (Exception e) { 204 return file.getAbsolutePath(); 205 } 206 } 207 208 211 public void initialize() throws Exception { 212 URL configFileURL = Thread.currentThread().getContextClassLoader().getResource(CONFIG_FILE); 213 this.cacheManager = CacheManager.create(configFileURL); 214 this.cache = new Cache(this.cacheName, this.maxObjects, this.overflowToDisk, true, 0, 0, true, 120); 215 this.cacheManager.addCache(this.cache); 216 this.storeJanitor.register(this); 217 } 218 219 222 public void dispose() { 223 if (this.storeJanitor != null) { 224 this.storeJanitor.unregister(this); 225 this.manager.release(this.storeJanitor); 226 this.storeJanitor = null; 227 } 228 this.manager = null; 229 this.cacheManager.shutdown(); 230 this.cacheManager = null; 231 this.cache = null; 232 } 233 234 236 239 public Object get(Object key) { 240 Object value = null; 241 try { 242 final Element element = this.cache.get((Serializable ) key); 243 if (element != null) { 244 value = element.getValue(); 245 } 246 } 247 catch (CacheException e) { 248 getLogger().error("Failure retrieving object from store", e); 249 } 250 if (getLogger().isDebugEnabled()) { 251 if (value != null) { 252 getLogger().debug("Found key: " + key); 253 } 254 else { 255 getLogger().debug("NOT Found key: " + key); 256 } 257 } 258 return value; 259 } 260 261 264 public void store(Object key, Object value) throws IOException { 265 if (getLogger().isDebugEnabled()) { 266 getLogger().debug("Store object " + value + " with key "+ key); 267 } 268 269 if(!(key instanceof Serializable )) { 271 throw new IOException ("Key of class " + key.getClass().getName() + " is not Serializable"); 272 } 273 if(!(value instanceof Serializable )) { 274 throw new IOException ("Value of class " + value.getClass().getName() + " is not Serializable"); 275 } 276 277 final Element element = new Element((Serializable ) key, (Serializable ) value); 278 this.cache.put(element); 279 } 280 281 284 public void free() { 285 try { 286 final List keys = this.cache.getKeysNoDuplicateCheck(); 287 if (!keys.isEmpty()) { 288 final Serializable key = (Serializable ) keys.get(0); 290 if (getLogger().isDebugEnabled()) { 291 getLogger().debug("Freeing cache"); 292 getLogger().debug("key: " + key); 293 getLogger().debug("value: " + this.cache.get(key)); 294 } 295 if (!this.cache.remove(key)) { 296 if (getLogger().isInfoEnabled()) { 297 getLogger().info("Concurrency condition in free()"); 298 } 299 } 300 } 301 } 302 catch (CacheException e) { 303 if (getLogger().isWarnEnabled()) { 304 getLogger().warn("Error in free()", e); 305 } 306 } 307 } 308 309 312 public void remove(Object key) { 313 if (getLogger().isDebugEnabled()) { 314 getLogger().debug("Removing item " + key); 315 } 316 this.cache.remove((Serializable ) key); 317 } 318 319 322 public void clear() { 323 if (getLogger().isDebugEnabled()) { 324 getLogger().debug("Clearing the store"); 325 } 326 try { 327 this.cache.removeAll(); 328 } 329 catch (IOException e) { 330 getLogger().error("Failure to clearing store", e); 331 } 332 } 333 334 337 public boolean containsKey(Object key) { 338 try { 339 return this.cache.get((Serializable ) key) != null; 340 } 341 catch (CacheException e) { 342 getLogger().error("Failure retrieving object from store",e); 343 } 344 return false; 345 } 346 347 350 public Enumeration keys() { 351 List keys = null; 352 try { 353 keys = this.cache.getKeys(); 354 } 355 catch (CacheException e) { 356 if (getLogger().isWarnEnabled()) { 357 getLogger().warn("Error while getting cache keys", e); 358 } 359 keys = Collections.EMPTY_LIST; 360 } 361 return Collections.enumeration(keys); 362 } 363 364 367 public int size() { 368 try { 369 return this.cache.getSize(); 370 } 371 catch (CacheException e) { 372 if (getLogger().isWarnEnabled()) { 373 getLogger().warn("Error while getting cache size", e); 374 } 375 return 0; 376 } 377 } 378 379 } 380 | Popular Tags |