Mercurial Hosting > nabble
view src/cachingfilter/CachingFilter.java @ 65:3d7067a23eff
fix
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Tue, 17 Sep 2024 05:01:59 -0600 |
parents | 7ecd1a4ef557 |
children |
line wrap: on
line source
package cachingfilter; import java.io.File; import java.io.FileFilter; import java.io.FilenameFilter; import java.io.IOException; import java.io.ObjectInputStream; import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.BufferedOutputStream; import java.io.FileOutputStream; import java.io.ObjectOutputStream; import java.util.Set; import java.util.HashSet; import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public final class CachingFilter implements Filter { private static final Logger logger = LoggerFactory.getLogger(CachingFilter.class); static final Locker<String> locker = new Locker<String>(); // private static final long sweepFreqSeconds = 60*60*24; // private static final long expiryPeriodMillis = 1000L*60*60*24*10; private static final long sweepFreqSeconds = 60*60; private static final long expiryPeriodMillis = 1000L*60*60*24; static final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); private File dir; private boolean hasDelayedDelete; private final Set<String> encodings = new HashSet<String>(); public void init(FilterConfig filterConfig) throws ServletException { String dirS = filterConfig.getInitParameter("dir"); if( dirS == null ) throw new ServletException("'dir' init parameter must be set"); dir = new File(dirS); dir.mkdirs(); String acceptEncoding = filterConfig.getInitParameter("acceptEncoding"); if( acceptEncoding == null ) throw new ServletException("'acceptEncoding' init parameter must be set"); for( String encoding : acceptEncoding.split(",") ) { encoding = encoding.trim(); if( encoding.length() > 0 ) encodings.add(encoding); } String hasDelayedDeleteS = filterConfig.getInitParameter("hasDelayedDelete"); if( hasDelayedDeleteS == null ) throw new ServletException("'hasDelayedDelete' init parameter must be set"); hasDelayedDelete = Boolean.parseBoolean(hasDelayedDeleteS); Runnable sweeper = new Runnable() { public void run() { try { logger.error("starting sweep"); final int[] total = new int[1]; final long expired = System.currentTimeMillis() - expiryPeriodMillis; File[] files = dir.listFiles(new FileFilter(){ public boolean accept(File file) { total[0]++; return file.lastModified() < expired && file.getName().charAt(0) != '~'; } }); int n = 0; for( File file : files ) { String name = file.getName(); locker.lock(name); try { if( newCachedPage(name).delete() ) n++; } finally { locker.unlock(name); } } logger.error("finished sweep, deleted "+n+" pages out of "+files.length+" candidates, "+total[0]+" total"); } catch(RuntimeException e) { logger.error("exception in sweeper",e); throw e; } catch(Error e) { logger.error("error in sweeper",e); System.exit(-1); } } }; executor.scheduleWithFixedDelay( sweeper, sweepFreqSeconds, sweepFreqSeconds, TimeUnit.SECONDS ); } public void destroy() {} public static void shutdown() {} CachedPage newCachedPage(String name) { if( name.length() == 0 ) throw new RuntimeException("empty filenames not allowed"); if( name.charAt(0) == '~' ) throw new RuntimeException("invalid filename: "+name); return hasDelayedDelete ? new CachedFile(dir,name) : new CachedDir(dir,name); } public void doFilter( ServletRequest req, ServletResponse res, FilterChain chain ) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest)req; HttpServletResponse response = (HttpServletResponse)res; if( !"GET".equals( request.getMethod() ) ) { chain.doFilter(request,response); return; } CachingRequestWrapper wrappedRequest = new CachingRequestWrapper(request); CachingResponseWrapper wrappedResponse = new CachingResponseWrapper(this,wrappedRequest,response); boolean isDone = false; try { chain.doFilter(wrappedRequest,wrappedResponse); isDone = true; } finally { wrappedResponse.finish(isDone); } } public Set<String> getEncodings() { return encodings; } }