View Javadoc

1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  package org.apache.http.impl.client.cache;
28  
29  import org.apache.http.util.Args;
30  
31  /**
32   * <p>Java Beans-style configuration for a {@link CachingHttpClient}. Any class
33   * in the caching module that has configuration options should take a
34   * {@link CacheConfig} argument in one of its constructors. A
35   * {@code CacheConfig} instance has sane and conservative defaults, so the
36   * easiest way to specify options is to get an instance and then set just
37   * the options you want to modify from their defaults.</p>
38   *
39   * <p><b>N.B.</b> This class is only for caching-specific configuration; to
40   * configure the behavior of the rest of the client, configure the
41   * {@link org.apache.http.client.HttpClient} used as the &quot;backend&quot;
42   * for the {@code CachingHttpClient}.</p>
43   *
44   * <p>Cache configuration can be grouped into the following categories:</p>
45   *
46   * <p><b>Cache size.</b> If the backend storage supports these limits, you
47   * can specify the {@link CacheConfig#getMaxCacheEntries maximum number of
48   * cache entries} as well as the {@link CacheConfig#getMaxObjectSizeBytes
49   * maximum cacheable response body size}.</p>
50   *
51   * <p><b>Public/private caching.</b> By default, the caching module considers
52   * itself to be a shared (public) cache, and will not, for example, cache
53   * responses to requests with {@code Authorization} headers or responses
54   * marked with {@code Cache-Control: private}. If, however, the cache
55   * is only going to be used by one logical "user" (behaving similarly to a
56   * browser cache), then you will want to {@link
57   * CacheConfig#setSharedCache(boolean) turn off the shared cache setting}.</p>
58   *
59   * <p><b>303 caching</b>. RFC2616 explicitly disallows caching 303 responses;
60   * however, the HTTPbis working group says they can be cached
61   * if explicitly indicated in the response headers and permitted by the request method.
62   * (They also indicate that disallowing 303 caching is actually an unintended
63   * spec error in RFC2616).
64   * This behavior is off by default, to err on the side of a conservative
65   * adherence to the existing standard, but you may want to
66   * {@link Builder#setAllow303Caching(boolean) enable it}.
67   *
68   * <p><b>Weak ETags on PUT/DELETE If-Match requests</b>. RFC2616 explicitly
69   * prohibits the use of weak validators in non-GET requests, however, the
70   * HTTPbis working group says while the limitation for weak validators on ranged
71   * requests makes sense, weak ETag validation is useful on full non-GET
72   * requests; e.g., PUT with If-Match. This behavior is off by default, to err on
73   * the side of a conservative adherence to the existing standard, but you may
74   * want to {@link Builder#setWeakETagOnPutDeleteAllowed(boolean) enable it}.
75   *
76   * <p><b>Heuristic caching</b>. Per RFC2616, a cache may cache certain cache
77   * entries even if no explicit cache control headers are set by the origin.
78   * This behavior is off by default, but you may want to turn this on if you
79   * are working with an origin that doesn't set proper headers but where you
80   * still want to cache the responses. You will want to {@link
81   * CacheConfig#setHeuristicCachingEnabled(boolean) enable heuristic caching},
82   * then specify either a {@link CacheConfig#getHeuristicDefaultLifetime()
83   * default freshness lifetime} and/or a {@link
84   * CacheConfig#setHeuristicCoefficient(float) fraction of the time since
85   * the resource was last modified}. See Sections
86   * <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.2.2">
87   * 13.2.2</a> and <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.2.4">
88   * 13.2.4</a> of the HTTP/1.1 RFC for more details on heuristic caching.</p>
89   *
90   * <p><b>Background validation</b>. The cache module supports the
91   * {@code stale-while-revalidate} directive of
92   * <a href="http://tools.ietf.org/html/rfc5861">RFC5861</a>, which allows
93   * certain cache entry revalidations to happen in the background. You may
94   * want to tweak the settings for the {@link
95   * CacheConfig#getAsynchronousWorkersCore() minimum} and {@link
96   * CacheConfig#getAsynchronousWorkersMax() maximum} number of background
97   * worker threads, as well as the {@link
98   * CacheConfig#getAsynchronousWorkerIdleLifetimeSecs() maximum time they
99   * can be idle before being reclaimed}. You can also control the {@link
100  * CacheConfig#getRevalidationQueueSize() size of the queue} used for
101  * revalidations when there aren't enough workers to keep up with demand.</b>
102  */
103 public class CacheConfig implements Cloneable {
104 
105     /** Default setting for the maximum object size that will be
106      * cached, in bytes.
107      */
108     public final static int DEFAULT_MAX_OBJECT_SIZE_BYTES = 8192;
109 
110     /** Default setting for the maximum number of cache entries
111      * that will be retained.
112      */
113     public final static int DEFAULT_MAX_CACHE_ENTRIES = 1000;
114 
115     /** Default setting for the number of retries on a failed
116      * cache update
117      */
118     public final static int DEFAULT_MAX_UPDATE_RETRIES = 1;
119 
120     /** Default setting for 303 caching
121      */
122     public final static boolean DEFAULT_303_CACHING_ENABLED = false;
123 
124     /** Default setting to allow weak tags on PUT/DELETE methods
125      */
126     public final static boolean DEFAULT_WEAK_ETAG_ON_PUTDELETE_ALLOWED = false;
127 
128     /** Default setting for heuristic caching
129      */
130     public final static boolean DEFAULT_HEURISTIC_CACHING_ENABLED = false;
131 
132     /** Default coefficient used to heuristically determine freshness
133      * lifetime from the Last-Modified time of a cache entry.
134      */
135     public final static float DEFAULT_HEURISTIC_COEFFICIENT = 0.1f;
136 
137     /** Default lifetime in seconds to be assumed when we cannot calculate
138      * freshness heuristically.
139      */
140     public final static long DEFAULT_HEURISTIC_LIFETIME = 0;
141 
142     /** Default number of worker threads to allow for background revalidations
143      * resulting from the stale-while-revalidate directive.
144      */
145     public static final int DEFAULT_ASYNCHRONOUS_WORKERS_MAX = 1;
146 
147     /** Default minimum number of worker threads to allow for background
148      * revalidations resulting from the stale-while-revalidate directive.
149      */
150     public static final int DEFAULT_ASYNCHRONOUS_WORKERS_CORE = 1;
151 
152     /** Default maximum idle lifetime for a background revalidation thread
153      * before it gets reclaimed.
154      */
155     public static final int DEFAULT_ASYNCHRONOUS_WORKER_IDLE_LIFETIME_SECS = 60;
156 
157     /** Default maximum queue length for background revalidation requests.
158      */
159     public static final int DEFAULT_REVALIDATION_QUEUE_SIZE = 100;
160 
161     public static final CacheConfig DEFAULT = new Builder().build();
162 
163     // TODO: make final
164     private long maxObjectSize;
165     private int maxCacheEntries;
166     private int maxUpdateRetries;
167     private boolean allow303Caching;
168     private boolean weakETagOnPutDeleteAllowed;
169     private boolean heuristicCachingEnabled;
170     private float heuristicCoefficient;
171     private long heuristicDefaultLifetime;
172     private boolean isSharedCache;
173     private int asynchronousWorkersMax;
174     private int asynchronousWorkersCore;
175     private int asynchronousWorkerIdleLifetimeSecs;
176     private int revalidationQueueSize;
177     private boolean neverCacheHTTP10ResponsesWithQuery;
178 
179     /**
180      * @deprecated (4.3) use {@link Builder}.
181      */
182     @Deprecated
183     public CacheConfig() {
184         super();
185         this.maxObjectSize = DEFAULT_MAX_OBJECT_SIZE_BYTES;
186         this.maxCacheEntries = DEFAULT_MAX_CACHE_ENTRIES;
187         this.maxUpdateRetries = DEFAULT_MAX_UPDATE_RETRIES;
188         this.allow303Caching = DEFAULT_303_CACHING_ENABLED;
189         this.weakETagOnPutDeleteAllowed = DEFAULT_WEAK_ETAG_ON_PUTDELETE_ALLOWED;
190         this.heuristicCachingEnabled = DEFAULT_HEURISTIC_CACHING_ENABLED;
191         this.heuristicCoefficient = DEFAULT_HEURISTIC_COEFFICIENT;
192         this.heuristicDefaultLifetime = DEFAULT_HEURISTIC_LIFETIME;
193         this.isSharedCache = true;
194         this.asynchronousWorkersMax = DEFAULT_ASYNCHRONOUS_WORKERS_MAX;
195         this.asynchronousWorkersCore = DEFAULT_ASYNCHRONOUS_WORKERS_CORE;
196         this.asynchronousWorkerIdleLifetimeSecs = DEFAULT_ASYNCHRONOUS_WORKER_IDLE_LIFETIME_SECS;
197         this.revalidationQueueSize = DEFAULT_REVALIDATION_QUEUE_SIZE;
198     }
199 
200     CacheConfig(
201             final long maxObjectSize,
202             final int maxCacheEntries,
203             final int maxUpdateRetries,
204             final boolean allow303Caching,
205             final boolean weakETagOnPutDeleteAllowed,
206             final boolean heuristicCachingEnabled,
207             final float heuristicCoefficient,
208             final long heuristicDefaultLifetime,
209             final boolean isSharedCache,
210             final int asynchronousWorkersMax,
211             final int asynchronousWorkersCore,
212             final int asynchronousWorkerIdleLifetimeSecs,
213             final int revalidationQueueSize,
214             final boolean neverCacheHTTP10ResponsesWithQuery) {
215         super();
216         this.maxObjectSize = maxObjectSize;
217         this.maxCacheEntries = maxCacheEntries;
218         this.maxUpdateRetries = maxUpdateRetries;
219         this.allow303Caching = allow303Caching;
220         this.weakETagOnPutDeleteAllowed = weakETagOnPutDeleteAllowed;
221         this.heuristicCachingEnabled = heuristicCachingEnabled;
222         this.heuristicCoefficient = heuristicCoefficient;
223         this.heuristicDefaultLifetime = heuristicDefaultLifetime;
224         this.isSharedCache = isSharedCache;
225         this.asynchronousWorkersMax = asynchronousWorkersMax;
226         this.asynchronousWorkersCore = asynchronousWorkersCore;
227         this.asynchronousWorkerIdleLifetimeSecs = asynchronousWorkerIdleLifetimeSecs;
228         this.revalidationQueueSize = revalidationQueueSize;
229     }
230 
231     /**
232      * Returns the current maximum response body size that will be cached.
233      * @return size in bytes
234      *
235      * @deprecated (4.2)  use {@link #getMaxObjectSize()}
236      */
237     @Deprecated
238     public int getMaxObjectSizeBytes() {
239         return maxObjectSize > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) maxObjectSize;
240     }
241 
242     /**
243      * Specifies the maximum response body size that will be eligible for caching.
244      * @param maxObjectSizeBytes size in bytes
245      *
246      * @deprecated (4.2)  use {@link Builder}.
247      */
248     @Deprecated
249     public void setMaxObjectSizeBytes(final int maxObjectSizeBytes) {
250         if (maxObjectSizeBytes > Integer.MAX_VALUE) {
251             this.maxObjectSize = Integer.MAX_VALUE;
252         } else {
253             this.maxObjectSize = maxObjectSizeBytes;
254         }
255     }
256 
257     /**
258      * Returns the current maximum response body size that will be cached.
259      * @return size in bytes
260      *
261      * @since 4.2
262      */
263     public long getMaxObjectSize() {
264         return maxObjectSize;
265     }
266 
267     /**
268      * Specifies the maximum response body size that will be eligible for caching.
269      * @param maxObjectSize size in bytes
270      *
271      * @since 4.2
272      *
273      * @deprecated (4.3) use {@link Builder}.
274      */
275     @Deprecated
276     public void setMaxObjectSize(final long maxObjectSize) {
277         this.maxObjectSize = maxObjectSize;
278     }
279 
280     /**
281      * Returns whether the cache will never cache HTTP 1.0 responses with a query string or not.
282      * @return {@code true} to not cache query string responses, {@code false} to cache if explicit cache headers are
283      * found
284      */
285     public boolean isNeverCacheHTTP10ResponsesWithQuery() {
286         return neverCacheHTTP10ResponsesWithQuery;
287     }
288 
289     /**
290      * Returns the maximum number of cache entries the cache will retain.
291      */
292     public int getMaxCacheEntries() {
293         return maxCacheEntries;
294     }
295 
296     /**
297      * Sets the maximum number of cache entries the cache will retain.
298      *
299      * @deprecated (4.3) use {@link Builder}.
300      */
301     @Deprecated
302     public void setMaxCacheEntries(final int maxCacheEntries) {
303         this.maxCacheEntries = maxCacheEntries;
304     }
305 
306     /**
307      * Returns the number of times to retry a cache update on failure
308      */
309     public int getMaxUpdateRetries(){
310         return maxUpdateRetries;
311     }
312 
313     /**
314      * Sets the number of times to retry a cache update on failure
315      *
316      * @deprecated (4.3) use {@link Builder}.
317      */
318     @Deprecated
319     public void setMaxUpdateRetries(final int maxUpdateRetries){
320         this.maxUpdateRetries = maxUpdateRetries;
321     }
322 
323     /**
324      * Returns whether 303 caching is enabled.
325      * @return {@code true} if it is enabled.
326      */
327     public boolean is303CachingEnabled() {
328         return allow303Caching;
329     }
330 
331     /**
332      * Returns whether weak etags is allowed with PUT/DELETE methods.
333      * @return {@code true} if it is allowed.
334      */
335     public boolean isWeakETagOnPutDeleteAllowed() {
336         return weakETagOnPutDeleteAllowed;
337     }
338 
339     /**
340      * Returns whether heuristic caching is enabled.
341      * @return {@code true} if it is enabled.
342      */
343     public boolean isHeuristicCachingEnabled() {
344         return heuristicCachingEnabled;
345     }
346 
347     /**
348      * Enables or disables heuristic caching.
349      * @param heuristicCachingEnabled should be {@code true} to
350      *   permit heuristic caching, {@code false} to disable it.
351      *
352      * @deprecated (4.3) use {@link Builder}.
353      */
354     @Deprecated
355     public void setHeuristicCachingEnabled(final boolean heuristicCachingEnabled) {
356         this.heuristicCachingEnabled = heuristicCachingEnabled;
357     }
358 
359     /**
360      * Returns lifetime coefficient used in heuristic freshness caching.
361      */
362     public float getHeuristicCoefficient() {
363         return heuristicCoefficient;
364     }
365 
366     /**
367      * Sets coefficient to be used in heuristic freshness caching. This is
368      * interpreted as the fraction of the time between the {@code Last-Modified}
369      * and {@code Date} headers of a cached response during which the cached
370      * response will be considered heuristically fresh.
371      * @param heuristicCoefficient should be between {@code 0.0} and
372      *   {@code 1.0}.
373      *
374      * @deprecated (4.3) use {@link Builder}.
375      */
376     @Deprecated
377     public void setHeuristicCoefficient(final float heuristicCoefficient) {
378         this.heuristicCoefficient = heuristicCoefficient;
379     }
380 
381     /**
382      * Get the default lifetime to be used if heuristic freshness calculation is
383      * not possible.
384      */
385     public long getHeuristicDefaultLifetime() {
386         return heuristicDefaultLifetime;
387     }
388 
389     /**
390      * Sets default lifetime in seconds to be used if heuristic freshness
391      * calculation is not possible. Explicit cache control directives on
392      * either the request or origin response will override this, as will
393      * the heuristic {@code Last-Modified} freshness calculation if it is
394      * available.
395      * @param heuristicDefaultLifetimeSecs is the number of seconds to
396      *   consider a cache-eligible response fresh in the absence of other
397      *   information. Set this to {@code 0} to disable this style of
398      *   heuristic caching.
399      *
400      * @deprecated (4.3) use {@link Builder}.
401      */
402     @Deprecated
403     public void setHeuristicDefaultLifetime(final long heuristicDefaultLifetimeSecs) {
404         this.heuristicDefaultLifetime = heuristicDefaultLifetimeSecs;
405     }
406 
407     /**
408      * Returns whether the cache will behave as a shared cache or not.
409      * @return {@code true} for a shared cache, {@code false} for a non-
410      * shared (private) cache
411      */
412     public boolean isSharedCache() {
413         return isSharedCache;
414     }
415 
416     /**
417      * Sets whether the cache should behave as a shared cache or not.
418      * @param isSharedCache true to behave as a shared cache, false to
419      * behave as a non-shared (private) cache. To have the cache
420      * behave like a browser cache, you want to set this to {@code false}.
421      *
422      * @deprecated (4.3) use {@link Builder}.
423      */
424     @Deprecated
425     public void setSharedCache(final boolean isSharedCache) {
426         this.isSharedCache = isSharedCache;
427     }
428 
429     /**
430      * Returns the maximum number of threads to allow for background
431      * revalidations due to the {@code stale-while-revalidate} directive. A
432      * value of 0 means background revalidations are disabled.
433      */
434     public int getAsynchronousWorkersMax() {
435         return asynchronousWorkersMax;
436     }
437 
438     /**
439      * Sets the maximum number of threads to allow for background
440      * revalidations due to the {@code stale-while-revalidate} directive.
441      * @param max number of threads; a value of 0 disables background
442      * revalidations.
443      *
444      * @deprecated (4.3) use {@link Builder}.
445      */
446     @Deprecated
447     public void setAsynchronousWorkersMax(final int max) {
448         this.asynchronousWorkersMax = max;
449     }
450 
451     /**
452      * Returns the minimum number of threads to keep alive for background
453      * revalidations due to the {@code stale-while-revalidate} directive.
454      */
455     public int getAsynchronousWorkersCore() {
456         return asynchronousWorkersCore;
457     }
458 
459     /**
460      * Sets the minimum number of threads to keep alive for background
461      * revalidations due to the {@code stale-while-revalidate} directive.
462      * @param min should be greater than zero and less than or equal
463      *   to <code>getAsynchronousWorkersMax()</code>
464      *
465      * @deprecated (4.3) use {@link Builder}.
466      */
467     @Deprecated
468     public void setAsynchronousWorkersCore(final int min) {
469         this.asynchronousWorkersCore = min;
470     }
471 
472     /**
473      * Returns the current maximum idle lifetime in seconds for a
474      * background revalidation worker thread. If a worker thread is idle
475      * for this long, and there are more than the core number of worker
476      * threads alive, the worker will be reclaimed.
477      */
478     public int getAsynchronousWorkerIdleLifetimeSecs() {
479         return asynchronousWorkerIdleLifetimeSecs;
480     }
481 
482     /**
483      * Sets the current maximum idle lifetime in seconds for a
484      * background revalidation worker thread. If a worker thread is idle
485      * for this long, and there are more than the core number of worker
486      * threads alive, the worker will be reclaimed.
487      * @param secs idle lifetime in seconds
488      *
489      * @deprecated (4.3) use {@link Builder}.
490      */
491     @Deprecated
492     public void setAsynchronousWorkerIdleLifetimeSecs(final int secs) {
493         this.asynchronousWorkerIdleLifetimeSecs = secs;
494     }
495 
496     /**
497      * Returns the current maximum queue size for background revalidations.
498      */
499     public int getRevalidationQueueSize() {
500         return revalidationQueueSize;
501     }
502 
503     /**
504      * Sets the current maximum queue size for background revalidations.
505      *
506      * @deprecated (4.3) use {@link Builder}.
507      */
508     @Deprecated
509     public void setRevalidationQueueSize(final int size) {
510         this.revalidationQueueSize = size;
511     }
512 
513     @Override
514     protected CacheConfig clone() throws CloneNotSupportedException {
515         return (CacheConfig) super.clone();
516     }
517 
518     public static Builder custom() {
519         return new Builder();
520     }
521 
522     public static Builder copy(final CacheConfig config) {
523         Args.notNull(config, "Cache config");
524         return new Builder()
525             .setMaxObjectSize(config.getMaxObjectSize())
526             .setMaxCacheEntries(config.getMaxCacheEntries())
527             .setMaxUpdateRetries(config.getMaxUpdateRetries())
528             .setHeuristicCachingEnabled(config.isHeuristicCachingEnabled())
529             .setHeuristicCoefficient(config.getHeuristicCoefficient())
530             .setHeuristicDefaultLifetime(config.getHeuristicDefaultLifetime())
531             .setSharedCache(config.isSharedCache())
532             .setAsynchronousWorkersMax(config.getAsynchronousWorkersMax())
533             .setAsynchronousWorkersCore(config.getAsynchronousWorkersCore())
534             .setAsynchronousWorkerIdleLifetimeSecs(config.getAsynchronousWorkerIdleLifetimeSecs())
535             .setRevalidationQueueSize(config.getRevalidationQueueSize())
536             .setNeverCacheHTTP10ResponsesWithQueryString(config.isNeverCacheHTTP10ResponsesWithQuery());
537     }
538 
539 
540     public static class Builder {
541 
542         private long maxObjectSize;
543         private int maxCacheEntries;
544         private int maxUpdateRetries;
545         private boolean allow303Caching;
546         private boolean weakETagOnPutDeleteAllowed;
547         private boolean heuristicCachingEnabled;
548         private float heuristicCoefficient;
549         private long heuristicDefaultLifetime;
550         private boolean isSharedCache;
551         private int asynchronousWorkersMax;
552         private int asynchronousWorkersCore;
553         private int asynchronousWorkerIdleLifetimeSecs;
554         private int revalidationQueueSize;
555         private boolean neverCacheHTTP10ResponsesWithQuery;
556 
557         Builder() {
558             this.maxObjectSize = DEFAULT_MAX_OBJECT_SIZE_BYTES;
559             this.maxCacheEntries = DEFAULT_MAX_CACHE_ENTRIES;
560             this.maxUpdateRetries = DEFAULT_MAX_UPDATE_RETRIES;
561             this.allow303Caching = DEFAULT_303_CACHING_ENABLED;
562             this.weakETagOnPutDeleteAllowed = DEFAULT_WEAK_ETAG_ON_PUTDELETE_ALLOWED;
563             this.heuristicCachingEnabled = false;
564             this.heuristicCoefficient = DEFAULT_HEURISTIC_COEFFICIENT;
565             this.heuristicDefaultLifetime = DEFAULT_HEURISTIC_LIFETIME;
566             this.isSharedCache = true;
567             this.asynchronousWorkersMax = DEFAULT_ASYNCHRONOUS_WORKERS_MAX;
568             this.asynchronousWorkersCore = DEFAULT_ASYNCHRONOUS_WORKERS_CORE;
569             this.asynchronousWorkerIdleLifetimeSecs = DEFAULT_ASYNCHRONOUS_WORKER_IDLE_LIFETIME_SECS;
570             this.revalidationQueueSize = DEFAULT_REVALIDATION_QUEUE_SIZE;
571         }
572 
573         /**
574          * Specifies the maximum response body size that will be eligible for caching.
575          * @param maxObjectSize size in bytes
576          */
577         public Builder setMaxObjectSize(final long maxObjectSize) {
578             this.maxObjectSize = maxObjectSize;
579             return this;
580         }
581 
582         /**
583          * Sets the maximum number of cache entries the cache will retain.
584          */
585         public Builder setMaxCacheEntries(final int maxCacheEntries) {
586             this.maxCacheEntries = maxCacheEntries;
587             return this;
588         }
589 
590         /**
591          * Sets the number of times to retry a cache update on failure
592          */
593         public Builder setMaxUpdateRetries(final int maxUpdateRetries) {
594             this.maxUpdateRetries = maxUpdateRetries;
595             return this;
596         }
597 
598         /**
599          * Enables or disables 303 caching.
600          * @param allow303Caching should be {@code true} to
601          *   permit 303 caching, {@code false} to disable it.
602          */
603         public Builder setAllow303Caching(final boolean allow303Caching) {
604             this.allow303Caching = allow303Caching;
605             return this;
606         }
607 
608         /**
609          * Allows or disallows weak etags to be used with PUT/DELETE If-Match requests.
610          * @param weakETagOnPutDeleteAllowed should be {@code true} to
611          *   permit weak etags, {@code false} to reject them.
612          */
613         public Builder setWeakETagOnPutDeleteAllowed(final boolean weakETagOnPutDeleteAllowed) {
614             this.weakETagOnPutDeleteAllowed = weakETagOnPutDeleteAllowed;
615             return this;
616         }
617 
618         /**
619          * Enables or disables heuristic caching.
620          * @param heuristicCachingEnabled should be {@code true} to
621          *   permit heuristic caching, {@code false} to enable it.
622          */
623         public Builder setHeuristicCachingEnabled(final boolean heuristicCachingEnabled) {
624             this.heuristicCachingEnabled = heuristicCachingEnabled;
625             return this;
626         }
627 
628         /**
629          * Sets coefficient to be used in heuristic freshness caching. This is
630          * interpreted as the fraction of the time between the {@code Last-Modified}
631          * and {@code Date} headers of a cached response during which the cached
632          * response will be considered heuristically fresh.
633          * @param heuristicCoefficient should be between {@code 0.0} and
634          *   {@code 1.0}.
635          */
636         public Builder setHeuristicCoefficient(final float heuristicCoefficient) {
637             this.heuristicCoefficient = heuristicCoefficient;
638             return this;
639         }
640 
641         /**
642          * Sets default lifetime in seconds to be used if heuristic freshness
643          * calculation is not possible. Explicit cache control directives on
644          * either the request or origin response will override this, as will
645          * the heuristic {@code Last-Modified} freshness calculation if it is
646          * available.
647          * @param heuristicDefaultLifetime is the number of seconds to
648          *   consider a cache-eligible response fresh in the absence of other
649          *   information. Set this to {@code 0} to disable this style of
650          *   heuristic caching.
651          */
652         public Builder setHeuristicDefaultLifetime(final long heuristicDefaultLifetime) {
653             this.heuristicDefaultLifetime = heuristicDefaultLifetime;
654             return this;
655         }
656 
657         /**
658          * Sets whether the cache should behave as a shared cache or not.
659          * @param isSharedCache true to behave as a shared cache, false to
660          * behave as a non-shared (private) cache. To have the cache
661          * behave like a browser cache, you want to set this to {@code false}.
662          */
663         public Builder setSharedCache(final boolean isSharedCache) {
664             this.isSharedCache = isSharedCache;
665             return this;
666         }
667 
668         /**
669          * Sets the maximum number of threads to allow for background
670          * revalidations due to the {@code stale-while-revalidate} directive.
671          * @param asynchronousWorkersMax number of threads; a value of 0 disables background
672          * revalidations.
673          */
674         public Builder setAsynchronousWorkersMax(final int asynchronousWorkersMax) {
675             this.asynchronousWorkersMax = asynchronousWorkersMax;
676             return this;
677         }
678 
679         /**
680          * Sets the minimum number of threads to keep alive for background
681          * revalidations due to the {@code stale-while-revalidate} directive.
682          * @param asynchronousWorkersCore should be greater than zero and less than or equal
683          *   to <code>getAsynchronousWorkersMax()</code>
684          */
685         public Builder setAsynchronousWorkersCore(final int asynchronousWorkersCore) {
686             this.asynchronousWorkersCore = asynchronousWorkersCore;
687             return this;
688         }
689 
690         /**
691          * Sets the current maximum idle lifetime in seconds for a
692          * background revalidation worker thread. If a worker thread is idle
693          * for this long, and there are more than the core number of worker
694          * threads alive, the worker will be reclaimed.
695          * @param asynchronousWorkerIdleLifetimeSecs idle lifetime in seconds
696          */
697         public Builder setAsynchronousWorkerIdleLifetimeSecs(final int asynchronousWorkerIdleLifetimeSecs) {
698             this.asynchronousWorkerIdleLifetimeSecs = asynchronousWorkerIdleLifetimeSecs;
699             return this;
700         }
701 
702         /**
703          * Sets the current maximum queue size for background revalidations.
704          */
705         public Builder setRevalidationQueueSize(final int revalidationQueueSize) {
706             this.revalidationQueueSize = revalidationQueueSize;
707             return this;
708         }
709 
710         /**
711          * Sets whether the cache should never cache HTTP 1.0 responses with a query string or not.
712          * @param neverCacheHTTP10ResponsesWithQuery true to never cache responses with a query
713          * string, false to cache if explicit cache headers are found.  Set this to {@code true}
714          * to better emulate IE, which also never caches responses, regardless of what caching
715          * headers may be present.
716          */
717         public Builder setNeverCacheHTTP10ResponsesWithQueryString(
718                 final boolean neverCacheHTTP10ResponsesWithQuery) {
719             this.neverCacheHTTP10ResponsesWithQuery = neverCacheHTTP10ResponsesWithQuery;
720             return this;
721         }
722 
723         public CacheConfig build() {
724             return new CacheConfig(
725                     maxObjectSize,
726                     maxCacheEntries,
727                     maxUpdateRetries,
728                     allow303Caching,
729                     weakETagOnPutDeleteAllowed,
730                     heuristicCachingEnabled,
731                     heuristicCoefficient,
732                     heuristicDefaultLifetime,
733                     isSharedCache,
734                     asynchronousWorkersMax,
735                     asynchronousWorkersCore,
736                     asynchronousWorkerIdleLifetimeSecs,
737                     revalidationQueueSize,
738                     neverCacheHTTP10ResponsesWithQuery);
739         }
740 
741     }
742 
743     @Override
744     public String toString() {
745         final StringBuilder builder = new StringBuilder();
746         builder.append("[maxObjectSize=").append(this.maxObjectSize)
747                 .append(", maxCacheEntries=").append(this.maxCacheEntries)
748                 .append(", maxUpdateRetries=").append(this.maxUpdateRetries)
749                 .append(", 303CachingEnabled=").append(this.allow303Caching)
750                 .append(", weakETagOnPutDeleteAllowed=").append(this.weakETagOnPutDeleteAllowed)
751                 .append(", heuristicCachingEnabled=").append(this.heuristicCachingEnabled)
752                 .append(", heuristicCoefficient=").append(this.heuristicCoefficient)
753                 .append(", heuristicDefaultLifetime=").append(this.heuristicDefaultLifetime)
754                 .append(", isSharedCache=").append(this.isSharedCache)
755                 .append(", asynchronousWorkersMax=").append(this.asynchronousWorkersMax)
756                 .append(", asynchronousWorkersCore=").append(this.asynchronousWorkersCore)
757                 .append(", asynchronousWorkerIdleLifetimeSecs=").append(this.asynchronousWorkerIdleLifetimeSecs)
758                 .append(", revalidationQueueSize=").append(this.revalidationQueueSize)
759                 .append(", neverCacheHTTP10ResponsesWithQuery=").append(this.neverCacheHTTP10ResponsesWithQuery)
760                 .append("]");
761         return builder.toString();
762     }
763 
764 }