View Javadoc

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