1 package ca.uhn.fhir.rest.client;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 import java.lang.reflect.InvocationHandler;
24 import java.lang.reflect.Method;
25 import java.lang.reflect.Proxy;
26 import java.util.HashMap;
27 import java.util.Map;
28 import java.util.concurrent.TimeUnit;
29
30 import org.apache.http.HttpHost;
31 import org.apache.http.client.HttpClient;
32 import org.apache.http.client.config.RequestConfig;
33 import org.apache.http.impl.client.HttpClients;
34 import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
35
36 import ca.uhn.fhir.context.ConfigurationException;
37 import ca.uhn.fhir.context.FhirContext;
38 import ca.uhn.fhir.rest.client.api.IRestfulClient;
39 import ca.uhn.fhir.rest.method.BaseMethodBinding;
40
41 public class RestfulClientFactory implements IRestfulClientFactory {
42
43 private int myConnectionRequestTimeout = 10000;
44 private int myConnectTimeout = 10000;
45 private FhirContext myContext;
46 private HttpClient myHttpClient;
47 private Map<Class<? extends IRestfulClient>, ClientInvocationHandler> myInvocationHandlers = new HashMap<Class<? extends IRestfulClient>, ClientInvocationHandler>();
48 private int mySocketTimeout = 10000;
49 private HttpHost myProxy;
50
51 @Override
52 public void setProxy(String theHost, Integer thePort) {
53 if (theHost != null) {
54 myProxy = new HttpHost(theHost, thePort, "http");
55 } else {
56 myProxy = null;
57 }
58 }
59
60
61
62
63
64
65
66 public RestfulClientFactory(FhirContext theFhirContext) {
67 myContext = theFhirContext;
68 }
69
70
71
72
73 public RestfulClientFactory() {
74 }
75
76
77
78
79 public void setFhirContext(FhirContext theContext) {
80 if (myContext != null && myContext != theContext) {
81 throw new IllegalStateException("RestfulClientFactory instance is already associated with one FhirContext. RestfulClientFactory instances can not be shared.");
82 }
83 myContext = theContext;
84 }
85
86 public int getConnectionRequestTimeout() {
87 return myConnectionRequestTimeout;
88 }
89
90 public int getConnectTimeout() {
91 return myConnectTimeout;
92 }
93
94 @Override
95 public synchronized HttpClient getHttpClient() {
96 if (myHttpClient == null) {
97
98 PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
99
100
101 RequestConfig defaultRequestConfig = RequestConfig.custom()
102 .setSocketTimeout(mySocketTimeout)
103 .setConnectTimeout(myConnectTimeout)
104 .setConnectionRequestTimeout(myConnectionRequestTimeout)
105 .setStaleConnectionCheckEnabled(true)
106 .setProxy(myProxy)
107 .build();
108
109 myHttpClient = HttpClients.custom()
110 .setConnectionManager(connectionManager)
111 .setDefaultRequestConfig(defaultRequestConfig)
112 .disableCookieManagement()
113 .build();
114
115
116 }
117
118 return myHttpClient;
119 }
120
121 public int getSocketTimeout() {
122 return mySocketTimeout;
123 }
124
125
126
127
128
129
130
131
132
133
134
135
136 @Override
137 public synchronized <T extends IRestfulClient> T newClient(Class<T> theClientType, String theServerBase) {
138 if (!theClientType.isInterface()) {
139 throw new ConfigurationException(theClientType.getCanonicalName() + " is not an interface");
140 }
141
142 HttpClient client = getHttpClient();
143
144 String serverBase = theServerBase;
145 if (!serverBase.endsWith("/")) {
146 serverBase = serverBase + "/";
147 }
148
149 ClientInvocationHandler invocationHandler = myInvocationHandlers.get(theClientType);
150 if (invocationHandler == null) {
151 invocationHandler = new ClientInvocationHandler(client, myContext, serverBase, theClientType);
152 for (Method nextMethod : theClientType.getMethods()) {
153 BaseMethodBinding<?> binding = BaseMethodBinding.bindMethod(nextMethod, myContext, null);
154 invocationHandler.addBinding(nextMethod, binding);
155 }
156 myInvocationHandlers.put(theClientType, invocationHandler);
157 }
158
159 T proxy = instantiateProxy(theClientType, invocationHandler);
160
161 return proxy;
162 }
163
164 @Override
165 public IGenericClient newGenericClient(String theServerBase) {
166 return new GenericClient(myContext, getHttpClient(), theServerBase);
167 }
168
169 @Override
170 public synchronized void setConnectionRequestTimeout(int theConnectionRequestTimeout) {
171 myConnectionRequestTimeout = theConnectionRequestTimeout;
172 myHttpClient = null;
173 }
174
175 @Override
176 public synchronized void setConnectTimeout(int theConnectTimeout) {
177 myConnectTimeout = theConnectTimeout;
178 myHttpClient = null;
179 }
180
181
182
183
184
185
186
187
188 @Override
189 public synchronized void setHttpClient(HttpClient theHttpClient) {
190 myHttpClient = theHttpClient;
191 }
192
193 @Override
194 public synchronized void setSocketTimeout(int theSocketTimeout) {
195 mySocketTimeout = theSocketTimeout;
196 myHttpClient = null;
197 }
198
199 @SuppressWarnings("unchecked")
200 private <T extends IRestfulClient> T instantiateProxy(Class<T> theClientType, InvocationHandler theInvocationHandler) {
201 T proxy = (T) Proxy.newProxyInstance(theClientType.getClassLoader(), new Class[] { theClientType }, theInvocationHandler);
202 return proxy;
203 }
204
205 }