001/* 002 * ==================================================================== 003 * Licensed to the Apache Software Foundation (ASF) under one 004 * or more contributor license agreements. See the NOTICE file 005 * distributed with this work for additional information 006 * regarding copyright ownership. The ASF licenses this file 007 * to you under the Apache License, Version 2.0 (the 008 * "License"); you may not use this file except in compliance 009 * with the License. You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, 014 * software distributed under the License is distributed on an 015 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 016 * KIND, either express or implied. See the License for the 017 * specific language governing permissions and limitations 018 * under the License. 019 * ==================================================================== 020 * 021 * This software consists of voluntary contributions made by many 022 * individuals on behalf of the Apache Software Foundation. For more 023 * information on the Apache Software Foundation, please see 024 * <http://www.apache.org/>. 025 * 026 */ 027 028package org.apache.http.impl.client; 029 030import java.io.Closeable; 031import java.io.IOException; 032import java.util.List; 033import java.util.concurrent.TimeUnit; 034 035import org.apache.commons.logging.Log; 036import org.apache.commons.logging.LogFactory; 037import org.apache.http.HttpException; 038import org.apache.http.HttpHost; 039import org.apache.http.HttpRequest; 040import org.apache.http.annotation.Contract; 041import org.apache.http.annotation.ThreadingBehavior; 042import org.apache.http.auth.AuthSchemeProvider; 043import org.apache.http.auth.AuthState; 044import org.apache.http.client.ClientProtocolException; 045import org.apache.http.client.CookieStore; 046import org.apache.http.client.CredentialsProvider; 047import org.apache.http.client.config.RequestConfig; 048import org.apache.http.client.methods.CloseableHttpResponse; 049import org.apache.http.client.methods.Configurable; 050import org.apache.http.client.methods.HttpExecutionAware; 051import org.apache.http.client.methods.HttpRequestWrapper; 052import org.apache.http.client.params.ClientPNames; 053import org.apache.http.client.params.HttpClientParamConfig; 054import org.apache.http.client.protocol.HttpClientContext; 055import org.apache.http.config.Lookup; 056import org.apache.http.conn.ClientConnectionManager; 057import org.apache.http.conn.ClientConnectionRequest; 058import org.apache.http.conn.HttpClientConnectionManager; 059import org.apache.http.conn.ManagedClientConnection; 060import org.apache.http.conn.routing.HttpRoute; 061import org.apache.http.conn.routing.HttpRoutePlanner; 062import org.apache.http.conn.scheme.SchemeRegistry; 063import org.apache.http.cookie.CookieSpecProvider; 064import org.apache.http.impl.execchain.ClientExecChain; 065import org.apache.http.params.HttpParams; 066import org.apache.http.params.HttpParamsNames; 067import org.apache.http.protocol.BasicHttpContext; 068import org.apache.http.protocol.HttpContext; 069import org.apache.http.util.Args; 070 071/** 072 * Internal class. 073 * 074 * @since 4.3 075 */ 076@Contract(threading = ThreadingBehavior.SAFE_CONDITIONAL) 077@SuppressWarnings("deprecation") 078class InternalHttpClient extends CloseableHttpClient implements Configurable { 079 080 private final Log log = LogFactory.getLog(getClass()); 081 082 private final ClientExecChain execChain; 083 private final HttpClientConnectionManager connManager; 084 private final HttpRoutePlanner routePlanner; 085 private final Lookup<CookieSpecProvider> cookieSpecRegistry; 086 private final Lookup<AuthSchemeProvider> authSchemeRegistry; 087 private final CookieStore cookieStore; 088 private final CredentialsProvider credentialsProvider; 089 private final RequestConfig defaultConfig; 090 private final List<Closeable> closeables; 091 092 public InternalHttpClient( 093 final ClientExecChain execChain, 094 final HttpClientConnectionManager connManager, 095 final HttpRoutePlanner routePlanner, 096 final Lookup<CookieSpecProvider> cookieSpecRegistry, 097 final Lookup<AuthSchemeProvider> authSchemeRegistry, 098 final CookieStore cookieStore, 099 final CredentialsProvider credentialsProvider, 100 final RequestConfig defaultConfig, 101 final List<Closeable> closeables) { 102 super(); 103 Args.notNull(execChain, "HTTP client exec chain"); 104 Args.notNull(connManager, "HTTP connection manager"); 105 Args.notNull(routePlanner, "HTTP route planner"); 106 this.execChain = execChain; 107 this.connManager = connManager; 108 this.routePlanner = routePlanner; 109 this.cookieSpecRegistry = cookieSpecRegistry; 110 this.authSchemeRegistry = authSchemeRegistry; 111 this.cookieStore = cookieStore; 112 this.credentialsProvider = credentialsProvider; 113 this.defaultConfig = defaultConfig; 114 this.closeables = closeables; 115 } 116 117 private HttpRoute determineRoute( 118 final HttpHost target, 119 final HttpRequest request, 120 final HttpContext context) throws HttpException { 121 HttpHost host = target; 122 if (host == null) { 123 host = (HttpHost) request.getParams().getParameter(ClientPNames.DEFAULT_HOST); 124 } 125 return this.routePlanner.determineRoute(host, request, context); 126 } 127 128 private void setupContext(final HttpClientContext context) { 129 if (context.getAttribute(HttpClientContext.TARGET_AUTH_STATE) == null) { 130 context.setAttribute(HttpClientContext.TARGET_AUTH_STATE, new AuthState()); 131 } 132 if (context.getAttribute(HttpClientContext.PROXY_AUTH_STATE) == null) { 133 context.setAttribute(HttpClientContext.PROXY_AUTH_STATE, new AuthState()); 134 } 135 if (context.getAttribute(HttpClientContext.AUTHSCHEME_REGISTRY) == null) { 136 context.setAttribute(HttpClientContext.AUTHSCHEME_REGISTRY, this.authSchemeRegistry); 137 } 138 if (context.getAttribute(HttpClientContext.COOKIESPEC_REGISTRY) == null) { 139 context.setAttribute(HttpClientContext.COOKIESPEC_REGISTRY, this.cookieSpecRegistry); 140 } 141 if (context.getAttribute(HttpClientContext.COOKIE_STORE) == null) { 142 context.setAttribute(HttpClientContext.COOKIE_STORE, this.cookieStore); 143 } 144 if (context.getAttribute(HttpClientContext.CREDS_PROVIDER) == null) { 145 context.setAttribute(HttpClientContext.CREDS_PROVIDER, this.credentialsProvider); 146 } 147 if (context.getAttribute(HttpClientContext.REQUEST_CONFIG) == null) { 148 context.setAttribute(HttpClientContext.REQUEST_CONFIG, this.defaultConfig); 149 } 150 } 151 152 @Override 153 protected CloseableHttpResponse doExecute( 154 final HttpHost target, 155 final HttpRequest request, 156 final HttpContext context) throws IOException, ClientProtocolException { 157 Args.notNull(request, "HTTP request"); 158 HttpExecutionAware execAware = null; 159 if (request instanceof HttpExecutionAware) { 160 execAware = (HttpExecutionAware) request; 161 } 162 try { 163 final HttpRequestWrapper wrapper = HttpRequestWrapper.wrap(request, target); 164 final HttpClientContext localcontext = HttpClientContext.adapt( 165 context != null ? context : new BasicHttpContext()); 166 RequestConfig config = null; 167 if (request instanceof Configurable) { 168 config = ((Configurable) request).getConfig(); 169 } 170 if (config == null) { 171 final HttpParams params = request.getParams(); 172 if (params instanceof HttpParamsNames) { 173 if (!((HttpParamsNames) params).getNames().isEmpty()) { 174 config = HttpClientParamConfig.getRequestConfig(params, this.defaultConfig); 175 } 176 } else { 177 config = HttpClientParamConfig.getRequestConfig(params, this.defaultConfig); 178 } 179 } 180 if (config != null) { 181 localcontext.setRequestConfig(config); 182 } 183 setupContext(localcontext); 184 final HttpRoute route = determineRoute(target, wrapper, localcontext); 185 return this.execChain.execute(route, wrapper, localcontext, execAware); 186 } catch (final HttpException httpException) { 187 throw new ClientProtocolException(httpException); 188 } 189 } 190 191 @Override 192 public RequestConfig getConfig() { 193 return this.defaultConfig; 194 } 195 196 @Override 197 public void close() { 198 if (this.closeables != null) { 199 for (final Closeable closeable: this.closeables) { 200 try { 201 closeable.close(); 202 } catch (final IOException ex) { 203 this.log.error(ex.getMessage(), ex); 204 } 205 } 206 } 207 } 208 209 @Override 210 public HttpParams getParams() { 211 throw new UnsupportedOperationException(); 212 } 213 214 @Override 215 public ClientConnectionManager getConnectionManager() { 216 217 return new ClientConnectionManager() { 218 219 @Override 220 public void shutdown() { 221 connManager.shutdown(); 222 } 223 224 @Override 225 public ClientConnectionRequest requestConnection( 226 final HttpRoute route, final Object state) { 227 throw new UnsupportedOperationException(); 228 } 229 230 @Override 231 public void releaseConnection( 232 final ManagedClientConnection conn, 233 final long validDuration, final TimeUnit timeUnit) { 234 throw new UnsupportedOperationException(); 235 } 236 237 @Override 238 public SchemeRegistry getSchemeRegistry() { 239 throw new UnsupportedOperationException(); 240 } 241 242 @Override 243 public void closeIdleConnections(final long idletime, final TimeUnit tunit) { 244 connManager.closeIdleConnections(idletime, tunit); 245 } 246 247 @Override 248 public void closeExpiredConnections() { 249 connManager.closeExpiredConnections(); 250 } 251 252 }; 253 254 } 255 256}