370 lines
13 KiB
Java
370 lines
13 KiB
Java
![]() |
/* GENERATED SOURCE. DO NOT MODIFY. */
|
||
|
package com.android.okhttp;
|
||
|
|
||
|
import com.android.okhttp.internal.http.HeaderParser;
|
||
|
import java.util.concurrent.TimeUnit;
|
||
|
|
||
|
/**
|
||
|
* A Cache-Control header with cache directives from a server or client. These
|
||
|
* directives set policy on what responses can be stored, and which requests can
|
||
|
* be satisfied by those stored responses.
|
||
|
*
|
||
|
* <p>See <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9">RFC
|
||
|
* 2616, 14.9</a>.
|
||
|
* @hide This class is not part of the Android public SDK API
|
||
|
*/
|
||
|
public final class CacheControl {
|
||
|
/**
|
||
|
* Cache control request directives that require network validation of
|
||
|
* responses. Note that such requests may be assisted by the cache via
|
||
|
* conditional GET requests.
|
||
|
*/
|
||
|
public static final CacheControl FORCE_NETWORK = new Builder().noCache().build();
|
||
|
|
||
|
/**
|
||
|
* Cache control request directives that uses the cache only, even if the
|
||
|
* cached response is stale. If the response isn't available in the cache or
|
||
|
* requires server validation, the call will fail with a {@code 504
|
||
|
* Unsatisfiable Request}.
|
||
|
*/
|
||
|
public static final CacheControl FORCE_CACHE = new Builder()
|
||
|
.onlyIfCached()
|
||
|
.maxStale(Integer.MAX_VALUE, TimeUnit.SECONDS)
|
||
|
.build();
|
||
|
|
||
|
private final boolean noCache;
|
||
|
private final boolean noStore;
|
||
|
private final int maxAgeSeconds;
|
||
|
private final int sMaxAgeSeconds;
|
||
|
private final boolean isPrivate;
|
||
|
private final boolean isPublic;
|
||
|
private final boolean mustRevalidate;
|
||
|
private final int maxStaleSeconds;
|
||
|
private final int minFreshSeconds;
|
||
|
private final boolean onlyIfCached;
|
||
|
private final boolean noTransform;
|
||
|
|
||
|
String headerValue; // Lazily computed, if absent.
|
||
|
|
||
|
private CacheControl(boolean noCache, boolean noStore, int maxAgeSeconds, int sMaxAgeSeconds,
|
||
|
boolean isPrivate, boolean isPublic, boolean mustRevalidate, int maxStaleSeconds,
|
||
|
int minFreshSeconds, boolean onlyIfCached, boolean noTransform, String headerValue) {
|
||
|
this.noCache = noCache;
|
||
|
this.noStore = noStore;
|
||
|
this.maxAgeSeconds = maxAgeSeconds;
|
||
|
this.sMaxAgeSeconds = sMaxAgeSeconds;
|
||
|
this.isPrivate = isPrivate;
|
||
|
this.isPublic = isPublic;
|
||
|
this.mustRevalidate = mustRevalidate;
|
||
|
this.maxStaleSeconds = maxStaleSeconds;
|
||
|
this.minFreshSeconds = minFreshSeconds;
|
||
|
this.onlyIfCached = onlyIfCached;
|
||
|
this.noTransform = noTransform;
|
||
|
this.headerValue = headerValue;
|
||
|
}
|
||
|
|
||
|
private CacheControl(Builder builder) {
|
||
|
this.noCache = builder.noCache;
|
||
|
this.noStore = builder.noStore;
|
||
|
this.maxAgeSeconds = builder.maxAgeSeconds;
|
||
|
this.sMaxAgeSeconds = -1;
|
||
|
this.isPrivate = false;
|
||
|
this.isPublic = false;
|
||
|
this.mustRevalidate = false;
|
||
|
this.maxStaleSeconds = builder.maxStaleSeconds;
|
||
|
this.minFreshSeconds = builder.minFreshSeconds;
|
||
|
this.onlyIfCached = builder.onlyIfCached;
|
||
|
this.noTransform = builder.noTransform;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* In a response, this field's name "no-cache" is misleading. It doesn't
|
||
|
* prevent us from caching the response; it only means we have to validate the
|
||
|
* response with the origin server before returning it. We can do this with a
|
||
|
* conditional GET.
|
||
|
*
|
||
|
* <p>In a request, it means do not use a cache to satisfy the request.
|
||
|
*/
|
||
|
public boolean noCache() {
|
||
|
return noCache;
|
||
|
}
|
||
|
|
||
|
/** If true, this response should not be cached. */
|
||
|
public boolean noStore() {
|
||
|
return noStore;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* The duration past the response's served date that it can be served without
|
||
|
* validation.
|
||
|
*/
|
||
|
public int maxAgeSeconds() {
|
||
|
return maxAgeSeconds;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* The "s-maxage" directive is the max age for shared caches. Not to be
|
||
|
* confused with "max-age" for non-shared caches, As in Firefox and Chrome,
|
||
|
* this directive is not honored by this cache.
|
||
|
*/
|
||
|
public int sMaxAgeSeconds() {
|
||
|
return sMaxAgeSeconds;
|
||
|
}
|
||
|
|
||
|
public boolean isPrivate() {
|
||
|
return isPrivate;
|
||
|
}
|
||
|
|
||
|
public boolean isPublic() {
|
||
|
return isPublic;
|
||
|
}
|
||
|
|
||
|
public boolean mustRevalidate() {
|
||
|
return mustRevalidate;
|
||
|
}
|
||
|
|
||
|
public int maxStaleSeconds() {
|
||
|
return maxStaleSeconds;
|
||
|
}
|
||
|
|
||
|
public int minFreshSeconds() {
|
||
|
return minFreshSeconds;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* This field's name "only-if-cached" is misleading. It actually means "do
|
||
|
* not use the network". It is set by a client who only wants to make a
|
||
|
* request if it can be fully satisfied by the cache. Cached responses that
|
||
|
* would require validation (ie. conditional gets) are not permitted if this
|
||
|
* header is set.
|
||
|
*/
|
||
|
public boolean onlyIfCached() {
|
||
|
return onlyIfCached;
|
||
|
}
|
||
|
|
||
|
public boolean noTransform() {
|
||
|
return noTransform;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the cache directives of {@code headers}. This honors both
|
||
|
* Cache-Control and Pragma headers if they are present.
|
||
|
*/
|
||
|
public static CacheControl parse(Headers headers) {
|
||
|
boolean noCache = false;
|
||
|
boolean noStore = false;
|
||
|
int maxAgeSeconds = -1;
|
||
|
int sMaxAgeSeconds = -1;
|
||
|
boolean isPrivate = false;
|
||
|
boolean isPublic = false;
|
||
|
boolean mustRevalidate = false;
|
||
|
int maxStaleSeconds = -1;
|
||
|
int minFreshSeconds = -1;
|
||
|
boolean onlyIfCached = false;
|
||
|
boolean noTransform = false;
|
||
|
|
||
|
boolean canUseHeaderValue = true;
|
||
|
String headerValue = null;
|
||
|
|
||
|
for (int i = 0, size = headers.size(); i < size; i++) {
|
||
|
String name = headers.name(i);
|
||
|
String value = headers.value(i);
|
||
|
|
||
|
if (name.equalsIgnoreCase("Cache-Control")) {
|
||
|
if (headerValue != null) {
|
||
|
// Multiple cache-control headers means we can't use the raw value.
|
||
|
canUseHeaderValue = false;
|
||
|
} else {
|
||
|
headerValue = value;
|
||
|
}
|
||
|
} else if (name.equalsIgnoreCase("Pragma")) {
|
||
|
// Might specify additional cache-control params. We invalidate just in case.
|
||
|
canUseHeaderValue = false;
|
||
|
} else {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
int pos = 0;
|
||
|
while (pos < value.length()) {
|
||
|
int tokenStart = pos;
|
||
|
pos = HeaderParser.skipUntil(value, pos, "=,;");
|
||
|
String directive = value.substring(tokenStart, pos).trim();
|
||
|
String parameter;
|
||
|
|
||
|
if (pos == value.length() || value.charAt(pos) == ',' || value.charAt(pos) == ';') {
|
||
|
pos++; // consume ',' or ';' (if necessary)
|
||
|
parameter = null;
|
||
|
} else {
|
||
|
pos++; // consume '='
|
||
|
pos = HeaderParser.skipWhitespace(value, pos);
|
||
|
|
||
|
// quoted string
|
||
|
if (pos < value.length() && value.charAt(pos) == '\"') {
|
||
|
pos++; // consume '"' open quote
|
||
|
int parameterStart = pos;
|
||
|
pos = HeaderParser.skipUntil(value, pos, "\"");
|
||
|
parameter = value.substring(parameterStart, pos);
|
||
|
pos++; // consume '"' close quote (if necessary)
|
||
|
|
||
|
// unquoted string
|
||
|
} else {
|
||
|
int parameterStart = pos;
|
||
|
pos = HeaderParser.skipUntil(value, pos, ",;");
|
||
|
parameter = value.substring(parameterStart, pos).trim();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ("no-cache".equalsIgnoreCase(directive)) {
|
||
|
noCache = true;
|
||
|
} else if ("no-store".equalsIgnoreCase(directive)) {
|
||
|
noStore = true;
|
||
|
} else if ("max-age".equalsIgnoreCase(directive)) {
|
||
|
maxAgeSeconds = HeaderParser.parseSeconds(parameter, -1);
|
||
|
} else if ("s-maxage".equalsIgnoreCase(directive)) {
|
||
|
sMaxAgeSeconds = HeaderParser.parseSeconds(parameter, -1);
|
||
|
} else if ("private".equalsIgnoreCase(directive)) {
|
||
|
isPrivate = true;
|
||
|
} else if ("public".equalsIgnoreCase(directive)) {
|
||
|
isPublic = true;
|
||
|
} else if ("must-revalidate".equalsIgnoreCase(directive)) {
|
||
|
mustRevalidate = true;
|
||
|
} else if ("max-stale".equalsIgnoreCase(directive)) {
|
||
|
maxStaleSeconds = HeaderParser.parseSeconds(parameter, Integer.MAX_VALUE);
|
||
|
} else if ("min-fresh".equalsIgnoreCase(directive)) {
|
||
|
minFreshSeconds = HeaderParser.parseSeconds(parameter, -1);
|
||
|
} else if ("only-if-cached".equalsIgnoreCase(directive)) {
|
||
|
onlyIfCached = true;
|
||
|
} else if ("no-transform".equalsIgnoreCase(directive)) {
|
||
|
noTransform = true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!canUseHeaderValue) {
|
||
|
headerValue = null;
|
||
|
}
|
||
|
return new CacheControl(noCache, noStore, maxAgeSeconds, sMaxAgeSeconds, isPrivate, isPublic,
|
||
|
mustRevalidate, maxStaleSeconds, minFreshSeconds, onlyIfCached, noTransform, headerValue);
|
||
|
}
|
||
|
|
||
|
@Override public String toString() {
|
||
|
String result = headerValue;
|
||
|
return result != null ? result : (headerValue = headerValue());
|
||
|
}
|
||
|
|
||
|
private String headerValue() {
|
||
|
StringBuilder result = new StringBuilder();
|
||
|
if (noCache) result.append("no-cache, ");
|
||
|
if (noStore) result.append("no-store, ");
|
||
|
if (maxAgeSeconds != -1) result.append("max-age=").append(maxAgeSeconds).append(", ");
|
||
|
if (sMaxAgeSeconds != -1) result.append("s-maxage=").append(sMaxAgeSeconds).append(", ");
|
||
|
if (isPrivate) result.append("private, ");
|
||
|
if (isPublic) result.append("public, ");
|
||
|
if (mustRevalidate) result.append("must-revalidate, ");
|
||
|
if (maxStaleSeconds != -1) result.append("max-stale=").append(maxStaleSeconds).append(", ");
|
||
|
if (minFreshSeconds != -1) result.append("min-fresh=").append(minFreshSeconds).append(", ");
|
||
|
if (onlyIfCached) result.append("only-if-cached, ");
|
||
|
if (noTransform) result.append("no-transform, ");
|
||
|
if (result.length() == 0) return "";
|
||
|
result.delete(result.length() - 2, result.length());
|
||
|
return result.toString();
|
||
|
}
|
||
|
|
||
|
/** Builds a {@code Cache-Control} request header.
|
||
|
* @hide This class is not part of the Android public SDK API*/
|
||
|
public static final class Builder {
|
||
|
boolean noCache;
|
||
|
boolean noStore;
|
||
|
int maxAgeSeconds = -1;
|
||
|
int maxStaleSeconds = -1;
|
||
|
int minFreshSeconds = -1;
|
||
|
boolean onlyIfCached;
|
||
|
boolean noTransform;
|
||
|
|
||
|
/** Don't accept an unvalidated cached response. */
|
||
|
public Builder noCache() {
|
||
|
this.noCache = true;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
/** Don't store the server's response in any cache. */
|
||
|
public Builder noStore() {
|
||
|
this.noStore = true;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the maximum age of a cached response. If the cache response's age
|
||
|
* exceeds {@code maxAge}, it will not be used and a network request will
|
||
|
* be made.
|
||
|
*
|
||
|
* @param maxAge a non-negative integer. This is stored and transmitted with
|
||
|
* {@link TimeUnit#SECONDS} precision; finer precision will be lost.
|
||
|
*/
|
||
|
public Builder maxAge(int maxAge, TimeUnit timeUnit) {
|
||
|
if (maxAge < 0) throw new IllegalArgumentException("maxAge < 0: " + maxAge);
|
||
|
long maxAgeSecondsLong = timeUnit.toSeconds(maxAge);
|
||
|
this.maxAgeSeconds = maxAgeSecondsLong > Integer.MAX_VALUE
|
||
|
? Integer.MAX_VALUE
|
||
|
: (int) maxAgeSecondsLong;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Accept cached responses that have exceeded their freshness lifetime by
|
||
|
* up to {@code maxStale}. If unspecified, stale cache responses will not be
|
||
|
* used.
|
||
|
*
|
||
|
* @param maxStale a non-negative integer. This is stored and transmitted
|
||
|
* with {@link TimeUnit#SECONDS} precision; finer precision will be
|
||
|
* lost.
|
||
|
*/
|
||
|
public Builder maxStale(int maxStale, TimeUnit timeUnit) {
|
||
|
if (maxStale < 0) throw new IllegalArgumentException("maxStale < 0: " + maxStale);
|
||
|
long maxStaleSecondsLong = timeUnit.toSeconds(maxStale);
|
||
|
this.maxStaleSeconds = maxStaleSecondsLong > Integer.MAX_VALUE
|
||
|
? Integer.MAX_VALUE
|
||
|
: (int) maxStaleSecondsLong;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the minimum number of seconds that a response will continue to be
|
||
|
* fresh for. If the response will be stale when {@code minFresh} have
|
||
|
* elapsed, the cached response will not be used and a network request will
|
||
|
* be made.
|
||
|
*
|
||
|
* @param minFresh a non-negative integer. This is stored and transmitted
|
||
|
* with {@link TimeUnit#SECONDS} precision; finer precision will be
|
||
|
* lost.
|
||
|
*/
|
||
|
public Builder minFresh(int minFresh, TimeUnit timeUnit) {
|
||
|
if (minFresh < 0) throw new IllegalArgumentException("minFresh < 0: " + minFresh);
|
||
|
long minFreshSecondsLong = timeUnit.toSeconds(minFresh);
|
||
|
this.minFreshSeconds = minFreshSecondsLong > Integer.MAX_VALUE
|
||
|
? Integer.MAX_VALUE
|
||
|
: (int) minFreshSecondsLong;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Only accept the response if it is in the cache. If the response isn't
|
||
|
* cached, a {@code 504 Unsatisfiable Request} response will be returned.
|
||
|
*/
|
||
|
public Builder onlyIfCached() {
|
||
|
this.onlyIfCached = true;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
/** Don't accept a transformed response. */
|
||
|
public Builder noTransform() {
|
||
|
this.noTransform = true;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
public CacheControl build() {
|
||
|
return new CacheControl(this);
|
||
|
}
|
||
|
}
|
||
|
}
|