1 24 package org.riotfamily.cachius; 25 26 import java.io.BufferedInputStream ; 27 import java.io.BufferedReader ; 28 import java.io.File ; 29 import java.io.FileInputStream ; 30 import java.io.FileNotFoundException ; 31 import java.io.IOException ; 32 import java.io.InputStream ; 33 import java.io.InputStreamReader ; 34 import java.io.ObjectInputStream ; 35 import java.io.Reader ; 36 import java.io.Serializable ; 37 import java.io.Writer ; 38 import java.util.Arrays ; 39 40 import javax.servlet.ServletResponse ; 41 import javax.servlet.http.HttpServletRequest ; 42 43 import org.apache.commons.logging.Log; 44 import org.apache.commons.logging.LogFactory; 45 import org.riotfamily.cachius.support.ReaderWriterLock; 46 import org.riotfamily.cachius.support.TokenFilterWriter; 47 import org.riotfamily.common.io.IOUtils; 48 49 50 67 public class CacheItem implements Serializable { 68 69 private static final String ITEM_PREFIX = "item"; 70 71 private static final String TEMP_PREFIX = "tmp"; 72 73 private static final String TEMPFILE_SUFFIX = ""; 74 75 private static final long NOT_YET = -1L; 76 77 private static final String FILE_ENCODING = "UTF-8"; 78 79 private Log log = LogFactory.getLog(CacheItem.class); 80 81 82 private transient CacheItem previous; 83 84 85 private transient CacheItem next; 86 87 88 private String key; 89 90 91 private String [] tags; 92 93 94 private boolean filterSessionId; 95 96 97 private File file = null; 98 99 100 private String contentType = null; 101 102 106 private boolean binary = true; 107 108 112 private transient ReaderWriterLock lock = new ReaderWriterLock(); 113 114 117 private long lastModified; 118 119 122 private long lastCheck; 123 124 public CacheItem(String key, File cacheDir) throws IOException { 125 this.key = key; 126 file = File.createTempFile(ITEM_PREFIX, TEMPFILE_SUFFIX, cacheDir); 127 lastModified = NOT_YET; 128 } 129 130 public String getKey() { 131 return key; 132 } 133 134 public void setKey(String key) { 135 this.key = key; 136 } 137 138 public void setTags(String [] tags) { 139 if (tags != null) { 140 Arrays.sort(tags); 141 } 142 this.tags = tags; 143 } 144 145 public String [] getTags() { 146 return tags; 147 } 148 149 public boolean hasTag(String tag) { 150 return tags != null && Arrays.binarySearch(tags, tag) >= 0; 151 } 152 153 public CacheItem getPrevious() { 154 return previous; 155 } 156 157 158 public void setPrevious(CacheItem previous) { 159 this.previous = previous; 160 } 161 162 public CacheItem getNext() { 163 return next; 164 } 165 166 public void setNext(CacheItem next) { 167 this.next = next; 168 } 169 170 public int hashCode() { 171 return key.hashCode(); 172 } 173 174 public boolean isFilterSessionId() { 175 return filterSessionId; 176 } 177 178 public void setFilterSessionId(boolean filterSessionId) { 179 this.filterSessionId = filterSessionId; 180 } 181 182 public void setContentType(String contentType) { 183 this.contentType = contentType; 184 } 185 186 public String getContentType() { 187 return contentType; 188 } 189 190 public long getLastModified() { 191 return lastModified; 192 } 193 194 public void setLastModified(long lastModified) { 195 this.lastModified = lastModified; 196 } 197 198 public long getLastCheck() { 199 return this.lastCheck; 200 } 201 202 public void setLastCheck(long lastCheck) { 203 this.lastCheck = lastCheck; 204 } 205 206 public boolean isNew() { 207 return lastModified == NOT_YET; 208 } 209 210 213 public boolean exists() { 214 return file != null && file.isFile(); 215 } 216 217 public File createTempFile() throws IOException { 218 File dir = file.getParentFile(); 219 dir.mkdirs(); 220 return File.createTempFile(TEMP_PREFIX, TEMPFILE_SUFFIX, dir); 221 } 222 223 public void update(File tempFile, boolean binary) { 224 log.debug("Updating cached version of " + key); 225 try { 226 lock.lockForWriting(); 227 lastModified = System.currentTimeMillis(); 228 delete(); 229 IOUtils.move(tempFile, file); 230 this.binary = binary; 231 } 232 finally { 233 lock.releaseWriterLock(); 234 } 235 } 236 237 public void writeTo(HttpServletRequest request, 238 ServletResponse response) throws IOException { 239 240 log.debug("Serving cached version of " + key); 241 try { 242 lock.lockForReading(); 243 if (contentType != null) { 244 response.setContentType(contentType); 245 } 246 247 if (binary) { 248 InputStream in = new BufferedInputStream ( 249 new FileInputStream (file)); 250 251 IOUtils.copy(in, response.getOutputStream()); 252 } 253 else { 254 Reader in = new BufferedReader (new InputStreamReader ( 255 new FileInputStream (file), FILE_ENCODING)); 256 257 Writer out = response.getWriter(); 258 if (filterSessionId) { 259 out = new TokenFilterWriter("${jsessionid}", 260 request.getSession().getId(), out); 261 } 262 263 IOUtils.copy(in, out); 264 } 265 } 266 catch (FileNotFoundException e) { 267 log.warn("Cache file not found. Resetting modification time " + 268 "to trigger update on next request."); 269 270 lastModified = NOT_YET; 271 } 272 finally { 273 lock.releaseReaderLock(); 274 } 275 } 276 277 public void invalidate() { 278 lastModified = NOT_YET; 279 delete(); 280 } 281 282 public void delete() { 283 if (file.exists()) { 284 if (!file.delete()) { 285 log.warn("Failed to delete cache file: " + file); 286 } 287 } 288 } 289 290 293 private void readObject(ObjectInputStream in) throws IOException , 294 ClassNotFoundException { 295 296 in.defaultReadObject(); 297 lock = new ReaderWriterLock(); 298 } 299 300 } 301 | Popular Tags |