1 package com.atlassian.httpclient.apache.httpcomponents;
2
3 import com.atlassian.event.api.EventPublisher;
4 import com.atlassian.httpclient.api.HttpClient;
5 import com.atlassian.httpclient.api.factory.HttpClientFactory;
6 import com.atlassian.httpclient.api.factory.HttpClientOptions;
7 import com.atlassian.sal.api.ApplicationProperties;
8 import com.atlassian.sal.api.executor.ThreadLocalContextManager;
9 import com.google.common.annotations.VisibleForTesting;
10 import org.springframework.beans.factory.DisposableBean;
11
12 import javax.annotation.Nonnull;
13 import java.util.Set;
14 import java.util.concurrent.CopyOnWriteArraySet;
15
16 import static com.google.common.base.Preconditions.checkNotNull;
17
18 public final class DefaultHttpClientFactory<C> implements HttpClientFactory, DisposableBean {
19 private final EventPublisher eventPublisher;
20 private final ApplicationProperties applicationProperties;
21 private final ThreadLocalContextManager<C> threadLocalContextManager;
22 private final Set<ApacheAsyncHttpClient> httpClients = new CopyOnWriteArraySet<ApacheAsyncHttpClient>();
23
24 public DefaultHttpClientFactory(
25 @Nonnull EventPublisher eventPublisher,
26 @Nonnull ApplicationProperties applicationProperties,
27 @Nonnull ThreadLocalContextManager<C> threadLocalContextManager) {
28 this.eventPublisher = checkNotNull(eventPublisher);
29 this.applicationProperties = checkNotNull(applicationProperties);
30 this.threadLocalContextManager = checkNotNull(threadLocalContextManager);
31 }
32
33 @Override
34 @Nonnull
35 public HttpClient create(@Nonnull HttpClientOptions options) {
36 return doCreate(options, threadLocalContextManager);
37 }
38
39 @Override
40 @Nonnull
41 public <C> HttpClient create(@Nonnull HttpClientOptions options, @Nonnull ThreadLocalContextManager<C> threadLocalContextManager) {
42 return doCreate(options, threadLocalContextManager);
43 }
44
45 @Override
46 public void dispose(@Nonnull final HttpClient httpClient) throws Exception {
47 if (httpClient instanceof ApacheAsyncHttpClient) {
48 final ApacheAsyncHttpClient client = (ApacheAsyncHttpClient) httpClient;
49 if (httpClients.remove(client)) {
50 client.destroy();
51 } else {
52 throw new IllegalStateException("Client is already disposed");
53 }
54 } else {
55 throw new IllegalArgumentException("Given client is not disposable");
56 }
57 }
58
59 private <C> HttpClient doCreate(@Nonnull HttpClientOptions options, ThreadLocalContextManager<C> threadLocalContextManager) {
60 checkNotNull(options);
61 final ApacheAsyncHttpClient<C> httpClient = new ApacheAsyncHttpClient<>(eventPublisher, applicationProperties, threadLocalContextManager, options);
62 httpClients.add(httpClient);
63 return httpClient;
64 }
65
66 @Override
67 public void destroy() throws Exception {
68 for (ApacheAsyncHttpClient httpClient : httpClients) {
69 httpClient.destroy();
70 }
71 }
72
73 @VisibleForTesting
74 @Nonnull
75 Iterable<ApacheAsyncHttpClient> getHttpClients() {
76 return httpClients;
77 }
78 }