Coverage Report - org.apache.commons.cache.FileStash
 
Classes in this File Line Coverage Branch Coverage Complexity
FileStash
0%
0/216
0%
0/70
3.714
 
 1  
 /*
 2  
  * Copyright 2001-2004 The Apache Software Foundation
 3  
  *
 4  
  * Licensed under the Apache License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  *     http://www.apache.org/licenses/LICENSE-2.0
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 package org.apache.commons.cache;
 17  
 
 18  
 import java.util.HashMap;
 19  
 import java.util.Iterator;
 20  
 import java.util.ArrayList;
 21  
 import java.util.StringTokenizer;
 22  
 import java.io.ByteArrayOutputStream;
 23  
 import java.io.ObjectOutputStream;
 24  
 import java.io.ObjectInputStream;
 25  
 import java.io.FileOutputStream;
 26  
 import java.io.FileInputStream;
 27  
 import java.io.BufferedInputStream;
 28  
 import java.io.BufferedOutputStream;
 29  
 import java.io.Serializable;
 30  
 import java.io.IOException;
 31  
 import java.io.File;
 32  
 
 33  
 /**
 34  
  * tk.
 35  
  * @version $Id: FileStash.java 155435 2005-02-26 13:17:27Z dirkv $
 36  
  * @author Rodney Waldhoff
 37  
  */
 38  
 public class FileStash extends BaseStash implements Stash {
 39  
   public transient static final long DEFAULT_MAX_OBJS;
 40  
   static {
 41  0
     int defaultMaxObjs = -1;
 42  
     try {
 43  0
       defaultMaxObjs = Integer.parseInt(System.getProperty("org.apache.commons.cache.FileStash.max-objs","-1"));
 44  0
     } catch(Exception e) {
 45  0
       defaultMaxObjs = -1;
 46  0
     }
 47  0
     DEFAULT_MAX_OBJS = defaultMaxObjs;
 48  
   }
 49  
 
 50  
   public transient static final long DEFAULT_MAX_BYTES;
 51  
   static {
 52  0
     int defaultMaxBytes = -1;
 53  
     try {
 54  0
       defaultMaxBytes = Integer.parseInt(System.getProperty("org.apache.commons.cache.FileStash.max-bytes","-1"));
 55  0
     } catch(Exception e) {
 56  0
       defaultMaxBytes = -1;
 57  0
     }
 58  0
     DEFAULT_MAX_BYTES = defaultMaxBytes;
 59  
   }
 60  
 
 61  
   public transient static final File[] DEFAULT_TEMP_DIRS;
 62  
   static {
 63  0
     ArrayList v = new ArrayList();
 64  0
     String rootdirstr = System.getProperty("org.apache.commons.cache.FileStash.root-cache-dir");
 65  0
     File rootdir = null;
 66  0
     if(null == rootdir) {
 67  0
       DEFAULT_TEMP_DIRS = null;
 68  
     } else {
 69  0
       rootdir = new File(rootdirstr);
 70  0
       int branchingFactor = 10;
 71  
       try {
 72  0
         branchingFactor = Integer.parseInt(System.getProperty("org.apache.commons.cache.FileStash.num-cache-dirs","10"));
 73  0
       } catch(Exception e) {
 74  0
         branchingFactor = 10;
 75  0
       }
 76  0
       if(branchingFactor < 0) {
 77  0
         branchingFactor = 10;
 78  0
       } else if(branchingFactor==0) {
 79  0
         v.add(rootdir);
 80  
       } else {
 81  0
         for(int i=0;i<branchingFactor;i++) {
 82  0
           v.add(new File(rootdir,String.valueOf(i)));
 83  
         }
 84  
       }
 85  0
       DEFAULT_TEMP_DIRS = (File[])(v.toArray(new File[0]));
 86  
     }
 87  
   }
 88  
 
 89  
   public transient static final String DEFAULT_FILE_PREFIX;
 90  
   static {
 91  0
     DEFAULT_FILE_PREFIX = System.getProperty("org.apache.commons.cached.FileStash.default-file-prefix","cache");
 92  
   }
 93  
 
 94  
 
 95  
   public transient static final String DEFAULT_FILE_SUFFIX;
 96  
   static {
 97  0
     DEFAULT_FILE_SUFFIX = System.getProperty("org.apache.commons.cache.FileStash.default-file-suffix",".ser");
 98  0
   }
 99  
 
 100  0
   protected HashMap _hash = null;
 101  0
   protected long _maxObjs = DEFAULT_MAX_OBJS;
 102  0
   protected long _maxBytes = DEFAULT_MAX_BYTES;
 103  0
   protected Cache _cache = null;
 104  0
   protected long _curBytes = 0;
 105  0
   protected File[] _tempFileDirs = null;
 106  0
   protected String _tempFilePrefix = DEFAULT_FILE_PREFIX;
 107  0
   protected String _tempFileSuffix = DEFAULT_FILE_SUFFIX;
 108  0
   protected boolean _cleanupfiles = false;
 109  
 
 110  
   public FileStash() {
 111  0
     this(DEFAULT_MAX_BYTES,DEFAULT_MAX_OBJS,DEFAULT_TEMP_DIRS,false);
 112  0
   }
 113  
 
 114  
   public FileStash(long maxbytes) {
 115  0
     this(maxbytes,DEFAULT_MAX_OBJS,DEFAULT_TEMP_DIRS,false);
 116  0
   }
 117  
 
 118  
   public FileStash(long maxbytes, long maxobjs) {
 119  0
     this(maxbytes,maxobjs,DEFAULT_TEMP_DIRS,false);
 120  0
   }
 121  
 
 122  0
   public FileStash(long maxbytes, long maxobjs, File[] tempdirs, boolean cleanup) {
 123  0
     _maxObjs = maxobjs;
 124  0
     _maxBytes = maxbytes;
 125  0
     _tempFileDirs = tempdirs;
 126  0
     _hash = new HashMap();
 127  0
     _cleanupfiles = cleanup;
 128  0
   }
 129  
 
 130  
   public FileStash(long maxbytes, long maxobjs, String rootdir, int numdirs) {
 131  0
     this(maxbytes,maxobjs,(null == rootdir ? ((File)null) : new File(rootdir)),numdirs,false);
 132  0
   }
 133  
 
 134  
   public FileStash(long maxbytes, long maxobjs, String rootdir, int numdirs, boolean cleanup) {
 135  0
     this(maxbytes,maxobjs,(null == rootdir ? ((File)null) : new File(rootdir)),numdirs,cleanup);
 136  0
   }
 137  
 
 138  
   public FileStash(long maxbytes, long maxobjs, File rootdir, int numdirs) {
 139  0
     this(maxbytes,maxobjs,rootdir,numdirs,false);
 140  0
   }
 141  
 
 142  0
   public FileStash(long maxbytes, long maxobjs, File rootdir, int numdirs, boolean cleanup) {
 143  0
     _maxObjs = maxobjs;
 144  0
     _maxBytes = maxbytes;
 145  0
     ArrayList v = new ArrayList();
 146  0
     if(null == rootdir) {
 147  0
       _tempFileDirs = null;
 148  
     } else {
 149  0
       if(numdirs < 0) {
 150  0
         numdirs = 10;
 151  0
       } else if(numdirs==0) {
 152  0
         v.add(rootdir);
 153  
       } else {
 154  0
         for(int i=0;i<numdirs;i++) {
 155  0
           v.add(new File(rootdir,String.valueOf(i)));
 156  
         }
 157  
       }
 158  0
       _tempFileDirs = (File[])(v.toArray(new File[0]));
 159  
     }
 160  0
     _cleanupfiles = cleanup;
 161  0
     _hash = new HashMap();
 162  0
   }
 163  
 
 164  
   protected byte[] getSerializedForm(Serializable val) {
 165  0
     byte[] serform = null;
 166  0
     if(null == val) { return null; }
 167  0
     ByteArrayOutputStream byout = null;
 168  0
     ObjectOutputStream out = null;
 169  
     try {
 170  0
       byout = new ByteArrayOutputStream();
 171  0
       out = new ObjectOutputStream(byout);
 172  0
       out.writeObject(val);
 173  0
       out.flush();
 174  0
       serform = byout.toByteArray();
 175  0
     } catch(IOException e) {
 176  0
       serform = null;
 177  
     } finally {
 178  0
       try { byout.close(); } catch(Exception e) { }
 179  0
       try { out.close(); } catch(Exception e) { }
 180  0
     }
 181  0
     return serform;
 182  
   }
 183  
 
 184  
   protected synchronized Serializable readFromFile(File file) {
 185  0
     ObjectInputStream oin = null;
 186  
     try {
 187  0
       oin = new ObjectInputStream(new BufferedInputStream(new FileInputStream(file)));
 188  0
       return (Serializable)(oin.readObject());
 189  0
     } catch(Exception e) {
 190  0
       return null;
 191  
     } finally {
 192  0
       try { oin.close(); } catch(Exception e) { }
 193  
     }
 194  
   }
 195  
 
 196  
   public synchronized int canStore(Serializable key, Serializable val, Long expiresAt, Long cost, Serializable group, byte[] serialized) {
 197  0
     if(null == serialized) {
 198  0
       serialized = getSerializedForm(val);
 199  
     }
 200  0
     if(null == serialized) {
 201  0
       return Stash.NO;
 202  0
     } else if(_maxBytes != -1 && serialized.length > _maxBytes) {
 203  0
       return Stash.NO_NOT_STORABLE;
 204  0
     } else if(_maxBytes != -1 && _curBytes + serialized.length > _maxBytes) {
 205  0
       return Stash.NO_FULL;
 206  0
     } else if(_maxObjs != -1 && _hash.size() > _maxObjs) {
 207  0
       return Stash.NO_FULL;
 208  
     } else {
 209  0
       return Stash.YES;
 210  
     }
 211  
   }
 212  
 
 213  0
   protected int _tempfileCounter = 0;
 214  
 
 215  
   protected File getTempfile() {
 216  0
     File cachefile = null;
 217  
     try {
 218  0
       File tempdir = null;
 219  0
       if(_tempFileDirs != null && _tempFileDirs.length > 0) {
 220  0
         tempdir = _tempFileDirs[_tempfileCounter++%_tempFileDirs.length];
 221  0
         if(!tempdir.exists()) {
 222  0
           if(_cleanupfiles) { tempdir.deleteOnExit(); }
 223  0
           tempdir.mkdirs();
 224  0
           tempdir.mkdir();
 225  
         }
 226  
       }
 227  0
       cachefile = File.createTempFile(_tempFilePrefix,_tempFileSuffix,tempdir);
 228  0
       if(_cleanupfiles) { cachefile.deleteOnExit(); }
 229  0
     } catch(Exception e) {
 230  0
       return null;
 231  0
     }
 232  0
     return cachefile;
 233  
   }
 234  
 
 235  
   public synchronized boolean store(Serializable key, Serializable val, Long expiresAt, Long cost, Serializable group, byte[] serialized) {
 236  0
     if(null == serialized) {
 237  0
       serialized = getSerializedForm(val);
 238  
     }
 239  0
     if(null == serialized) {
 240  0
       return false;
 241  
     }
 242  
 
 243  0
     File cachefile = getTempfile();
 244  0
     if(null == cachefile) {
 245  0
       return false;
 246  
     }
 247  
 
 248  0
     BufferedOutputStream fout = null;
 249  
     try {
 250  0
       fout = new BufferedOutputStream(new FileOutputStream(cachefile));
 251  0
       fout.write(serialized);
 252  0
       fout.flush();
 253  0
     } catch(Exception e) {
 254  0
       try { fout.close(); } catch(Exception ex) { }
 255  0
       fout = null;
 256  0
       try { cachefile.delete(); } catch(Exception ex) { }
 257  0
       return false;
 258  
     } finally {
 259  0
       try { fout.close(); } catch(Exception e) { }
 260  0
     }
 261  
 
 262  0
     Object oldobj = null;
 263  
     try {
 264  0
       oldobj = _hash.put(key,new CachedObjectInfoImpl(cachefile,expiresAt,new Long(serialized.length)));
 265  0
     } catch(Exception e) {
 266  0
       try { cachefile.delete(); } catch(Exception ex)  { }
 267  0
       return false;
 268  
     } finally {
 269  0
       if(null != oldobj && oldobj instanceof CachedObjectInfo) {
 270  0
         CachedObjectInfo oldcachedobj = (CachedObjectInfo)oldobj;
 271  
         try {
 272  0
           _curBytes -= oldcachedobj.getCost().longValue();
 273  0
         } catch(NullPointerException ex) {
 274  
           // ignored
 275  0
         }
 276  
         try {
 277  0
           File f = (File)(oldcachedobj.getKey());
 278  0
           f.delete();
 279  0
         } catch(Exception ex) {
 280  0
             ex.printStackTrace();
 281  
           // ignored
 282  0
         }
 283  0
       }
 284  
     }
 285  0
     _curBytes += serialized.length;
 286  0
     return true;
 287  
   }
 288  
 
 289  
   public Serializable retrieve(Serializable key) {
 290  
     // grab a lock on the cache first, since it may attempt to grab a lock on this
 291  0
     synchronized(_cache) {
 292  0
       synchronized(this) {
 293  0
         CachedObjectInfo info = (CachedObjectInfo)(_hash.get(key));
 294  0
         if(null != info) {
 295  0
           Long expiry = info.getExpirationTs();
 296  0
           if(null != expiry) {
 297  0
             if(expiry.longValue() < System.currentTimeMillis()) {
 298  0
               _cache.clear(key);
 299  0
               return null;
 300  
             } else {
 301  0
               return readFromFile((File)(info.getKey()));
 302  
             }
 303  
           } else {
 304  0
             return readFromFile((File)(info.getKey()));
 305  
           }
 306  
         } else {
 307  0
           return null;
 308  
         }
 309  0
       }
 310  0
     }
 311  
   }
 312  
 
 313  
   public synchronized boolean contains(Serializable key) {
 314  0
     return _hash.containsKey(key);
 315  
   }
 316  
 
 317  
   public synchronized float capacity() {
 318  0
     float objcount = 0;
 319  0
     if(_maxObjs > 0) {
 320  0
        objcount = (((float)_hash.size())/((float)_maxObjs));
 321  
     }
 322  0
     float bytecount = 0;
 323  0
     if(_maxBytes > 0) {
 324  0
       bytecount = (((float)_curBytes)/((float)_maxBytes));
 325  
     }
 326  0
     return (objcount > bytecount) ? objcount : bytecount;
 327  
   }
 328  
 
 329  
   public synchronized void clear(Serializable key) {
 330  0
     CachedObjectInfo obj = (CachedObjectInfo)(_hash.remove(key));
 331  0
     if(null != obj) {
 332  0
       _curBytes -= obj.getCost().longValue();
 333  0
       ((File)(obj.getKey())).delete();
 334  
     }
 335  0
   }
 336  
 
 337  
   public synchronized void clear() {
 338  0
     Iterator it = _hash.keySet().iterator();
 339  0
     while(it.hasNext()) {
 340  
       try {
 341  0
         CachedObjectInfo obj = (CachedObjectInfo)(it.next());
 342  0
         ((File)(obj.getKey())).delete();
 343  0
       } catch(Exception e) {
 344  0
           e.printStackTrace();
 345  
         // ignored
 346  0
       }
 347  
     }
 348  0
     _hash.clear();
 349  0
     _curBytes = 0;
 350  0
   }
 351  
 
 352  
   public void setCache(Cache c) {
 353  0
     if(null != _cache) {
 354  0
       Object mutex = _cache;
 355  0
       synchronized(mutex) {
 356  0
         synchronized(this) {
 357  0
           unsetCache();
 358  0
           _cache = c;
 359  0
         }
 360  0
       }
 361  0
     } else {
 362  0
       _cache = c;
 363  
     }
 364  0
   }
 365  
 
 366  
   public void unsetCache() {
 367  0
     if(null != _cache) {
 368  0
       Object mutex = _cache;
 369  0
       synchronized(mutex) {
 370  0
         clear();
 371  0
         _cache = null;
 372  0
       }
 373  
     }
 374  0
   }
 375  
 
 376  
   public boolean wantsSerializedForm() {
 377  0
     return true;
 378  
   }
 379  
 }