1 package com.atlassian.plugin.servlet.util;
2
3 import javax.servlet.http.HttpServletRequest;
4 import javax.servlet.http.HttpServletResponse;
5 import java.util.Date;
6
7
8
9
10 public class LastModifiedHandler {
11 private long lastModified;
12 private String etag;
13 private static final int ONE_SECOND_MILLIS = 1000;
14
15 public LastModifiedHandler() {
16 modified(new Date());
17 }
18
19 public LastModifiedHandler(Date lastModifiedDate) {
20 modified(lastModifiedDate);
21 }
22
23
24
25
26
27
28
29
30
31 public boolean checkRequest(HttpServletRequest request, HttpServletResponse response) {
32 return checkRequest(request, response, lastModified, etag);
33 }
34
35
36
37
38 public void modified() {
39 modified(new Date());
40 }
41
42 private void modified(Date date) {
43 lastModified = calculateLastModifiedDate(date);
44 etag = calculateEtag(lastModified);
45 }
46
47 private static long calculateLastModifiedDate(Date lastModifiedDate) {
48 long lastModified = lastModifiedDate.getTime();
49
50 lastModified -= lastModified % ONE_SECOND_MILLIS;
51 return lastModified;
52 }
53
54 private static String calculateEtag(long lastModified) {
55 return "\"" + lastModified + "\"";
56 }
57
58
59
60
61
62 public static boolean checkRequest(HttpServletRequest request, HttpServletResponse response, Date lastModifiedDate) {
63 long lastModified = calculateLastModifiedDate(lastModifiedDate);
64 return checkRequest(request, response, lastModified, calculateEtag(lastModified));
65 }
66
67 private static boolean checkRequest(HttpServletRequest request, HttpServletResponse response, long lastModified, String etagString) {
68 if ("true".equals(System.getProperty("atlassian.disable.caches", "false")))
69 return false;
70
71 response.setDateHeader("Last-Modified", lastModified);
72 response.setHeader("ETag", etagString);
73
74 long ifModifiedSince = request.getDateHeader("If-Modified-Since");
75 String ifNoneMatch = request.getHeader("If-None-Match");
76 if (noConditionalGetHeadersFound(ifModifiedSince, ifNoneMatch)
77 || isContentModifiedSince(ifModifiedSince, lastModified)
78 || !etagMatches(ifNoneMatch, etagString)) {
79 return false;
80 }
81 response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
82 return true;
83 }
84
85 private static boolean etagMatches(String ifNoneMatch, String etagString) {
86 return ifNoneMatch != null && ifNoneMatch.equals(etagString);
87 }
88
89 private static boolean isContentModifiedSince(long ifModifiedSince, long lastModified) {
90 return ifModifiedSince != -1 && ifModifiedSince < lastModified;
91 }
92
93 private static boolean noConditionalGetHeadersFound(long ifModifiedSince, String ifNoneMatch) {
94 return ifModifiedSince == -1 && ifNoneMatch == null;
95 }
96 }