001package ca.uhn.fhir.rest.client.apache;
002
003/*
004 * #%L
005 * HAPI FHIR - Core Library
006 * %%
007 * Copyright (C) 2014 - 2017 University Health Network
008 * %%
009 * Licensed under the Apache License, Version 2.0 (the "License");
010 * you may not use this file except in compliance with the License.
011 * You may obtain a copy of the License at
012 * 
013 *      http://www.apache.org/licenses/LICENSE-2.0
014 * 
015 * Unless required by applicable law or agreed to in writing, software
016 * distributed under the License is distributed on an "AS IS" BASIS,
017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
018 * See the License for the specific language governing permissions and
019 * limitations under the License.
020 * #L%
021 */
022
023import java.util.List;
024import java.util.Map;
025import java.util.concurrent.TimeUnit;
026
027import org.apache.commons.lang3.StringUtils;
028import org.apache.http.HttpHost;
029import org.apache.http.auth.AuthScope;
030import org.apache.http.auth.UsernamePasswordCredentials;
031import org.apache.http.client.CredentialsProvider;
032import org.apache.http.client.HttpClient;
033import org.apache.http.client.config.RequestConfig;
034import org.apache.http.impl.client.*;
035import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
036
037import ca.uhn.fhir.context.FhirContext;
038import ca.uhn.fhir.rest.api.RequestTypeEnum;
039import ca.uhn.fhir.rest.client.RestfulClientFactory;
040import ca.uhn.fhir.rest.client.api.Header;
041import ca.uhn.fhir.rest.client.api.IHttpClient;
042
043/**
044 * A Restful Factory to create clients, requests and responses based on the Apache httpclient library.
045 * 
046 * @author Peter Van Houte | peter.vanhoute@agfa.com | Agfa Healthcare
047 */
048public class ApacheRestfulClientFactory extends RestfulClientFactory {
049
050        private HttpClient myHttpClient;
051        private HttpHost myProxy;
052
053        /**
054         * Constructor
055         */
056        public ApacheRestfulClientFactory() {
057                super();
058        }
059
060        /**
061         * Constructor
062         * 
063         * @param theContext
064         *            The context
065         */
066        public ApacheRestfulClientFactory(FhirContext theContext) {
067                super(theContext);
068        }
069
070        @Override
071        protected ApacheHttpClient getHttpClient(String theServerBase) {
072                return new ApacheHttpClient(getNativeHttpClient(), new StringBuilder(theServerBase), null, null, null, null);
073        }
074
075        @Override
076        public IHttpClient getHttpClient(StringBuilder theUrl, Map<String, List<String>> theIfNoneExistParams,
077                        String theIfNoneExistString, RequestTypeEnum theRequestType, List<Header> theHeaders) {
078                return new ApacheHttpClient(getNativeHttpClient(), theUrl, theIfNoneExistParams, theIfNoneExistString, theRequestType,
079                                theHeaders);
080        }
081
082        public synchronized HttpClient getNativeHttpClient() {
083                if (myHttpClient == null) {
084
085                        //FIXME potential resoource leak
086                        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000,
087                                        TimeUnit.MILLISECONDS);
088                        connectionManager.setMaxTotal(getPoolMaxTotal());
089                        connectionManager.setDefaultMaxPerRoute(getPoolMaxPerRoute());
090
091                        // @formatter:off
092                        //TODO: Use of a deprecated method should be resolved.
093                        RequestConfig defaultRequestConfig = RequestConfig.custom().setSocketTimeout(getSocketTimeout())
094                                        .setConnectTimeout(getConnectTimeout()).setConnectionRequestTimeout(getConnectionRequestTimeout())
095                                        .setStaleConnectionCheckEnabled(true).setProxy(myProxy).build();
096
097                        HttpClientBuilder builder = HttpClients.custom().setConnectionManager(connectionManager)
098                                        .setDefaultRequestConfig(defaultRequestConfig).disableCookieManagement();
099
100                        if (myProxy != null && StringUtils.isNotBlank(getProxyUsername()) && StringUtils.isNotBlank(getProxyPassword())) {
101                                CredentialsProvider credsProvider = new BasicCredentialsProvider();
102                                credsProvider.setCredentials(new AuthScope(myProxy.getHostName(), myProxy.getPort()),
103                                                new UsernamePasswordCredentials(getProxyUsername(), getProxyPassword()));
104                                builder.setProxyAuthenticationStrategy(new ProxyAuthenticationStrategy());
105                                builder.setDefaultCredentialsProvider(credsProvider);
106                        }
107
108                        myHttpClient = builder.build();
109                        // @formatter:on
110
111                }
112
113                return myHttpClient;
114        }
115
116        @Override
117        protected void resetHttpClient() {
118                this.myHttpClient = null;
119        }
120
121        /**
122         * Only allows to set an instance of type org.apache.http.client.HttpClient
123         * @see ca.uhn.fhir.rest.client.IRestfulClientFactory#setHttpClient(ca.uhn.fhir.rest.client.api.IHttpClient)
124         */
125        @Override
126        public synchronized void setHttpClient(Object theHttpClient) {
127                this.myHttpClient = (HttpClient) theHttpClient;
128        }
129
130        @Override
131        public void setProxy(String theHost, Integer thePort) {
132                if (theHost != null) {
133                        myProxy = new HttpHost(theHost, thePort, "http");
134                } else {
135                        myProxy = null;
136                }
137        }
138
139}