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 package org.apache.http.impl.client.cache;
28
29 import java.io.IOException;
30 import java.util.Date;
31
32 import org.apache.http.Header;
33 import org.apache.http.HeaderIterator;
34 import org.apache.http.HttpResponse;
35 import org.apache.http.HttpStatus;
36 import org.apache.http.annotation.Contract;
37 import org.apache.http.annotation.ThreadingBehavior;
38 import org.apache.http.client.cache.HeaderConstants;
39 import org.apache.http.client.cache.HttpCacheEntry;
40 import org.apache.http.client.cache.Resource;
41 import org.apache.http.client.cache.ResourceFactory;
42 import org.apache.http.client.utils.DateUtils;
43 import org.apache.http.message.HeaderGroup;
44 import org.apache.http.protocol.HTTP;
45 import org.apache.http.util.Args;
46
47
48
49
50
51
52
53
54 @Contract(threading = ThreadingBehavior.IMMUTABLE_CONDITIONAL)
55 class CacheEntryUpdater {
56
57 private final ResourceFactory resourceFactory;
58
59 CacheEntryUpdater() {
60 this(new HeapResourceFactory());
61 }
62
63 CacheEntryUpdater(final ResourceFactory resourceFactory) {
64 super();
65 this.resourceFactory = resourceFactory;
66 }
67
68
69
70
71
72
73
74
75
76
77
78
79
80 public HttpCacheEntry updateCacheEntry(
81 final String requestId,
82 final HttpCacheEntry entry,
83 final Date requestDate,
84 final Date responseDate,
85 final HttpResponse response) throws IOException {
86 Args.check(response.getStatusLine().getStatusCode() == HttpStatus.SC_NOT_MODIFIED,
87 "Response must have 304 status code");
88 final Header[] mergedHeaders = mergeHeaders(entry, response);
89 Resource resource = null;
90 if (entry.getResource() != null) {
91 resource = resourceFactory.copy(requestId, entry.getResource());
92 }
93 return new HttpCacheEntry(
94 requestDate,
95 responseDate,
96 entry.getStatusLine(),
97 mergedHeaders,
98 resource,
99 entry.getRequestMethod());
100 }
101
102 protected Header[] mergeHeaders(final HttpCacheEntry entry, final HttpResponse response) {
103 if (entryAndResponseHaveDateHeader(entry, response)
104 && entryDateHeaderNewerThenResponse(entry, response)) {
105
106 return entry.getAllHeaders();
107 }
108
109 final HeaderGroup headerGroup = new HeaderGroup();
110 headerGroup.setHeaders(entry.getAllHeaders());
111
112 for (final HeaderIterator it = response.headerIterator(); it.hasNext(); ) {
113 final Header responseHeader = it.nextHeader();
114
115 if (HTTP.CONTENT_ENCODING.equals(responseHeader.getName())
116 || HTTP.CONTENT_LEN.equals(responseHeader.getName())) {
117 continue;
118 }
119 final Header[] matchingHeaders = headerGroup.getHeaders(responseHeader.getName());
120 for (final Header matchingHeader : matchingHeaders) {
121 headerGroup.removeHeader(matchingHeader);
122 }
123
124 }
125
126 for (final HeaderIterator it = headerGroup.iterator(); it.hasNext(); ) {
127 final Header cacheHeader = it.nextHeader();
128 if (HeaderConstants.WARNING.equalsIgnoreCase(cacheHeader.getName())) {
129 final String warningValue = cacheHeader.getValue();
130 if (warningValue != null && warningValue.startsWith("1")) {
131 it.remove();
132 }
133 }
134 }
135 for (final HeaderIterator it = response.headerIterator(); it.hasNext(); ) {
136 final Header responseHeader = it.nextHeader();
137
138 if (HTTP.CONTENT_ENCODING.equals(responseHeader.getName())
139 || HTTP.CONTENT_LEN.equals(responseHeader.getName())) {
140 continue;
141 }
142 headerGroup.addHeader(responseHeader);
143 }
144 return headerGroup.getAllHeaders();
145 }
146
147 private boolean entryDateHeaderNewerThenResponse(final HttpCacheEntry entry, final HttpResponse response) {
148 final Date entryDate = DateUtils.parseDate(entry.getFirstHeader(HTTP.DATE_HEADER)
149 .getValue());
150 final Date responseDate = DateUtils.parseDate(response.getFirstHeader(HTTP.DATE_HEADER)
151 .getValue());
152 return entryDate != null && responseDate != null && entryDate.after(responseDate);
153 }
154
155 private boolean entryAndResponseHaveDateHeader(final HttpCacheEntry entry, final HttpResponse response) {
156 return entry.getFirstHeader(HTTP.DATE_HEADER) != null
157 && response.getFirstHeader(HTTP.DATE_HEADER) != null;
158
159 }
160
161 }