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