1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.module.cache.executor;
35
36 import info.magnolia.cms.core.Content;
37 import info.magnolia.context.MgnlContext;
38 import info.magnolia.jcr.util.NodeUtil;
39 import info.magnolia.module.ModuleRegistry;
40 import info.magnolia.module.cache.Cache;
41 import info.magnolia.module.cache.CacheModule;
42 import info.magnolia.module.cache.CachePolicy;
43 import info.magnolia.module.cache.CachePolicyResult;
44 import info.magnolia.module.cache.filter.CacheResponseWrapper;
45 import info.magnolia.module.cache.filter.CachedEntry;
46 import info.magnolia.module.cache.filter.CachedError;
47 import info.magnolia.module.cache.filter.CachedRedirect;
48 import info.magnolia.module.cache.filter.ContentCachedEntry;
49 import info.magnolia.module.cache.filter.DelegatingBlobCachedEntry;
50 import info.magnolia.module.cache.filter.InMemoryCachedEntry;
51 import info.magnolia.objectfactory.Components;
52
53 import java.io.IOException;
54
55 import javax.inject.Inject;
56 import javax.jcr.Node;
57 import javax.jcr.RepositoryException;
58 import javax.servlet.FilterChain;
59 import javax.servlet.ServletException;
60 import javax.servlet.http.HttpServletRequest;
61 import javax.servlet.http.HttpServletResponse;
62
63
64
65
66
67
68
69 public class Store extends AbstractExecutor {
70
71 private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(Store.class);
72 private final CacheModule cacheModule;
73
74
75
76
77 public Store() {
78 this.cacheModule = Components.getComponent(ModuleRegistry.class).getModuleInstance(CacheModule.class);
79 }
80
81 @Inject
82 public Store(CacheModule cacheModule) {
83 this.cacheModule = cacheModule;
84 }
85
86 @Override
87 public void processCacheRequest(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Cache cache, CachePolicyResult cachePolicyResult) throws IOException, ServletException {
88 CachedEntry cachedEntry = null;
89 final Object key = cachePolicyResult.getCacheKey();
90
91 final CacheResponseWrapper responseWrapper = new CacheResponseWrapper(response, CacheResponseWrapper.DEFAULT_THRESHOLD, false);
92 responseWrapper.setResponseExpirationDetectionEnabled();
93
94
95 final long cacheStorageDate = System.currentTimeMillis();
96 responseWrapper.setDateHeader("Last-Modified", cacheStorageDate);
97
98 try {
99 chain.doFilter(request, responseWrapper);
100 if (responseWrapper.getStatus() == HttpServletResponse.SC_NOT_MODIFIED) {
101 response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
102 }
103 else {
104 responseWrapper.flushBuffer();
105 cachedEntry = makeCachedEntry(request, responseWrapper);
106 }
107
108 } catch (IOException e) {
109 responseWrapper.cleanUp();
110 throw e;
111 } catch (ServletException e) {
112 responseWrapper.cleanUp();
113 throw e;
114 } catch (Throwable e) {
115 responseWrapper.cleanUp();
116 throw new RuntimeException("Failed to process request with: " + e.getMessage(), e);
117 }
118
119 if (cachedEntry == null) {
120
121 cache.put(key, null);
122 return;
123 }
124
125 int timeToLiveInSeconds = cachedEntry.getTimeToLiveInSeconds();
126 if (timeToLiveInSeconds == 0) {
127
128 cache.put(key, null);
129
130
131 cachedEntry.replay(request, response, chain);
132 response.flushBuffer();
133
134 return;
135 }
136
137
138 cachePolicyResult.setCachedEntry(cachedEntry);
139
140 if (timeToLiveInSeconds == -1) {
141 cache.put(key, cachedEntry);
142 } else {
143 cache.put(key, cachedEntry, timeToLiveInSeconds);
144 }
145
146
147 final Content mainContent = MgnlContext.getAggregationState().getMainContent();
148 final Node content = mainContent != null ? mainContent.getJCRNode() : null;
149 try {
150 if (content != null && NodeUtil.isNodeType(content, "mix:referenceable")) {
151 final String uuid = content.getIdentifier();
152 String repo = content.getSession().getWorkspace().getName();
153 getCachePolicy(cache).persistCacheKey(repo, uuid, key);
154 }
155 } catch (RepositoryException e) {
156
157 responseWrapper.cleanUp();
158 throw new RuntimeException(e);
159 }
160 }
161
162 protected CachedEntry makeCachedEntry(HttpServletRequest request, CacheResponseWrapper cachedResponse) throws IOException {
163
164 final String originalUrl = request.getRequestURL().toString();
165 int status = cachedResponse.getStatus();
166 int timeToLiveInSeconds = cachedResponse.getTimeToLiveInSeconds();
167
168
169 if (cachedResponse.getRedirectionLocation() != null) {
170 return new CachedRedirect(cachedResponse.getStatus(), cachedResponse.getRedirectionLocation(), originalUrl, timeToLiveInSeconds);
171 }
172
173 if (cachedResponse.isError()) {
174 return new CachedError(cachedResponse.getStatus(), originalUrl, timeToLiveInSeconds);
175 }
176
177 final long modificationDate = cachedResponse.getLastModified();
178 final String contentType = cachedResponse.getContentType();
179
180 ContentCachedEntry cacheEntry;
181 if (!cachedResponse.isThresholdExceeded()) {
182 cacheEntry = new InMemoryCachedEntry(cachedResponse.getBufferedContent(),
183 contentType,
184 cachedResponse.getCharacterEncoding(),
185 status,
186 cachedResponse.getHeaders(),
187 modificationDate,
188 originalUrl,
189 timeToLiveInSeconds);
190 }
191 else {
192 cacheEntry = new DelegatingBlobCachedEntry(cachedResponse.getContentLength(),
193 contentType,
194 cachedResponse.getCharacterEncoding(),
195 status,
196 cachedResponse.getHeaders(),
197 modificationDate,
198 originalUrl,
199 timeToLiveInSeconds);
200
201
202
203 ((DelegatingBlobCachedEntry) cacheEntry).bindContentFileToCurrentRequest(request, cachedResponse.getContentFile());
204 cachedResponse.getThresholdingOutputStream().close();
205 }
206
207 return cacheEntry;
208 }
209
210 protected CachePolicy getCachePolicy(Cache cache) {
211 return cacheModule.getConfiguration(cache.getName()).getCachePolicy();
212 }
213
214
215
216
217 @Deprecated
218 protected CacheModule getModule() {
219 return cacheModule;
220 }
221 }