Mercurial Hosting > nabble
diff src/cachingfilter/CachingFilter.java @ 0:7ecd1a4ef557
add content
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Thu, 21 Mar 2019 19:15:52 -0600 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/cachingfilter/CachingFilter.java Thu Mar 21 19:15:52 2019 -0600 @@ -0,0 +1,147 @@ +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; + } + +}