View Javadoc

1   package com.atlassian.httpclient.api.factory;
2   
3   import com.atlassian.httpclient.api.HostResolver;
4   import com.atlassian.httpclient.api.Request;
5   import com.atlassian.util.concurrent.Effect;
6   import com.atlassian.util.concurrent.Effects;
7   import com.atlassian.util.concurrent.ThreadFactories;
8   import com.google.common.base.Preconditions;
9   import com.google.common.collect.ImmutableList;
10  import org.slf4j.Logger;
11  import org.slf4j.LoggerFactory;
12  
13  import javax.annotation.Nonnull;
14  import java.util.Collections;
15  import java.util.List;
16  import java.util.concurrent.*;
17  
18  /**
19   * Configuration options for the http client instance and its caching system
20   */
21  public final class HttpClientOptions {
22      public static final String OPTION_PROPERTY_PREFIX = "com.atlassian.httpclient.options";
23      public static final String OPTION_THREAD_WORK_QUEUE_LIMIT = OPTION_PROPERTY_PREFIX + ".threadWorkQueueLimit";
24  
25      private final Logger log = LoggerFactory.getLogger(this.getClass());
26      private List<String> blacklistedAddresses;
27  
28      private String threadPrefix = "httpclient";
29      private boolean ignoreCookies = false;
30      private int ioThreadCount = Integer.getInteger(OPTION_PROPERTY_PREFIX + ".ioThreadCount", 10);
31      private long ioSelectInterval = Integer.getInteger(OPTION_PROPERTY_PREFIX + ".ioSelectInterval", 1000);
32      private int threadWorkQueueLimit = Integer.getInteger(OPTION_THREAD_WORK_QUEUE_LIMIT, 256);
33  
34      private long connectionTimeout = 5 * 1000;
35      private long socketTimeout = 20 * 1000;
36      private long requestTimeout = 30 * 3000;
37  
38      private int maxTotalConnections = 20;
39      private int maxConnectionsPerHost = 20;
40  
41      private long connectionPoolTimeToLive = 30 * 1000;
42  
43      private long maxCacheObjectSize = 100 * 1024L;
44      private int maxCacheEntries = 100;
45  
46      private long maxEntitySize = 1024 * 1024 * 100;
47  
48      private long leaseTimeout = 10 * 60 * 1000; // 10 mins
49      private int maxCallbackThreadPoolSize = 16;
50  
51      private boolean trustSelfSignedCertificates = false;
52  
53      private Effect<Request> requestPreparer = Effects.noop();
54  
55      private String userAgent = "Default";
56  
57      private ExecutorService callbackExecutor;
58  
59      private ProxyOptions proxyOptions = ProxyOptions.ProxyOptionsBuilder.create().build();
60  
61      private HostResolver hostResolver;
62  
63      /**
64       * Whether or not to ignore cookies.
65       * <p/>
66       * Default: <code>false</code>
67       */
68      public boolean getIgnoreCookies() {
69          return ignoreCookies;
70      }
71  
72      /**
73       * @param ignoreCookies Whether or not to ignore cookies.
74       */
75      public void setIgnoreCookies(boolean ignoreCookies) {
76          this.ignoreCookies = ignoreCookies;
77      }
78  
79      /**
80       * Determines the number of I/O dispatch threads to be used by the I/O reactor.
81       * <p/>
82       * Default: <code>10</code>
83       */
84      public int getIoThreadCount() {
85          return ioThreadCount;
86      }
87  
88      /**
89       * @param ioThreadCount The number of I/O dispatch threads to be used by the I/O reactor.
90       *                      May not be negative or zero.
91       */
92      public void setIoThreadCount(int ioThreadCount) {
93          this.ioThreadCount = ioThreadCount;
94      }
95  
96      /**
97       * Determines time interval in milliseconds at which the I/O reactor wakes up to check for
98       * timed out sessions and session requests.
99       * <p/>
100      * Default: <code>1000</code> milliseconds.
101      */
102     public long getIoSelectInterval() {
103         return ioSelectInterval;
104     }
105 
106     /**
107      * Defines time interval in milliseconds at which the I/O reactor wakes up to check for
108      * timed out sessions and session requests. May not be negative or zero.
109      */
110     public void setIoSelectInterval(int ioSelectInterval, TimeUnit timeUnit) {
111         this.ioSelectInterval = timeUnit.toMillis(ioSelectInterval);
112     }
113 
114     /**
115      * @return How long, in milliseconds, to wait for a TCP connection
116      */
117     public long getConnectionTimeout() {
118         return connectionTimeout;
119     }
120 
121     /**
122      * Sets how long, in milliseconds, to wait for a TCP connection
123      *
124      * @param connectionTimeout Timeout value, defaults to 5000 milliseconds
125      * @param timeUnit          The time unit
126      */
127     public void setConnectionTimeout(int connectionTimeout, TimeUnit timeUnit) {
128         this.connectionTimeout = timeUnit.toMillis(connectionTimeout);
129     }
130 
131     /**
132      * @return How long, in milliseconds, to wait for data over the socket
133      */
134     public long getSocketTimeout() {
135         return socketTimeout;
136     }
137 
138     /**
139      * @param socketTimeout How long to wait for data, defaults to 20 seconds
140      * @param timeUnit      The time unit
141      */
142     public void setSocketTimeout(int socketTimeout, TimeUnit timeUnit) {
143         this.socketTimeout = timeUnit.toMillis(socketTimeout);
144     }
145 
146     /**
147      * @return How long to wait for the entire request
148      */
149     public long getRequestTimeout() {
150         return requestTimeout;
151     }
152 
153     /**
154      * @param requestTimeout How long to wait for the entire request.  Defaults to 30 seconds.
155      * @param timeUnit       The time unit
156      */
157     public void setRequestTimeout(int requestTimeout, TimeUnit timeUnit) {
158         this.requestTimeout = timeUnit.toMillis(requestTimeout);
159     }
160 
161     /**
162      * @return The user agent string
163      */
164     public String getUserAgent() {
165         return userAgent;
166     }
167 
168     /**
169      * @param userAgent The user agent string
170      */
171     public void setUserAgent(String userAgent) {
172         this.userAgent = userAgent;
173     }
174 
175     /**
176      * @return Name prefix to use for spawned threads
177      */
178     public String getThreadPrefix() {
179         return threadPrefix;
180     }
181 
182     /**
183      * @param blacklistedAddresses a list of addresses or cidr ranges that this http client cannot connect to
184      */
185     public void setBlacklistedAddresses(@Nonnull List<String> blacklistedAddresses) {
186         this.blacklistedAddresses = Collections.unmodifiableList(blacklistedAddresses);
187     }
188 
189     @Nonnull
190     public List<String> getBlacklistedAddresses() {
191         if (blacklistedAddresses == null) {
192             return ImmutableList.of();
193         }
194         return blacklistedAddresses;
195     }
196 
197     /**
198      * @param threadPrefix Name prefix to use for spawned threads
199      */
200     public void setThreadPrefix(String threadPrefix) {
201         this.threadPrefix = threadPrefix;
202     }
203 
204     /**
205      * @return How long, in milliseconds, to allow connections to live in the pool.  Defaults
206      * to 30 seconds.
207      */
208     public long getConnectionPoolTimeToLive() {
209         return connectionPoolTimeToLive;
210     }
211 
212     /**
213      * @param connectionPoolTimeToLive How long to allow connections to live in the pool
214      * @param timeUnit                 The time unit
215      */
216     public void setConnectionPoolTimeToLive(int connectionPoolTimeToLive, TimeUnit timeUnit) {
217         this.connectionPoolTimeToLive = timeUnit.toMillis(connectionPoolTimeToLive);
218     }
219 
220     /**
221      * @return How many simultaneous connections are allowed in total. Defaults to 20
222      */
223     public int getMaxTotalConnections() {
224         return maxTotalConnections;
225     }
226 
227     /**
228      * @param maxTotalConnections How many simultaneous connections are allowed in total
229      */
230     public void setMaxTotalConnections(int maxTotalConnections) {
231         this.maxTotalConnections = maxTotalConnections;
232     }
233 
234     /**
235      * @return How many simultaneous connections are allowed per host. Defaults to 20
236      */
237     public int getMaxConnectionsPerHost() {
238         return maxConnectionsPerHost;
239     }
240 
241     /**
242      * @param maxConnectionsPerHost How many connections are allowed per host
243      */
244     public void setMaxConnectionsPerHost(int maxConnectionsPerHost) {
245         this.maxConnectionsPerHost = maxConnectionsPerHost;
246     }
247 
248     /**
249      * @return The max object size, in bytes, allowed in the HTTP cache.  Defaults to 100k
250      */
251     public long getMaxCacheObjectSize() {
252         return maxCacheObjectSize;
253     }
254 
255     /**
256      * @param maxCacheObjectSize The max cache object size in bytes
257      */
258     public void setMaxCacheObjectSize(long maxCacheObjectSize) {
259         this.maxCacheObjectSize = maxCacheObjectSize;
260     }
261 
262     /**
263      * @return The max cache entries.  Defaults to 1000.
264      */
265     public int getMaxCacheEntries() {
266         return maxCacheEntries;
267     }
268 
269     /**
270      * @param maxCacheEntries The max cache entries
271      */
272     public void setMaxCacheEntries(int maxCacheEntries) {
273         this.maxCacheEntries = maxCacheEntries;
274     }
275 
276     /**
277      * @return The effect to apply before the request is executed
278      */
279     public Effect<Request> getRequestPreparer() {
280         return requestPreparer;
281     }
282 
283     /**
284      * @param requestPreparer The effect to apply before the request is executed
285      */
286     public void setRequestPreparer(Effect<Request> requestPreparer) {
287         this.requestPreparer = requestPreparer;
288     }
289 
290     /**
291      * @return The maximum entity size in bytes.  Default is 100MB
292      */
293     public long getMaxEntitySize() {
294         return maxEntitySize;
295     }
296 
297     /**
298      * @return The maximum time request to be kept in queue before execution, after timeout - request will be removed
299      */
300     public long getLeaseTimeout() {
301         return leaseTimeout;
302     }
303 
304     /**
305      * @param leaseTimeout The maximum time request to be kept in queue before execution, after timeout - request will be removed
306      */
307     public void setLeaseTimeout(long leaseTimeout) {
308         this.leaseTimeout = leaseTimeout;
309     }
310 
311     /**
312      * param maxEntitySize The maximum entity size in bytes
313      */
314     public void setMaxEntitySize(long maxEntitySize) {
315         this.maxEntitySize = maxEntitySize;
316     }
317 
318     /**
319      * @return The maximum number of threads that can be used for executing callbacks
320      */
321     public int getMaxCallbackThreadPoolSize() {
322         return maxCallbackThreadPoolSize;
323     }
324 
325     /**
326      * @param maxCallbackThreadPoolSize The maximum number of threads that can be used for executing callbacks
327      */
328     public void setMaxCallbackThreadPoolSize(final int maxCallbackThreadPoolSize) {
329         this.maxCallbackThreadPoolSize = maxCallbackThreadPoolSize;
330     }
331 
332     public void setCallbackExecutor(ExecutorService callbackExecutor) {
333         this.callbackExecutor = callbackExecutor;
334     }
335 
336     public ExecutorService getCallbackExecutor() {
337         return callbackExecutor != null ? callbackExecutor : defaultCallbackExecutor();
338     }
339 
340     private ExecutorService defaultCallbackExecutor() {
341         ThreadFactory threadFactory = ThreadFactories.namedThreadFactory(getThreadPrefix() + "-callbacks", ThreadFactories.Type.DAEMON);
342         return new ThreadPoolExecutor(
343                 0,
344                 getMaxCallbackThreadPoolSize(),
345                 60L,
346                 TimeUnit.SECONDS,
347                 new LinkedBlockingQueue<Runnable>(threadWorkQueueLimit),
348                 threadFactory,
349                 (r, e) -> log.warn(
350                         "Exceeded the limit of requests waiting for execution. " +
351                                 " Increase the value of the system property {} to prevent these situations in the " +
352                                 "future. Current value of {} = {}.",
353                         OPTION_THREAD_WORK_QUEUE_LIMIT,
354                         OPTION_THREAD_WORK_QUEUE_LIMIT,
355                         threadWorkQueueLimit)
356         );
357     }
358 
359     public void setTrustSelfSignedCertificates(boolean trustSelfSignedCertificates) {
360         this.trustSelfSignedCertificates = trustSelfSignedCertificates;
361     }
362 
363     /**
364      * @return whether self signed certificates are trusted.
365      */
366     public boolean trustSelfSignedCertificates() {
367         return trustSelfSignedCertificates;
368     }
369 
370     /**
371      * Set proxy options for the client
372      *
373      * @param proxyOptions Proxy options created using {@link com.atlassian.httpclient.api.factory.ProxyOptions.ProxyOptionsBuilder}.
374      */
375     public void setProxyOptions(final @Nonnull ProxyOptions proxyOptions) {
376         Preconditions.checkNotNull(proxyOptions, "Proxy options cannot be null");
377         this.proxyOptions = proxyOptions;
378     }
379 
380     /**
381      * @return The proxy options to use for the client.
382      */
383     public ProxyOptions getProxyOptions() {
384         return this.proxyOptions;
385     }
386 
387     public int getThreadWorkQueueLimit() {
388         return threadWorkQueueLimit;
389     }
390 
391     public void setThreadWorkQueueLimit(int threadWorkQueueLimit) {
392         this.threadWorkQueueLimit = threadWorkQueueLimit;
393     }
394 }