Mercurial Hosting > nabble
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 } |