118118/**
119119 * Default implementation of {@link WebConnection}, using the HttpClient library to perform HTTP requests.
120120 *
121- * @author <a href="mailto:mbowler@GargoyleSoftware.com"> Mike Bowler</a>
121+ * @author Mike Bowler
122122 * @author Noboru Sinohara
123123 * @author David D. Kilzer
124124 * @author Marc Guillemot
@@ -138,7 +138,7 @@ public class HttpWebConnection implements WebConnection {
138138 private static final String HACKED_COOKIE_POLICY = "mine" ;
139139
140140 // have one per thread because this is (re)configured for every call (see configureHttpProcessorBuilder)
141- // do not use a ThreadLocal because this in only accessed form this class
141+ // do not use a ThreadLocal because this in only accessed form this class, but we still need it synchronized
142142 private final Map <Thread , HttpClientBuilder > httpClientBuilder_ = new WeakHashMap <>();
143143 private final WebClient webClient_ ;
144144
@@ -212,7 +212,9 @@ public WebResponse getResponse(final WebRequest webRequest) throws IOException {
212212 // Calling code may catch the StackOverflowError, but due to the leak, the httpClient_ may
213213 // come out of connections and throw a ConnectionPoolTimeoutException.
214214 // => best solution, discard the HttpClient instance.
215- httpClientBuilder_ .remove (Thread .currentThread ());
215+ synchronized (httpClientBuilder_ ) {
216+ httpClientBuilder_ .remove (Thread .currentThread ());
217+ }
216218 throw e ;
217219 }
218220 }
@@ -427,7 +429,8 @@ private static Charset getCharset(final Charset charset, final List<NameValuePai
427429 final KeyDataPair pairWithFile = (KeyDataPair ) pair ;
428430 if (pairWithFile .getData () == null && pairWithFile .getFile () != null ) {
429431 final String fileName = pairWithFile .getFile ().getName ();
430- for (int i = 0 ; i < fileName .length (); i ++) {
432+ final int length = fileName .length ();
433+ for (int i = 0 ; i < length ; i ++) {
431434 if (fileName .codePointAt (i ) > 127 ) {
432435 return charset ;
433436 }
@@ -532,23 +535,26 @@ protected HttpRequestBase buildHttpMethod(final HttpMethod submitMethod, final U
532535 */
533536 protected HttpClientBuilder getHttpClientBuilder () {
534537 final Thread currentThread = Thread .currentThread ();
535- HttpClientBuilder builder = httpClientBuilder_ .get (currentThread );
536- if (builder == null ) {
537- builder = createHttpClientBuilder ();
538538
539- // this factory is required later
540- // to be sure this is done, we do it outside the createHttpClient() call
541- final RegistryBuilder <CookieSpecProvider > registeryBuilder
542- = RegistryBuilder .<CookieSpecProvider >create ()
543- .register (HACKED_COOKIE_POLICY , htmlUnitCookieSpecProvider_ );
544- builder .setDefaultCookieSpecRegistry (registeryBuilder .build ());
539+ synchronized (httpClientBuilder_ ) {
540+ HttpClientBuilder builder = httpClientBuilder_ .get (currentThread );
541+ if (builder == null ) {
542+ builder = createHttpClientBuilder ();
543+
544+ // this factory is required later
545+ // to be sure this is done, we do it outside the createHttpClient() call
546+ final RegistryBuilder <CookieSpecProvider > registeryBuilder
547+ = RegistryBuilder .<CookieSpecProvider >create ()
548+ .register (HACKED_COOKIE_POLICY , htmlUnitCookieSpecProvider_ );
549+ builder .setDefaultCookieSpecRegistry (registeryBuilder .build ());
550+
551+ builder .setDefaultCookieStore (new HtmlUnitCookieStore (webClient_ .getCookieManager ()));
552+ builder .setUserAgent (webClient_ .getBrowserVersion ().getUserAgent ());
553+ httpClientBuilder_ .put (currentThread , builder );
554+ }
545555
546- builder .setDefaultCookieStore (new HtmlUnitCookieStore (webClient_ .getCookieManager ()));
547- builder .setUserAgent (webClient_ .getBrowserVersion ().getUserAgent ());
548- httpClientBuilder_ .put (currentThread , builder );
556+ return builder ;
549557 }
550-
551- return builder ;
552558 }
553559
554560 /**
@@ -1288,7 +1294,11 @@ public synchronized String toString() {
12881294 */
12891295 @ Override
12901296 public void close () {
1291- httpClientBuilder_ .clear ();
1297+ synchronized (httpClientBuilder_ ) {
1298+ httpClientBuilder_ .clear ();
1299+ }
1300+ sharedAuthCache_ .clear ();
1301+ httpClientContextByThread_ .clear ();
12921302
12931303 if (connectionManager_ != null ) {
12941304 connectionManager_ .shutdown ();
0 commit comments