comparison 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
comparison
equal deleted inserted replaced
-1:000000000000 0:7ecd1a4ef557
1 package cachingfilter;
2
3 import java.io.File;
4 import java.io.FileFilter;
5 import java.io.FilenameFilter;
6 import java.io.IOException;
7 import java.io.ObjectInputStream;
8 import java.io.BufferedInputStream;
9 import java.io.FileInputStream;
10 import java.io.BufferedOutputStream;
11 import java.io.FileOutputStream;
12 import java.io.ObjectOutputStream;
13 import java.util.Set;
14 import java.util.HashSet;
15 import java.util.concurrent.CopyOnWriteArraySet;
16 import java.util.concurrent.Executors;
17 import java.util.concurrent.ScheduledExecutorService;
18 import java.util.concurrent.TimeUnit;
19 import javax.servlet.Filter;
20 import javax.servlet.FilterChain;
21 import javax.servlet.FilterConfig;
22 import javax.servlet.ServletException;
23 import javax.servlet.ServletRequest;
24 import javax.servlet.ServletResponse;
25 import javax.servlet.http.HttpServletRequest;
26 import javax.servlet.http.HttpServletResponse;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
29
30
31 public final class CachingFilter implements Filter {
32 private static final Logger logger = LoggerFactory.getLogger(CachingFilter.class);
33
34 static final Locker<String> locker = new Locker<String>();
35
36 // private static final long sweepFreqSeconds = 60*60*24;
37 // private static final long expiryPeriodMillis = 1000L*60*60*24*10;
38 private static final long sweepFreqSeconds = 60*60;
39 private static final long expiryPeriodMillis = 1000L*60*60*24;
40
41 static final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
42
43 private File dir;
44 private boolean hasDelayedDelete;
45 private final Set<String> encodings = new HashSet<String>();
46
47 public void init(FilterConfig filterConfig)
48 throws ServletException
49 {
50 String dirS = filterConfig.getInitParameter("dir");
51 if( dirS == null )
52 throw new ServletException("'dir' init parameter must be set");
53 dir = new File(dirS);
54 dir.mkdirs();
55
56 String acceptEncoding = filterConfig.getInitParameter("acceptEncoding");
57 if( acceptEncoding == null )
58 throw new ServletException("'acceptEncoding' init parameter must be set");
59 for( String encoding : acceptEncoding.split(",") ) {
60 encoding = encoding.trim();
61 if( encoding.length() > 0 )
62 encodings.add(encoding);
63 }
64
65 String hasDelayedDeleteS = filterConfig.getInitParameter("hasDelayedDelete");
66 if( hasDelayedDeleteS == null )
67 throw new ServletException("'hasDelayedDelete' init parameter must be set");
68 hasDelayedDelete = Boolean.parseBoolean(hasDelayedDeleteS);
69
70 Runnable sweeper = new Runnable() {
71 public void run() {
72 try {
73 logger.error("starting sweep");
74 final int[] total = new int[1];
75 final long expired = System.currentTimeMillis() - expiryPeriodMillis;
76 File[] files = dir.listFiles(new FileFilter(){
77 public boolean accept(File file) {
78 total[0]++;
79 return file.lastModified() < expired && file.getName().charAt(0) != '~';
80 }
81 });
82 int n = 0;
83 for( File file : files ) {
84 String name = file.getName();
85 locker.lock(name);
86 try {
87 if( newCachedPage(name).delete() )
88 n++;
89 } finally {
90 locker.unlock(name);
91 }
92 }
93 logger.error("finished sweep, deleted "+n+" pages out of "+files.length+" candidates, "+total[0]+" total");
94 } catch(RuntimeException e) {
95 logger.error("exception in sweeper",e);
96 throw e;
97 } catch(Error e) {
98 logger.error("error in sweeper",e);
99 System.exit(-1);
100 }
101 }
102 };
103 executor.scheduleWithFixedDelay( sweeper, sweepFreqSeconds, sweepFreqSeconds, TimeUnit.SECONDS );
104 }
105
106 public void destroy() {}
107
108 public static void shutdown() {}
109
110 CachedPage newCachedPage(String name) {
111 if( name.length() == 0 )
112 throw new RuntimeException("empty filenames not allowed");
113 if( name.charAt(0) == '~' )
114 throw new RuntimeException("invalid filename: "+name);
115 return hasDelayedDelete ? new CachedFile(dir,name) : new CachedDir(dir,name);
116 }
117
118 public void doFilter(
119 ServletRequest req,
120 ServletResponse res,
121 FilterChain chain
122 )
123 throws IOException, ServletException
124 {
125 HttpServletRequest request = (HttpServletRequest)req;
126 HttpServletResponse response = (HttpServletResponse)res;
127 if( !"GET".equals( request.getMethod() ) ) {
128 chain.doFilter(request,response);
129 return;
130 }
131 CachingRequestWrapper wrappedRequest = new CachingRequestWrapper(request);
132 CachingResponseWrapper wrappedResponse = new CachingResponseWrapper(this,wrappedRequest,response);
133 boolean isDone = false;
134 try {
135 chain.doFilter(wrappedRequest,wrappedResponse);
136 isDone = true;
137 } finally {
138 wrappedResponse.finish(isDone);
139 }
140
141 }
142
143 public Set<String> getEncodings() {
144 return encodings;
145 }
146
147 }