001package ca.uhn.fhir.rest.client.apache;
002
003/*
004 * #%L
005 * HAPI FHIR - Client Framework
006 * %%
007 * Copyright (C) 2014 - 2019 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.io.UnsupportedEncodingException;
024import java.util.*;
025import java.util.Map.Entry;
026
027import org.apache.http.HttpEntity;
028import org.apache.http.NameValuePair;
029import org.apache.http.client.HttpClient;
030import org.apache.http.client.entity.UrlEncodedFormEntity;
031import org.apache.http.client.methods.*;
032import org.apache.http.entity.ByteArrayEntity;
033import org.apache.http.message.BasicNameValuePair;
034
035import ca.uhn.fhir.rest.api.Constants;
036import ca.uhn.fhir.rest.api.RequestTypeEnum;
037import ca.uhn.fhir.rest.client.api.*;
038import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
039
040/**
041 * A Http Client based on Apache. This is an adapter around the class
042 * {@link org.apache.http.client.HttpClient HttpClient}
043 * 
044 * @author Peter Van Houte | peter.vanhoute@agfa.com | Agfa Healthcare
045 */
046public class ApacheHttpClient extends BaseHttpClient implements IHttpClient {
047
048        private HttpClient myClient;
049
050        public ApacheHttpClient(HttpClient theClient, StringBuilder theUrl, Map<String, List<String>> theIfNoneExistParams, String theIfNoneExistString, RequestTypeEnum theRequestType, List<Header> theHeaders) {
051                super(theUrl, theIfNoneExistParams, theIfNoneExistString, theRequestType, theHeaders);
052                this.myClient = theClient;
053        }
054
055        private HttpRequestBase constructRequestBase(HttpEntity theEntity) {
056                String url = myUrl.toString();
057                switch (myRequestType) {
058                case DELETE:
059                        return new HttpDelete(url);
060                case PATCH:
061                        HttpPatch httpPatch = new HttpPatch(url);
062                        httpPatch.setEntity(theEntity);
063                        return httpPatch;
064                case OPTIONS:
065                        return new HttpOptions(url);
066                case POST:
067                        HttpPost httpPost = new HttpPost(url);
068                        httpPost.setEntity(theEntity);
069                        return httpPost;
070                case PUT:
071                        HttpPut httpPut = new HttpPut(url);
072                        httpPut.setEntity(theEntity);
073                        return httpPut;
074                case GET:
075                default:
076                        return new HttpGet(url);
077                }
078        }
079
080
081        private UrlEncodedFormEntity createFormEntity(List<NameValuePair> parameters) {
082                try {
083                        return new UrlEncodedFormEntity(parameters, "UTF-8");
084                } catch (UnsupportedEncodingException e) {
085                        throw new InternalErrorException("Server does not support UTF-8 (should not happen)", e);
086                }
087        }
088
089
090        protected IHttpRequest createHttpRequest() {
091                IHttpRequest retVal = createHttpRequest((HttpEntity)null);
092                return retVal;
093        }
094
095        protected IHttpRequest createHttpRequest(byte[] content) {
096                /*
097                 * Note: Be careful about changing which constructor we use for
098                 * ByteArrayEntity, as Android's version of HTTPClient doesn't support
099                 * the newer ones for whatever reason.
100                 */
101                ByteArrayEntity entity = new ByteArrayEntity(content);
102                IHttpRequest retVal = createHttpRequest(entity);
103                return retVal;
104        }
105
106        private ApacheHttpRequest createHttpRequest(HttpEntity theEntity) {
107                HttpRequestBase request = constructRequestBase(theEntity);
108                ApacheHttpRequest result = new ApacheHttpRequest(myClient, request);
109                return result;
110        }
111
112        protected IHttpRequest createHttpRequest(Map<String, List<String>> theParams) {
113                List<NameValuePair> parameters = new ArrayList<NameValuePair>();
114                for (Entry<String, List<String>> nextParam : theParams.entrySet()) {
115                        List<String> value = nextParam.getValue();
116                        for (String s : value) {
117                                parameters.add(new BasicNameValuePair(nextParam.getKey(), s));
118                        }
119                }
120
121                UrlEncodedFormEntity entity = createFormEntity(parameters);
122                IHttpRequest retVal = createHttpRequest(entity);
123                return retVal;
124        }
125
126
127        protected IHttpRequest createHttpRequest(String theContents) {
128                /*
129                 * We aren't using a StringEntity here because the constructors
130                 * supported by Android aren't available in non-Android, and vice versa.
131                 * Since we add the content type header manually, it makes no difference
132                 * which one we use anyhow.
133                 */
134                ByteArrayEntity entity = new ByteArrayEntity(theContents.getBytes(Constants.CHARSET_UTF8));
135                IHttpRequest retVal = createHttpRequest(entity);
136                return retVal;
137        }
138
139
140
141
142}