001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.juneau.rest.client;
018
019import static java.lang.Character.isWhitespace;
020import static java.util.logging.Level.*;
021import static org.apache.juneau.commons.lang.StateEnum.*;
022import static org.apache.juneau.commons.utils.AssertionUtils.*;
023import static org.apache.juneau.commons.utils.CollectionUtils.*;
024import static org.apache.juneau.commons.utils.StringUtils.*;
025import static org.apache.juneau.commons.utils.ThrowableUtils.*;
026import static org.apache.juneau.commons.utils.Utils.*;
027import static org.apache.juneau.http.HttpEntities.*;
028import static org.apache.juneau.http.HttpHeaders.*;
029import static org.apache.juneau.http.HttpMethod.*;
030import static org.apache.juneau.http.HttpParts.*;
031import static org.apache.juneau.httppart.HttpPartType.*;
032import static org.apache.juneau.rest.client.RestOperation.*;
033
034import java.io.*;
035import java.lang.annotation.Annotation;
036import java.lang.reflect.*;
037import java.lang.reflect.Proxy;
038import java.net.*;
039import java.nio.charset.*;
040import java.text.*;
041import java.util.*;
042import java.util.concurrent.*;
043import java.util.concurrent.atomic.*;
044import java.util.function.*;
045import java.util.logging.*;
046import java.util.regex.*;
047
048import javax.net.ssl.*;
049
050import org.apache.http.*;
051import org.apache.http.auth.*;
052import org.apache.http.client.*;
053import org.apache.http.client.CookieStore;
054import org.apache.http.client.config.*;
055import org.apache.http.client.entity.*;
056import org.apache.http.client.methods.*;
057import org.apache.http.client.utils.*;
058import org.apache.http.config.*;
059import org.apache.http.conn.*;
060import org.apache.http.conn.routing.*;
061import org.apache.http.conn.socket.*;
062import org.apache.http.conn.util.*;
063import org.apache.http.cookie.*;
064import org.apache.http.impl.client.*;
065import org.apache.http.impl.conn.*;
066import org.apache.http.params.*;
067import org.apache.http.protocol.*;
068import org.apache.juneau.*;
069import org.apache.juneau.annotation.*;
070import org.apache.juneau.collections.*;
071import org.apache.juneau.commons.collections.*;
072import org.apache.juneau.commons.collections.FluentMap;
073import org.apache.juneau.commons.function.*;
074import org.apache.juneau.commons.reflect.*;
075import org.apache.juneau.cp.*;
076import org.apache.juneau.html.*;
077import org.apache.juneau.http.entity.*;
078import org.apache.juneau.http.header.*;
079import org.apache.juneau.http.part.*;
080import org.apache.juneau.http.remote.*;
081import org.apache.juneau.http.resource.*;
082import org.apache.juneau.httppart.*;
083import org.apache.juneau.json.*;
084import org.apache.juneau.marshaller.*;
085import org.apache.juneau.msgpack.*;
086import org.apache.juneau.oapi.*;
087import org.apache.juneau.objecttools.*;
088import org.apache.juneau.parser.*;
089import org.apache.juneau.parser.ParseException;
090import org.apache.juneau.plaintext.*;
091import org.apache.juneau.rest.client.assertion.*;
092import org.apache.juneau.rest.client.remote.*;
093import org.apache.juneau.serializer.*;
094import org.apache.juneau.uon.*;
095import org.apache.juneau.urlencoding.*;
096import org.apache.juneau.xml.*;
097
098/**
099 * Utility class for interfacing with remote REST interfaces.
100 *
101 * <p>
102 * Built upon the feature-rich Apache HttpClient library, the Juneau RestClient API adds support for fluent-style
103 * REST calls and the ability to perform marshalling of POJOs to and from HTTP parts.
104 *
105 * <h5 class='figure'>Example:</h5>
106 * <p class='bjava'>
107 *    <jc>// Create a basic REST client with JSON support and download a bean.</jc>
108 *    MyBean <jv>bean</jv> = RestClient.<jsm>create</jsm>()
109 *       .json5()
110 *       .build()
111 *       .get(<jsf>URI</jsf>)
112 *       .run()
113 *       .assertStatus().asCode().is(200)
114 *       .assertHeader(<js>"Content-Type"</js>).matchesSimple(<js>"application/json*"</js>)
115 *       .getContent().as(MyBean.<jk>class</jk>);
116 * </p>
117 *
118 * <p>
119 * Breaking apart the fluent call, we can see the classes being used:
120 * <p class='bjava'>
121 *    RestClient.Builder <jv>builder</jv> = RestClient.<jsm>create</jsm>().json5();
122 *    RestClient <jv>client</jv> = <jv>builder</jv>.build();
123 *    RestRequest <jv>req</jv> = <jv>client</jv>.get(<jsf>URI</jsf>);
124 *    RestResponse <jv>res</jv> = <jv>req</jv>.run();
125 *    RestResponseStatusLineAssertion <jv>statusLineAssertion</jv> = <jv>res</jv>.assertStatus();
126 *    FluentIntegerAssertion&lt;RestResponse&gt; <jv>codeAssertion</jv> = <jv>statusLineAssertion</jv>.asCode();
127 *    <jv>res</jv> = <jv>codeAssertion</jv>.is(200);
128 *    FluentStringAssertion&lt;RestResponse&gt; <jv>headerAssertion</jv> = <jv>res</jv>.assertHeader(<js>"Content-Type"</js>);
129 *    <jv>res</jv> = <jv>headerAssertion</jv>.matchesSimple(<js>"application/json*"</js>);
130 *    RestResponseBody <jv>content</jv> = <jv>res</jv>.getContent();
131 *    MyBean <jv>bean</jv> = <jv>content</jv>.as(MyBean.<jk>class</jk>);
132 * </p>
133 *
134 * <p>
135 * It additionally provides support for creating remote proxy interfaces using REST as the transport medium.
136 *
137 * <h5 class='figure'>Example:</h5>
138 * <p class='bjava'>
139 *    <jc>// Define a Remote proxy for interacting with a REST interface.</jc>
140 *    <ja>@Remote</ja>(path=<js>"/petstore"</js>)
141 *    <jk>public interface</jk> PetStore {
142 *
143 *       <ja>@RemotePost</ja>(<js>"/pets"</js>)
144 *       Pet addPet(
145 *          <ja>@Content</ja> CreatePet <jv>pet</jv>,
146 *          <ja>@Header</ja>(<js>"E-Tag"</js>) UUID <jv>etag</jv>,
147 *          <ja>@Query</ja>(<js>"debug"</js>) <jk>boolean</jk> <jv>debug</jv>
148 *       );
149 *    }
150 *
151 *    <jc>// Use a RestClient with default JSON 5 support.</jc>
152 *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().json5().build();
153 *
154 *    PetStore <jv>store</jv> = <jv>client</jv>.getRemote(PetStore.<jk>class</jk>, <js>"http://localhost:10000"</js>);
155 *    CreatePet <jv>createPet</jv> = <jk>new</jk> CreatePet(<js>"Fluffy"</js>, 9.99);
156 *    Pet <jv>pet</jv> = <jv>store</jv>.addPet(<jv>createPet</jv>, UUID.<jsm>randomUUID</jsm>(), <jk>true</jk>);
157 * </p>
158 *
159 * <p>
160 * The classes are closely tied to Apache HttpClient, yet provide lots of additional functionality:
161 * <ul class='javatree'>
162 *    <li class='jc'>{@link RestClient} <jk>extends</jk> {@link HttpClient}, creates {@link RestRequest} objects.
163 *    <li class='jc'>{@link RestRequest} <jk>extends</jk> {@link HttpUriRequest}, creates {@link RestResponse} objects.
164 *    <li class='jc'>{@link RestResponse} creates {@link ResponseContent} and {@link ResponseHeader} objects.
165 *    <li class='jc'>{@link ResponseContent} <jk>extends</jk> {@link HttpEntity}
166 *    <li class='jc'>{@link ResponseHeader} <jk>extends</jk> {@link Header}
167 * </ul>
168 *
169 *
170 * <p>
171 * Instances of this class are built using the {@link Builder} class which can be constructed using
172 * the {@link #create() RestClient.create()} method as shown above.
173 *
174 * <p>
175 * Clients are typically created with a root URI so that relative URIs can be used when making requests.
176 * This is done using the {@link Builder#rootUrl(Object)} method.
177 *
178 * <h5 class='figure'>Example:</h5>
179 * <p class='bjava'>
180 *    <jc>// Create a client where all URIs are relative to localhost.</jc>
181 *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().json().rootUrl(<js>"http://localhost:5000"</js>).build();
182 *
183 *    <jc>// Use relative paths.</jc>
184 *    String <jv>body</jv> = <jv>client</jv>.get(<js>"/subpath"</js>).run().getContent().asString();
185 * </p>
186 *
187 * <p>
188 * The {@link RestClient} class creates {@link RestRequest} objects using the following methods:
189 *
190 * <ul class='javatree'>
191 *    <li class='jc'>{@link RestClient}
192 *    <ul>
193 *       <li class='jm'>{@link RestClient#get(Object) get(uri)} / {@link RestClient#get() get()}
194 *       <li class='jm'>{@link RestClient#put(Object,Object) put(uri,body)} / {@link RestClient#put(Object) put(uri)}
195 *       <li class='jm'>{@link RestClient#post(Object) post(uri,body)} / {@link RestClient#post(Object) post(uri)}
196 *       <li class='jm'>{@link RestClient#patch(Object,Object) patch(uri,body)} / {@link RestClient#patch(Object) patch(uri)}
197 *       <li class='jm'>{@link RestClient#delete(Object) delete(uri)}
198 *       <li class='jm'>{@link RestClient#head(Object) head(uri)}
199 *       <li class='jm'>{@link RestClient#options(Object) options(uri)}
200 *       <li class='jm'>{@link RestClient#formPost(Object,Object) formPost(uri,body)} / {@link RestClient#formPost(Object) formPost(uri)}
201 *       <li class='jm'>{@link RestClient#formPostPairs(Object,String...) formPostPairs(uri,parameters...)}
202 *       <li class='jm'>{@link RestClient#request(String,Object,Object) request(method,uri,body)}
203 *    </ul>
204 * </ul>
205 *
206 * <p>
207 * The {@link RestRequest} class creates {@link RestResponse} objects using the following methods:
208 *
209 * <ul class='javatree'>
210 *    <li class='jc'>{@link RestRequest}
211 *    <ul>
212 *       <li class='jm'>{@link RestRequest#run() run()}
213 *       <li class='jm'>{@link RestRequest#complete() complete()}
214 *    </ul>
215 * </ul>
216 *
217 * <p>
218 * The distinction between the two methods is that {@link RestRequest#complete() complete()} automatically consumes the response body and
219 * {@link RestRequest#run() run()} does not.  Note that you must consume response bodies in order for HTTP connections to be freed up
220 * for reuse!  The {@link InputStream InputStreams} returned by the {@link ResponseContent} object are auto-closing once
221 * they are exhausted, so it is often not necessary to explicitly close them.
222 *
223 * <p>
224 * The following examples show the distinction between the two calls:
225 *
226 * <p class='bjava'>
227 *    <jc>// Consuming the response, so use run().</jc>
228 *    String <jv>body</jv> = <jv>client</jv>.get(<jsf>URI</jsf>).run().getContent().asString();
229 *
230 *    <jc>// Only interested in response status code, so use complete().</jc>
231 *    <jk>int</jk> <jv>status</jv> = <jv>client</jv>.get(<jsf>URI</jsf>).complete().getStatusCode();
232 * </p>
233 *
234 *
235 * <h4 class='topic'>POJO Marshalling</h4>
236 *
237 * <p>
238 * By default, JSON support is provided for HTTP request and response bodies.
239 * Other languages can be specified using any of the following builder methods:
240 * <ul class='javatree'>
241 *    <li class='jc'>{@link Builder}
242 *    <ul>
243 *       <li class='jm'>{@link Builder#json() json()}
244 *       <li class='jm'>{@link Builder#json5() json5()}
245 *       <li class='jm'>{@link Builder#xml() xml()}
246 *       <li class='jm'>{@link Builder#html() html()}
247 *       <li class='jm'>{@link Builder#plainText() plainText()}
248 *       <li class='jm'>{@link Builder#msgPack() msgPack()}
249 *       <li class='jm'>{@link Builder#uon() uon()}
250 *       <li class='jm'>{@link Builder#urlEnc() urlEnc()}
251 *       <li class='jm'>{@link Builder#openApi() openApi()}
252 *    </ul>
253 * </ul>
254 *
255 * <h5 class='figure'>Example:</h5>
256 * <p class='bjava'>
257 *    <jc>// Create a basic REST client with JSON 5 support.</jc>
258 *    <jc>// Typically easier to use when performing unit tests.</jc>
259 *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().json5().build();
260 * </p>
261 *
262 * <p>
263 * Clients can also support multiple languages:
264 *
265 * <h5 class='figure'>Example:</h5>
266 * <p class='bjava'>
267 *    <jc>// Create a REST client with support for multiple languages.</jc>
268 *    RestClient <jv>client1</jv> = RestClient.<jsm>create</jsm>().json().xml().openApi().build();
269 *
270 *    <jc>// Create a REST client with support for all supported languages.</jc>
271 *    RestClient <jv>client2</jv> = RestClient.<jsm>create</jsm>().universal().build();
272 * </p>
273 *
274 * <p>
275 * When using clients with multiple language support, you must specify the <c>Content-Type</c> header on requests
276 * with bodies to specify which serializer should be selected.
277 *
278 * <p class='bjava'>
279 *    <jc>// Create a REST client with support for multiple languages.</jc>
280 *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().universal().build();
281 *
282 *    <jv>client</jv>
283 *       .post(<jsf>URI</jsf>, <jv>myBean</jv>)
284 *       .contentType(<js>"application/json"</js>)
285 *       .complete()
286 *       .assertStatus().is(200);
287 * </p>
288 *
289 * <p>
290 * Languages can also be specified per-request.
291 *
292 * <p class='bjava'>
293 *    <jc>// Create a REST client with no default languages supported.</jc>
294 *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().build();
295 *
296 *    <jc>// Use JSON for this request.</jc>
297 *    <jv>client</jv>
298 *       .post(<jsf>URI</jsf>, <jv>myBean</jv>)
299 *       .json()
300 *       .complete()
301 *       .assertStatus().is(200);
302 * </p>
303 *
304 *
305 * <p>
306 * The {@link Builder} class provides convenience methods for setting common serializer and parser
307 * settings.
308 *
309 * <h5 class='figure'>Example:</h5>
310 * <p class='bjava'>
311 *    <jc>// Create a basic REST client with JSON support.</jc>
312 *    <jc>// Use single-quotes and whitespace.</jc>
313 *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().json().sq().ws().build();
314 * </p>
315 *
316 * <p>
317 *    Other methods are also provided for specifying the serializers and parsers used for lower-level marshalling support:
318 * <ul class='javatree'>
319 *    <li class='jc'>{@link Builder}
320 *    <ul>
321 *       <li class='jm'>{@link Builder#serializer(Serializer) serializer(Serializer)}
322 *       <li class='jm'>{@link Builder#parser(Parser) parser(Parser)}
323 *       <li class='jm'>{@link Builder#marshaller(Marshaller) marshaller(Marshaller)}
324 *    </ul>
325 * </ul>
326 *
327 * <p>
328 * HTTP parts (headers, query parameters, form data...) are serialized and parsed using the {@link HttpPartSerializer}
329 * and {@link HttpPartParser} APIs.  By default, clients are configured to use {@link OpenApiSerializer} and
330 * {@link OpenApiParser}.  These can be overridden using the following methods:
331 * <ul class='javatree'>
332 *    <li class='jc'>{@link Builder}
333 *    <ul>
334 *       <li class='jm'>{@link Builder#partSerializer(Class) partSerializer(Class&lt;? extends HttpPartSerializer>)}
335 *       <li class='jm'>{@link Builder#partParser(Class) partParser(Class&lt;? extends HttpPartParser>)}
336 *    </ul>
337 * </ul>
338 *
339 *
340 * <h4 class='topic'>Request Headers</h4>
341 * <p>
342 * Per-client or per-request headers can be specified using the following methods:
343 * <ul class='javatree'>
344 *    <li class='jc'>{@link Builder}
345 *    <ul>
346 *       <li class='jm'>{@link Builder#headers() headerData()}
347 *       <li class='jm'>{@link Builder#header(String,String) header(String,Object)}
348 *       <li class='jm'>{@link Builder#header(String,Supplier) header(String,Supplier&lt;?&gt;)}
349 *       <li class='jm'>{@link Builder#headers(Header...) headers(Header...)}
350 *       <li class='jm'>{@link Builder#headersDefault(Header...) defaultHeaders(Header...)}
351 *    </ul>
352 *    <li class='jc'>{@link RestRequest}
353 *    <ul>
354 *       <li class='jm'>{@link RestRequest#header(String,Object) header(String,Object)}
355 *       <li class='jm'>{@link RestRequest#headers(Header...) headers(Header...)}
356 *       <li class='jm'>{@link RestRequest#headersBean(Object) headersBean(Object)}
357 *       <li class='jm'>{@link RestRequest#headerPairs(String...) headerPairs(String...)}
358 *    </ul>
359 * </ul>
360 *
361 * <p>
362 * The supplier methods are particularly useful for header values whose values may change over time (such as <c>Authorization</c> headers
363 * which may need to change every few minutes).
364 * </p>
365 *
366 * <h5 class='figure'>Example:</h5>
367 * <p class='bjava'>
368 *    <jc>// Create a client that adds a dynamic Authorization header to every request.</jc>
369 *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().header(<js>"Authorization"</js>, ()-&gt;getMyAuthToken()).build();
370 * </p>
371 *
372 * <p>
373 * The {@link HttpPartSchema} API allows you to define OpenAPI schemas to POJO data structures on both requests
374 * and responses.
375 *
376 * <h5 class='figure'>Example:</h5>
377 * <p class='bjava'>
378 *    <jc>// Create a client that adds a header "Foo: bar|baz" to every request.</jc>
379 *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>()
380 *       .header(<js>"Foo"</js>, AList.<jsm>of</jsm>(<js>"bar"</js>,<js>"baz"</js>), <jsf>T_ARRAY_PIPES</jsf>)
381 *       .build();
382 * </p>
383 *
384 * <p>
385 * The methods with {@link ListOperation} parameters allow you to control whether new headers get appended, prepended, or
386 * replace existing headers with the same name.
387 *
388 * <h5 class='section'>Notes:</h5><ul>
389 *    <li class='note'>Methods that pass in POJOs convert values to strings using the part serializers.  Methods that pass in <c>Header</c> or
390 *       <c>NameValuePair</c> objects use the values returned by that bean directly.
391 * </ul>
392 *
393 *
394 * <h4 class='topic'>Request Query Parameters</h4>
395 * <p>
396 * Per-client or per-request query parameters can be specified using the following methods:
397 * <ul class='javatree'>
398 *    <li class='jc'>{@link Builder}
399 *    <ul>
400 *       <li class='jm'>{@link Builder#queryData() queryData()}
401 *       <li class='jm'>{@link Builder#queryData(String,String) queryData(String,String)}
402 *       <li class='jm'>{@link Builder#queryData(String,Supplier) queryData(String,Supplier&lt;?&gt;)}
403 *       <li class='jm'>{@link Builder#queryData(NameValuePair...) queryData(NameValuePair...)}
404 *       <li class='jm'>{@link Builder#queryDataDefault(NameValuePair...) defaultQueryData(NameValuePair...)}
405 *    </ul>
406 *    <li class='jc'>{@link RestRequest}
407 *    <ul>
408 *       <li class='jm'>{@link RestRequest#queryData(String,Object) queryData(String,Object)}
409 *       <li class='jm'>{@link RestRequest#queryData(NameValuePair...) queryData(NameValuePair...)}
410 *       <li class='jm'>{@link RestRequest#queryDataBean(Object) queryDataBean(Object)}
411 *       <li class='jm'>{@link RestRequest#queryCustom(Object) queryCustom(Object)}
412 *       <li class='jm'>{@link RestRequest#queryDataPairs(String...) queryDataPairs(String...)}
413 *    </ul>
414 * </ul>
415 *
416 * <h5 class='figure'>Example:</h5>
417 * <p class='bjava'>
418 *    <jc>// Create a client that adds a ?foo=bar query parameter to every request.</jc>
419 *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().query(<js>"foo"</js>, <js>"bar"</js>).build();
420 *
421 *    <jc>// Or do it on every request.</jc>
422 *    String <jv>response</jv> = <jv>client</jv>.get(<jsf>URI</jsf>).query(<js>"foo"</js>, <js>"bar"</js>).run().getContent().asString();
423 * </p>
424 *
425 * <h5 class='section'>Notes:</h5><ul>
426 *    <li class='note'>Like header values, dynamic values and OpenAPI schemas are supported.
427 *    <li class='note'>Methods that pass in POJOs convert values to strings using the part serializers.  Methods that pass in <c>NameValuePair</c>
428 *       objects use the values returned by that bean directly.
429 * </ul>
430 *
431 *
432 * <h4 class='topic'>Request Form Data</h4>
433 *
434 * <p>
435 * Per-client or per-request form-data parameters can be specified using the following methods:
436 * <ul class='javatree'>
437 *    <li class='jc'>{@link Builder}
438 *    <ul>
439 *       <li class='jm'>{@link Builder#formData() formData()}
440 *       <li class='jm'>{@link Builder#formData(String,String) formData(String,String)}
441 *       <li class='jm'>{@link Builder#formData(String,Supplier) formData(String,Supplier&lt;?&gt;)}
442 *       <li class='jm'>{@link Builder#formData(NameValuePair...) formDatas(NameValuePair...)}
443 *       <li class='jm'>{@link Builder#formDataDefault(NameValuePair...) defaultFormData(NameValuePair...)}
444 *    </ul>
445 *    <li class='jc'>{@link RestRequest}
446 *    <ul>
447 *       <li class='jm'>{@link RestRequest#formData(String,Object) formData(String,Object)}
448 *       <li class='jm'>{@link RestRequest#formData(NameValuePair...) formData(NameValuePair...)}
449 *       <li class='jm'>{@link RestRequest#formDataBean(Object) formDataBean(Object)}
450 *       <li class='jm'>{@link RestRequest#formDataCustom(Object) formDataCustom(Object)}
451 *       <li class='jm'>{@link RestRequest#formDataPairs(String...) formDataPairs(String...)}
452 *    </ul>
453 * </ul>
454 *
455 * <h5 class='section'>Notes:</h5><ul>
456 *    <li class='note'>Like header values, dynamic values and OpenAPI schemas are supported.
457 *    <li class='note'>Methods that pass in POJOs convert values to strings using the part serializers.  Methods that pass in <c>NameValuePair</c>
458 *       objects use the values returned by that bean directly.
459 * </ul>
460 *
461 *
462 * <h4 class='topic'>Request Body</h4>
463 *
464 * <p>
465 * The request body can either be passed in with the client creator method (e.g. {@link RestClient#post(Object,Object) post(uri,body)}),
466 * or can be specified via the following methods:
467 *
468 * <ul class='javatree'>
469 *    <li class='jc'>{@link RestRequest}
470 *    <ul>
471 *       <li class='jm'>{@link RestRequest#content(Object) body(Object)}
472 *       <li class='jm'>{@link RestRequest#content(Object,HttpPartSchema) body(Object,HttpPartSchema)}
473 *    </ul>
474 * </ul>
475 *
476 * <p>
477 * The request body can be any of the following types:
478 * <ul class='javatree'>
479 *       <li class='jc'>
480 *          {@link Object} - POJO to be converted to text using the {@link Serializer} defined on the client or request.
481 *       <li class='jc'>
482 *          {@link Reader} - Raw contents of {@code Reader} will be serialized to remote resource.
483 *       <li class='jc'>
484 *          {@link InputStream} - Raw contents of {@code InputStream} will be serialized to remote resource.
485 *       <li class='jc'>
486 *          {@link HttpResource} - Raw contents will be serialized to remote resource.  Additional headers and media type will be set on request.
487 *       <li class='jc'>
488 *          {@link HttpEntity} - Bypass Juneau serialization and pass HttpEntity directly to HttpClient.
489 *       <li class='jc'>
490 *          {@link PartList} - Converted to a URL-encoded FORM post.
491 *       <li class='jc'>
492 *          {@link Supplier} - A supplier of anything on this list.
493 *    </ul>
494 *
495 * <h5 class='section'>Notes:</h5><ul>
496 *    <li class='note'>If the serializer on the client or request is explicitly set to <jk>null</jk>, POJOs will be converted to strings
497 *       using the registered part serializer as content type <js>"text/plain</js>.  If the part serializer is also <jk>null</jk>,
498 *       POJOs will be converted to strings using {@link ClassMeta#toString(Object)} which typically just calls {@link Object#toString()}.
499 * </ul>
500 *
501 *
502 * <h4 class='topic'>Response Status</h4>
503 *
504 * <p>
505 * After execution using {@link RestRequest#run()} or {@link RestRequest#complete()}, the following methods can be used
506 * to get the response status:
507 *
508 * <ul class='javatree'>
509 *    <li class='jc'>{@link RestResponse}
510 *    <ul>
511 *       <li class='jm'><c>{@link RestResponse#getStatusLine() getStatusLine()} <jk>returns</jk> {@link StatusLine}</c>
512 *       <li class='jm'><c>{@link RestResponse#getStatusCode() getStatusCode()} <jk>returns</jk> <jk>int</jk></c>
513 *       <li class='jm'><c>{@link RestResponse#getReasonPhrase() getReasonPhrase()} <jk>returns</jk> String</c>
514 *       <li class='jm'><c>{@link RestResponse#assertStatus() assertStatus()} <jk>returns</jk> {@link FluentResponseStatusLineAssertion}</c>
515 *    </ul>
516 * </ul>
517 *
518 * <h5 class='figure'>Example:</h5>
519 * <p class='bjava'>
520 *    <jc>// Only interested in status code.</jc>
521 *    <jk>int</jk> <jv>statusCode</jv> = <jv>client</jv>.get(<jsf>URI</jsf>).complete().getStatusCode();
522 * </p>
523 *
524 * <p>
525 * Equivalent methods with mutable parameters are provided to allow access to status values without breaking fluent call chains.
526 *
527 * <h5 class='figure'>Example:</h5>
528 * <p class='bjava'>
529 *    <jc>// Interested in multiple values.</jc>
530 *    Value&lt;Integer&gt; <jv>statusCode</jv> = Value.<jsm>create</jsm>();
531 *    Value&lt;String&gt; <jv>reasonPhrase</jv> = Value.<jsm>create</jsm>();
532 *
533 *    <jv>client</jv>.get(<jsf>URI</jsf>).complete().getStatusCode(<jv>statusCode</jv>).getReasonPhrase(<jv>reasonPhrase</jv>);
534 *    System.<jsf>err</jsf>.println(<js>"statusCode="</js>+<jv>statusCode</jv>.get()+<js>", reasonPhrase="</js>+<jv>reasonPhrase</jv>.get());
535 * </p>
536 *
537 * <h5 class='section'>Notes:</h5><ul>
538 *    <li class='note'>If you are only interested in the response status and not the response body, be sure to use {@link RestRequest#complete()} instead
539 *       of {@link RestRequest#run()} to make sure the response body gets automatically cleaned up.  Otherwise you must
540 *       consume the response yourself.
541 * </ul>
542 *
543 * <p>
544 * The assertion method is provided for quickly asserting status codes in fluent calls.
545 *
546 * <h5 class='figure'>Example:</h5>
547 * <p class='bjava'>
548 *    <jc>// Status assertion using a static value.</jc>
549 *    String <jv>body</jv> = <jv>client</jv>.get(<jsf>URI</jsf>)
550 *       .run()
551 *       .assertStatus().asCode().isBetween(200,399)
552 *       .getContent().asString();
553 *
554 *    <jc>// Status assertion using a predicate.</jc>
555 *    String <jv>body</jv> = <jv>client</jv>.get(<jsf>URI</jsf>)
556 *       .run()
557 *       .assertStatus().asCode().is(<jv>x</jv> -&gt; <jv>x</jv>&lt;400)
558 *       .getContent().asString();
559 * </p>
560 *
561 *
562 * <h4 class='topic'>Response Headers</h4>
563 *
564 * <p>
565 * Response headers are accessed through the following methods:
566 *
567 * <ul class='javatree'>
568 *    <li class='jc'>{@link RestResponse}
569 *    <ul>
570 *       <li class='jm'><c>{@link RestResponse#getHeaders(String) getHeaders(String)} <jk>returns</jk> {@link ResponseHeader}[]</c>
571 *       <li class='jm'><c>{@link RestResponse#getFirstHeader(String) getFirstHeader(String)} <jk>returns</jk> {@link ResponseHeader}</c>
572 *       <li class='jm'><c>{@link RestResponse#getLastHeader(String) getLastHeader(String)} <jk>returns</jk> {@link ResponseHeader}</c>
573 *       <li class='jm'><c>{@link RestResponse#getAllHeaders() getAllHeaders()} <jk>returns</jk> {@link ResponseHeader}[]</c>
574 *       <li class='jm'><c>{@link RestResponse#getStringHeader(String) getStringHeader(String)} <jk>returns</jk> String</c>
575 *       <li class='jm'><c>{@link RestResponse#containsHeader(String) containsHeader(String)} <jk>returns</jk> <jk>boolean</jk></c>
576 *    </ul>
577 * </ul>
578 *
579 * <p>
580 * The {@link RestResponse#getFirstHeader(String)} and {@link RestResponse#getLastHeader(String)} methods return an empty {@link ResponseHeader} object instead of<jk>null</jk>.
581 * This allows it to be used more easily in fluent calls.
582 *
583 * <h5 class='figure'>Example:</h5>
584 * <p class='bjava'>
585 *    <jc>// See if response contains Location header.</jc>
586 *    <jk>boolean</jk> <jv>hasLocationHeader</jv> = <jv>client</jv>.get(<jsf>URI</jsf>).complete().getLastHeader(<js>"Location"</js>).exists();
587 * </p>
588 *
589 * <p>
590 * The {@link ResponseHeader} class extends from the HttpClient {@link Header} class and provides several convenience
591 * methods:
592 *
593 * <ul class='javatree'>
594 *    <li class='jc'>{@link ResponseHeader}
595 *    <ul>
596 *       <li class='jm'><c>{@link ResponseHeader#isPresent() isPresent()} <jk>returns</jk> <jk>boolean</jk></c>
597 *       <li class='jm'><c>{@link ResponseHeader#asString() asString()} <jk>returns</jk> String</c>
598 *       <li class='jm'><c>{@link ResponseHeader#as(Type,Type...) as(Type,Type...)} <jk>returns</jk> T</c>
599 *       <li class='jm'><c>{@link ResponseHeader#as(Class) as(Class&lt;T&gt;)} <jk>returns</jk> T</c>
600 *       <li class='jm'><c>{@link ResponseHeader#asMatcher(Pattern) asMatcher(Pattern)} <jk>returns</jk> {@link Matcher}</c>
601 *       <li class='jm'><c>{@link ResponseHeader#asMatcher(String) asMatcher(String)} <jk>returns</jk> {@link Matcher}</c>
602 *       <li class='jm'><c>{@link ResponseHeader#asHeader(Class) asHeader(Class&lt;T <jk>extends</jk> BasicHeader&gt; c)} <jk>returns</jk> {@link BasicHeader}</c>
603 *       <li class='jm'><c>{@link ResponseHeader#asStringHeader() asStringHeader()} <jk>returns</jk> {@link BasicStringHeader}</c>
604 *       <li class='jm'><c>{@link ResponseHeader#asIntegerHeader() asIntegerHeader()} <jk>returns</jk> {@link BasicIntegerHeader}</c>
605 *       <li class='jm'><c>{@link ResponseHeader#asLongHeader() asLongHeader()} <jk>returns</jk> {@link BasicLongHeader}</c>
606 *       <li class='jm'><c>{@link ResponseHeader#asDateHeader() asDateHeader()} <jk>returns</jk> {@link BasicDateHeader}</c>
607 *       <li class='jm'><c>{@link ResponseHeader#asCsvHeader() asCsvHeader()} <jk>returns</jk> {@link BasicCsvHeader}</c>
608 *       <li class='jm'><c>{@link ResponseHeader#asEntityTagsHeader() asEntityTagsHeader()} <jk>returns</jk> {@link BasicEntityTagsHeader}</c>
609 *       <li class='jm'><c>{@link ResponseHeader#asStringRangesHeader() asStringRangesHeader()} <jk>returns</jk> {@link BasicStringRangesHeader}</c>
610 *       <li class='jm'><c>{@link ResponseHeader#asUriHeader() asUriHeader()} <jk>returns</jk> {@link BasicUriHeader}</c>
611 *    </ul>
612 * </ul>
613 *
614 * <p>
615 * The {@link ResponseHeader#schema(HttpPartSchema)} method allows you to perform parsing of OpenAPI formats for
616 * header parts.
617 *
618 * <h5 class='figure'>Example:</h5>
619 * <p class='bjava'>
620 *    <jc>// Parse the header "Foo: bar|baz".</jc>
621 *    List&lt;String&gt; <jv>fooHeader</jv> = <jv>client</jv>
622 *       .get(<jsf>URI</jsf>)
623 *       .complete()
624 *       .getHeader(<js>"Foo"</js>).schema(<jsf>T_ARRAY_PIPES</jsf>).as(List.<jk>class</jk>, String.<jk>class</jk>);
625 * </p>
626 *
627 * <p>
628 * Assertion methods are also provided for fluent-style calls:
629 *
630 * <ul class='javatree'>
631 *    <li class='jc'>{@link ResponseHeader}
632 *    <ul>
633 *       <li class='jm'><c>{@link ResponseHeader#assertValue() assertValue()} <jk>returns</jk> {@link FluentResponseHeaderAssertion}</c>
634 *    </ul>
635 * </ul>
636 *
637 * <p>
638 * Note how in the following example, the fluent assertion returns control to the {@link RestResponse} object after
639 * the assertion has been completed:
640 *
641 * <h5 class='figure'>Example:</h5>
642 * <p class='bjava'>
643 *    <jc>// Assert the response content type is any sort of JSON.</jc>
644 *    String <jv>body</jv> = <jv>client</jv>.get(<jsf>URI</jsf>)
645 *       .run()
646 *       .getHeader(<js>"Content-Type"</js>).assertValue().matchesSimple(<js>"application/json*"</js>)
647 *       .getContent().asString();
648 * </p>
649 *
650 *
651 * <h4 class='topic'>Response Body</h4>
652 *
653 * <p>
654 * The response body is accessed through the following method:
655 *
656 * <ul class='javatree'>
657 *    <li class='jc'>{@link RestResponse}
658 *    <ul>
659 *       <li class='jm'><c>{@link RestResponse#getContent() getContent()} <jk>returns</jk> {@link ResponseContent}</c>
660 *    </ul>
661 * </ul>
662 *
663 * <p>
664 * The {@link ResponseContent} class extends from the HttpClient {@link HttpEntity} class and provides several convenience
665 * methods:
666 *
667 * <ul class='javatree'>
668 *    <li class='jc'>{@link ResponseContent}
669 *    <ul>
670 *       <li class='jm'><c>{@link ResponseContent#asInputStream() asInputStream()} <jk>returns</jk> InputStream</c>
671 *       <li class='jm'><c>{@link ResponseContent#asReader() asReader()} <jk>returns</jk> Reader</c>
672 *       <li class='jm'><c>{@link ResponseContent#asReader(Charset) asReader(Charset)} <jk>returns</jk> Reader</c>
673 *       <li class='jm'><c>{@link ResponseContent#pipeTo(OutputStream) pipeTo(OutputStream)} <jk>returns</jk> {@link RestResponse}</c>
674 *       <li class='jm'><c>{@link ResponseContent#pipeTo(Writer) pipeTo(Writer)} <jk>returns</jk> {@link RestResponse}</c>
675 *       <li class='jm'><c>{@link ResponseContent#as(Type,Type...) as(Type,Type...)} <jk>returns</jk> T</c>
676 *       <li class='jm'><c>{@link ResponseContent#as(Class) as(Class&lt;T&gt;)} <jk>returns</jk> T</c>
677 *       <li class='jm'><c>{@link ResponseContent#asFuture(Class) asFuture(Class&lt;T&gt;)} <jk>returns</jk> Future&lt;T&gt;</c>
678 *       <li class='jm'><c>{@link ResponseContent#asFuture(Type,Type...) asFuture(Type,Type...)} <jk>returns</jk> Future&lt;T&gt;</c>
679 *       <li class='jm'><c>{@link ResponseContent#asString() asString()} <jk>returns</jk> String</c>
680 *       <li class='jm'><c>{@link ResponseContent#asStringFuture() asStringFuture()} <jk>returns</jk> Future&lt;String&gt;</c>
681 *       <li class='jm'><c>{@link ResponseContent#asAbbreviatedString(int) asAbbreviatedString(int)} <jk>returns</jk> String</c>
682 *       <li class='jm'><c>{@link ResponseContent#asObjectRest(Class) asObjectRest(Class&lt;?&gt;)} <jk>returns</jk> {@link ObjectRest}</c>
683 *       <li class='jm'><c>{@link ResponseContent#asObjectRest() asObjectRest()} <jk>returns</jk> {@link ObjectRest}</c>
684 *       <li class='jm'><c>{@link ResponseContent#asMatcher(Pattern) asMatcher(Pattern)} <jk>returns</jk> {@link Matcher}</c>
685 *       <li class='jm'><c>{@link ResponseContent#asMatcher(String) asMatcher(String)} <jk>returns</jk> {@link Matcher}</c>
686 *    </ul>
687 * </ul>
688 *
689 * <br>
690 *
691 * <h5 class='figure'>Examples:</h5>
692 * <p class='bjava'>
693 *    <jc>// Parse into a linked-list of strings.</jc>
694 *    List&lt;String&gt; <jv>list1</jv> = <jv>client</jv>
695 *       .get(<jsf>URI</jsf>)
696 *       .run()
697 *       .getContent().as(LinkedList.<jk>class</jk>, String.<jk>class</jk>);
698 *
699 *    <jc>// Parse into a linked-list of beans.</jc>
700 *    List&lt;MyBean&gt; <jv>list2</jv> = <jv>client</jv>
701 *       .get(<jsf>URI</jsf>)
702 *       .run()
703 *       .getContent().as(LinkedList.<jk>class</jk>, MyBean.<jk>class</jk>);
704 *
705 *    <jc>// Parse into a linked-list of linked-lists of strings.</jc>
706 *    List&lt;List&lt;String&gt;&gt; <jv>list3</jv> = <jv>client</jv>
707 *       .get(<jsf>URI</jsf>)
708 *       .run()
709 *       .getContent().as(LinkedList.<jk>class</jk>, LinkedList.<jk>class</jk>, String.<jk>class</jk>);
710 *
711 *    <jc>// Parse into a map of string keys/values.</jc>
712 *    Map&lt;String,String&gt; <jv>map1</jv> = <jv>client</jv>
713 *       .get(<jsf>URI</jsf>)
714 *       .run()
715 *       .getContent().as(TreeMap.<jk>class</jk>, String.<jk>class</jk>, String.<jk>class</jk>);
716 *
717 *    <jc>// Parse into a map containing string keys and values of lists containing beans.</jc>
718 *    Map&lt;String,List&lt;MyBean&gt;&gt; <jv>map2</jv> = <jv>client</jv>
719 *       .get(<jsf>URI</jsf>)
720 *       .run()
721 *       .getContent().as(TreeMap.<jk>class</jk>, String.<jk>class</jk>, List.<jk>class</jk>, MyBean.<jk>class</jk>);
722 * </p>
723 *
724 * <p>
725 * The response body can only be consumed once unless it has been cached into memory.  In many cases, the body is
726 * automatically cached when using the assertions methods or methods such as {@link ResponseContent#asString()}.
727 * However, methods that involve reading directly from the input stream cannot be called twice.
728 * In these cases, the {@link RestResponse#cacheContent()} and {@link ResponseContent#cache()} methods are provided
729 * to cache the response body in memory so that you can perform several operations against it.
730 *
731 * <p class='bjava'>
732 *    <jc>// Cache the response body so we can access it twice.</jc>
733 *    InputStream <jv>inputStream</jv> = <jv>client</jv>
734 *       .get(<jsf>URI</jsf>)
735 *       .run()
736 *       .cacheBody()
737 *       .getContent().pipeTo(<jv>someOtherStream</jv>)
738 *       .getContent().asInputStream();
739 * </p>
740 *
741 * <p>
742 * Assertion methods are also provided for fluent-style calls:
743 *
744 * <ul class='javatree'>
745 *    <li class='jc'>{@link ResponseContent}
746 *    <ul>
747 *       <li class='jm'><c>{@link ResponseContent#assertValue() assertValue()} <jk>returns</jk> {@link FluentResponseBodyAssertion}</c>
748 *    </ul>
749 * </ul>
750 *
751 * <br>
752 *
753 * <h5 class='figure'>Example:</h5>
754 * <p class='bjava'>
755 *    <jc>// Assert that the body contains the string "Success".</jc>
756 *    String <jv>body</jv> = <jv>client</jv>
757 *       .get(<jsf>URI</jsf>)
758 *       .run()
759 *       .getContent().assertString().contains(<js>"Success"</js>)
760 *       .getContent().asString();
761 * </p>
762 *
763 * <p>
764 * Object assertions allow you to parse the response body into a POJO and then perform various tests on that resulting
765 * POJO.
766 *
767 * <h5 class='figure'>Example:</h5>
768 * <p class='bjava'>
769 *    <jc>// Parse bean into POJO and then validate that it was parsed correctly.</jc>
770 *    MyBean <jv>bean</jv> = <jv>client</jv>.get(<jsf>URI</jsf>)
771 *       .run()
772 *       .getContent().assertObject(MyBean.<jk>class</jk>).asJson().is(<js>"{foo:'bar'}"</js>)
773 *       .getContent().as(MyBean.<jk>class</jk>);
774 * </p>
775 *
776 *
777 * <h4 class='topic'>Custom Call Handlers</h4>
778 *
779 * <p>
780 * The {@link RestCallHandler} interface provides the ability to provide custom handling of requests.
781 *
782 * <ul class='javatree'>
783 *    <li class='jc'>{@link Builder}
784 *    <ul>
785 *       <li class='jm'>{@link Builder#callHandler() callHandler()}
786 *    </ul>
787 *    <li class='jic'>{@link RestCallHandler}
788 *    <ul>
789 *       <li class='jm'><c>{@link RestCallHandler#run(HttpHost,HttpRequest,HttpContext) run(HttpHost,HttpRequest,HttpContext)} <jk>returns</jk> HttpResponse</c>
790 *    </ul>
791 * </ul>
792 *
793 * <p>
794 * Note that there are other ways of accomplishing this such as extending the {@link RestClient} class and overriding
795 * the {@link #run(HttpHost,HttpRequest,HttpContext)} method
796 * or by defining your own {@link HttpRequestExecutor}.  Using this interface is often simpler though.
797 *
798 *
799 * <h4 class='topic'>Interceptors</h4>
800 *
801 * <p>
802 * The {@link RestCallInterceptor} API provides a quick way of intercepting and manipulating requests and responses beyond
803 * the existing {@link HttpRequestInterceptor} and {@link HttpResponseInterceptor} APIs.
804 *
805 * <ul class='javatree'>
806 *    <li class='jc'>{@link Builder}
807 *    <ul>
808 *       <li class='jm'>{@link Builder#interceptors(Object...) interceptors(Object...)}
809 *    </ul>
810 *    <li class='jc'>{@link RestRequest}
811 *    <ul>
812 *       <li class='jm'>{@link RestRequest#interceptors(RestCallInterceptor...) interceptors(RestCallInterceptor...)}
813 *    </ul>
814 *    <li class='jic'>{@link RestCallInterceptor}
815 *    <ul>
816 *       <li class='jm'>{@link RestCallInterceptor#onInit(RestRequest) onInit(RestRequest)}
817 *       <li class='jm'>{@link RestCallInterceptor#onConnect(RestRequest,RestResponse) onConnect(RestRequest,RestResponse)}
818 *       <li class='jm'>{@link RestCallInterceptor#onClose(RestRequest,RestResponse) onClose(RestRequest,RestResponse)}
819 *    </ul>
820 * </ul>
821 *
822 *
823 * <h4 class='topic'>Logging / Debugging</h4>
824 *
825 * <p>
826 * The following methods provide logging of requests and responses:
827 *
828 * <ul class='javatree'>
829 *    <li class='jc'>{@link Builder}
830 *    <ul>
831 *       <li class='jm'>{@link Builder#logger(Logger) logger(Logger)}
832 *       <li class='jm'>{@link Builder#logToConsole() logToConsole()}
833 *       <li class='jm'>{@link Builder#logRequests(DetailLevel,Level,BiPredicate) logRequests(DetailLevel,Level,BiPredicate)}
834 *    </ul>
835 * </ul>
836 *
837 * <p>
838 * The following example shows the results of logging all requests that end with <c>/bean</c>.
839 *
840 * <h5 class='figure'>Examples:</h5>
841 * <p class='bjava'>
842 *    MyBean <jv>bean</jv> = RestClient
843 *       .<jsm>create</jsm>()
844 *       .json5()
845 *       .logRequests(DetailLevel.<jsf>FULL</jsf>, Level.<jsf>SEVERE</jsf>, (<jv>req</jv>,<jv>res</jv>)-&gt;<jv>req</jv>.getUri().endsWith(<js>"/bean"</js>))
846 *       .logToConsole()
847 *       .build()
848 *       .post(<js>"http://localhost/bean"</js>, <jv>anotherBean</jv>)
849 *       .run()
850 *       .getContent().as(MyBean.<jk>class</jk>);
851 * </p>
852 *
853 * <p>
854 * This produces the following console output:
855 *
856 * <p class='bconsole'>
857 *    === HTTP Call (outgoing) ======================================================
858 *    === REQUEST ===
859 *    POST http://localhost/bean
860 *    ---request headers---
861 *       Accept: application/json5
862 *    ---request entity---
863 *    Content-Type: application/json5
864 *    ---request content---
865 *    {f:1}
866 *    === RESPONSE ===
867 *    HTTP/1.1 200
868 *    ---response headers---
869 *       Content-Type: application/json
870 *    ---response content---
871 *    {f:1}
872 *    === END =======================================================================",
873 * </p>
874 *
875 *
876 * <p class='notes'>
877 * It should be noted that if you enable request logging detail level {@link DetailLevel#FULL}, response bodies will be cached by default which may introduce
878 * a performance penalty.
879 *
880 * <p>
881 * Additionally, the following method is also provided for enabling debug mode:
882 *
883 * <ul class='javatree'>
884 *    <li class='jc'>{@link Builder}
885 *    <ul>
886 *       <li class='jm'>{@link Builder#debug() debug()}
887 *    </ul>
888 * </ul>
889 *
890 * <p>
891 * Enabling debug mode has the following effects:
892 * <ul>
893 *    <li>{@link org.apache.juneau.Context.Builder#debug()} is enabled.
894 *    <li>{@link Builder#detectLeaks()} is enabled.
895 *    <li>{@link Builder#logToConsole()} is called.
896 * </ul>
897 *
898 *
899 * <h4 class='topic'>REST Proxies</h4>
900 *
901 * <p>
902 * One of the more powerful features of the REST client class is the ability to produce Java interface proxies against
903 * arbitrary remote REST resources.
904 *
905 * <h5 class='figure'>Example:</h5>
906 * <p class='bjava'>
907 *    <jc>// Define a Remote proxy for interacting with a REST interface.</jc>
908 *    <ja>@Remote</ja>(path=<js>"/petstore"</js>)
909 *    <jk>public interface</jk> PetStore {
910 *
911 *       <ja>@RemotePost</ja>(<js>"/pets"</js>)
912 *       Pet addPet(
913 *          <ja>@Content</ja> CreatePet <jv>pet</jv>,
914 *          <ja>@Header</ja>(<js>"E-Tag"</js>) UUID <jv>etag</jv>,
915 *          <ja>@Query</ja>(<js>"debug"</js>) <jk>boolean</jk> <jv>debug</jv>
916 *       );
917 *    }
918 *
919 *    <jc>// Use a RestClient with default JSON 5 support.</jc>
920 *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().json5().build())
921 *
922 *    PetStore <jv>store</jv> = <jv>client</jv>.getRemote(PetStore.<jk>class</jk>, <js>"http://localhost:10000"</js>);
923 *    CreatePet <jv>createPet</jv> = <jk>new</jk> CreatePet(<js>"Fluffy"</js>, 9.99);
924 *    Pet <jv>pet</jv> = <jv>store</jv>.addPet(<jv>createPet</jv>, UUID.<jsm>randomUUID</jsm>(), <jk>true</jk>);
925 * </p>
926 *
927 * <p>
928 * The methods to retrieve remote interfaces are:
929 *
930 * <ul class='javatree'>
931 *    <li class='jc'>{@link RestClient}
932 *    <ul>
933 *       <li class='jm'><c>{@link RestClient#getRemote(Class) getRemote(Class&lt;T&gt;)} <jk>returns</jk> T</c>
934 *       <li class='jm'><c>{@link RestClient#getRemote(Class,Object) getRemote(Class&lt;T&gt;,Object)} <jk>returns</jk> T</c>
935 *       <li class='jm'><c>{@link RestClient#getRemote(Class,Object,Serializer,Parser) getRemote(Class&lt;T&gt;,Object,Serializer,Parser)} <jk>returns</jk> T</c>
936 *       <li class='jm'><c>{@link RestClient#getRrpcInterface(Class) getRrpcInterface(Class&lt;T&gt;)} <jk>returns</jk> T</c>
937 *       <li class='jm'><c>{@link RestClient#getRrpcInterface(Class,Object) getRrpcInterface(Class&lt;T&gt;,Object)} <jk>returns</jk> T</c>
938 *       <li class='jm'><c>{@link RestClient#getRrpcInterface(Class,Object,Serializer,Parser) getRrpcInterface(Class&lt;T&gt;,Object,Serializer,Parser)} <jk>returns</jk> T</c>
939 *    </ul>
940 * </ul>
941 *
942 * <p>
943 * Two basic types of remote interfaces are provided:
944 *
945 * <ul class='spaced-list'>
946 *    <li>{@link Remote @Remote}-annotated interfaces.  These can be defined against arbitrary external REST resources.
947 *    <li>RPC-over-REST interfaces.  These are Java interfaces that allow you to make method calls on server-side POJOs.
948 * </ul>
949 *
950 * <p>
951 * Refer to the following documentation on both flavors:
952 *
953 * <ul class='doctree'>
954 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/RestProxyBasics">REST Proxy Basics</a>
955 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/RestRpc">REST/RPC</a>
956 * </ul>
957 *
958 * <br>
959 * <hr>
960 * <h4 class='topic'>Customizing Apache HttpClient</h4>
961 *
962 * <p>
963 * Several methods are provided for customizing the underlying HTTP client and client builder classes:
964 * <ul class='javatree'>
965 *    <li class='jc'>{@link Builder}
966 *    <ul>
967 *       <li class='jm'>{@link Builder#httpClientBuilder(HttpClientBuilder) httpClientBuilder(HttpClientBuilder)} - Set the client builder yourself.
968 *       <li class='jm'>{@link Builder#createHttpClientBuilder() createHttpClientBuilder()} - Override to create the client builder.
969 *       <li class='jm'>{@link Builder#createHttpClient() createHttpClient()} - Override to create the client.
970 *       <li class='jm'>{@link Builder#createConnectionManager() createConnectionManager()} - Override to create the connection management.
971 *    </ul>
972 * </ul>
973 *
974 * <p>
975 * Additionally, all methods on the <c>HttpClientBuilder</c> class have been extended with fluent setters.
976 *
977 * <h5 class='figure'>Example:</h5>
978 * <p class='bjava'>
979 *    <jc>// Create a client with customized HttpClient settings.</jc>
980 *    MyBean <jv>bean</jv> = RestClient
981 *       .<jsm>create</jsm>()
982 *       .disableRedirectHandling()
983 *       .connectionManager(<jv>myConnectionManager</jv>)
984 *       .addInterceptorFirst(<jv>myHttpRequestInterceptor</jv>)
985 *       .build();
986 * </p>
987 *
988 * <p>
989 * Refer to the {@link HttpClientBuilder HTTP Client Builder API} for more information.
990 *
991 *
992 * <h4 class='topic'>Extending RestClient</h4>
993 *
994 * <p>
995 * The <c>RestClient</c> API has been designed to allow for the ability to be easily extended.
996 * The following example that overrides the primary run method shows how this can be done.
997 *
998 * <h5 class='figure'>Example:</h5>
999 * <p class='bjava'>
1000 *    <jk>public class</jk> MyRestClient <jk>extends</jk> RestClient {
1001 *
1002 *       <jc>// Must provide this constructor!</jc>
1003 *       <jk>public</jk> MyRestClient(RestClient.Builder <jv>builder</jv>) {
1004 *          <jk>super</jk>(<jv>builder</jv>);
1005 *       }
1006 *
1007 *       <jd>/** Optionally override to customize builder settings before initialization. </jd>
1008 *       <ja>@Override</ja>
1009 *       <jk>protected void</jk> init(RestClient.Builder) {...}
1010 *
1011 *       <jd>/** Optionally override to provide post-initialization (e.g. setting up SAML handshakes, etc...). </jd>
1012 *       <ja>@Override</ja>
1013 *       <jk>protected void</jk> init() {...}
1014 *
1015 *       <jd>/** Optionally override to customize requests when they're created (e.g. add headers to each request). </jd>
1016 *       <ja>@Override</ja>
1017 *       <jk>protected</jk> RestRequest request(RestOperation) {...}
1018 *
1019 *       <jd>/** Optionally override to implement your own call handling. </jd>
1020 *       <ja>@Override</ja>
1021 *       <jk>protected</jk> HttpResponse run(HttpHost, HttpRequest, HttpContext) {...}
1022 *
1023 *       <jd>/** Optionally override to customize requests before they're executed. </jd>
1024 *       <ja>@Override</ja>
1025 *       <jk>protected void</jk> onCallInit(RestRequest) {...}
1026 *
1027 *       <jd>/** Optionally override to customize responses as soon as a connection is made. </jd>
1028 *       <ja>@Override</ja>
1029 *       <jk>protected void</jk> onCallConnect(RestRequest, RestResponse) {...}
1030 *
1031 *       <jd>/** Optionally override to perform any call cleanup. </jd>
1032 *       <ja>@Override</ja>
1033 *       <jk>protected void</jk> onCallClose(RestRequest, RestResponse) {...}
1034 *    }
1035 *
1036 *    <jc>// Instantiate your client.</jc>
1037 *    MyRestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().json().build(MyRestClient.<jk>class</jk>);
1038 * </p>
1039 *
1040 * <p>
1041 * The {@link RestRequest} and {@link RestResponse} objects can also be extended and integrated by overriding the
1042 * {@link RestClient#createRequest(URI,String,boolean)} and {@link RestClient#createResponse(RestRequest,HttpResponse,Parser)} methods.
1043 *
1044 * <h5 class='section'>Notes:</h5><ul>
1045 *    <li class='note'>This class is thread safe and reusable.
1046 * </ul>
1047 *
1048 * <h5 class='section'>See Also:</h5><ul>
1049 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauRestClientBasics">juneau-rest-client Basics</a>
1050 * </ul>
1051 */
1052@SuppressWarnings("resource")
1053public class RestClient extends BeanContextable implements HttpClient, Closeable {
1054   /**
1055    * Builder class.
1056    */
1057   public static class Builder extends BeanContextable.Builder {
1058
1059      private BeanCreator<RestCallHandler> callHandler;
1060      private BeanStore beanStore = BeanStore.create().build();
1061      private BiPredicate<RestRequest,RestResponse> logRequestsPredicate;
1062      private boolean detectLeaks;
1063      private boolean executorServiceShutdownOnClose;
1064      private boolean ignoreErrors;
1065      private boolean keepHttpClientOpen;
1066      private boolean logToConsole;
1067      private boolean pooled;
1068      private boolean skipEmptyFormData;
1069      private boolean skipEmptyHeaderData;
1070      private boolean skipEmptyQueryData;
1071      private CloseableHttpClient httpClient;
1072      private DetailLevel logRequests;
1073      private ExecutorService executorService;
1074      private HeaderList headerData;
1075      private HttpClientBuilder httpClientBuilder;
1076      private HttpClientConnectionManager connectionManager;
1077      private HttpPartParser.Creator partParser;
1078      private HttpPartSerializer.Creator partSerializer;
1079      private Level logRequestsLevel;
1080      private Logger logger;
1081      private PartList formData;
1082      private PartList pathData;
1083      private PartList queryData;
1084      private ParserSet.Builder parsers;
1085      private Predicate<Integer> errorCodes = x -> x <= 0 || x >= 400;
1086      private PrintStream console;
1087      private SerializerSet.Builder serializers;
1088      private String rootUrl;
1089      private UrlEncodingSerializer.Builder urlEncodingSerializer;
1090      List<RestCallInterceptor> interceptors;
1091
1092      /**
1093       * Constructor.
1094       */
1095      protected Builder() {}
1096
1097      /**
1098       * Appends an <c>Accept</c> header on this request.
1099       *
1100       * <p>
1101       * This is a shortcut for calling <c>headerData().append(Accept.<jsm>of</jsm>(<jv>value</jv>))</c>.
1102       *
1103       * @param value
1104       *    The new header value.
1105       *    <br>Can be <jk>null</jk> (no Accept header will be added).
1106       * @return This object.
1107       * @see #headers()
1108       */
1109      public Builder accept(String value) {
1110         return headers(Accept.of(value));
1111      }
1112
1113      /**
1114       * Sets the value for the <c>Accept-Charset</c> request header on all requests.
1115       *
1116       * <p>
1117       * This is a shortcut for calling <c>headerData().append(AcceptCharset.<jsm>of</jsm>(<jv>value</jv>))</c>.
1118       *
1119       * @param value The new header value.
1120       *    <br>Can be <jk>null</jk> (no Accept-Charset header will be added).
1121       * @return This object.
1122       * @see #headers()
1123       */
1124      public Builder acceptCharset(String value) {
1125         return headers(AcceptCharset.of(value));
1126      }
1127
1128      /**
1129       * <i><l>Serializer</l> configuration property:&emsp;</i>  Add <js>"_type"</js> properties when needed.
1130       *
1131       * <p>
1132       * When enabled, <js>"_type"</js> properties will be added to beans if their type cannot be inferred
1133       * through reflection.
1134       *
1135       * <p>
1136       * This is used to recreate the correct objects during parsing if the object types cannot be inferred.
1137       * <br>For example, when serializing a <c>Map&lt;String,Object&gt;</c> field where the bean class cannot be determined from
1138       * the type of the values.
1139       *
1140       * <p>
1141       * Note the differences between the following settings:
1142       * <ul class='javatree'>
1143       *    <li class='jf'>{@link #addRootType()} - Affects whether <js>'_type'</js> is added to root node.
1144       *    <li class='jf'>{@link #addBeanTypes()} - Affects whether <js>'_type'</js> is added to any nodes.
1145       * </ul>
1146       *
1147       * <h5 class='section'>Example:</h5>
1148       * <p class='bjava'>
1149       *    <jc>// Create a JSON client that adds _type to nodes in the request body.</jc>
1150       *    RestClient <jv>client</jv> = RestClient
1151       *       .<jsm>create</jsm>()
1152       *       .json()
1153       *       .addBeanTypes()
1154       *       .build();
1155       *
1156       *    <jc>// Our map of beans to serialize.</jc>
1157       *    <ja>@Bean</ja>(typeName=<js>"mybean"</js>)
1158       *    <jk>public class</jk> MyBean {
1159       *       <jk>public</jk> String <jf>foo</jf> = <js>"bar"</js>;
1160       *    }
1161       *
1162       *    AMap <jv>map</jv> = AMap.of(<js>"foo"</js>, <jk>new</jk> MyBean());
1163       *
1164       *    <jc>// Request body will contain:  {"foo":{"_type":"mybean","foo":"bar"}}</jc>
1165       *    <jv>client</jv>
1166       *       .post(<js>"http://localhost:10000/foo"</js>, <jv>map</jv>)
1167       *       .run();
1168       * </p>
1169       *
1170       * <h5 class='section'>See Also:</h5><ul>
1171       *    <li class='jm'>{@link org.apache.juneau.serializer.Serializer.Builder#addBeanTypes()}
1172       * </ul>
1173       *
1174       * @return This object.
1175       */
1176      public Builder addBeanTypes() {
1177         serializers().forEach(org.apache.juneau.serializer.Serializer.Builder::addBeanTypes);
1178         return this;
1179      }
1180
1181      /**
1182       * Adds this protocol interceptor to the head of the protocol processing list.
1183       *
1184       * <h5 class='section'>Notes:</h5><ul>
1185       *    <li class='note'>This value can be overridden by the {@link #httpProcessor(HttpProcessor)} method.
1186       * </ul>
1187       *
1188       * @param itcp New property value.
1189       *    <br>Cannot be <jk>null</jk>.
1190       * @return This object.
1191       * @see HttpClientBuilder#addInterceptorFirst(HttpRequestInterceptor)
1192       */
1193      public Builder addInterceptorFirst(HttpRequestInterceptor itcp) {
1194         httpClientBuilder().addInterceptorFirst(assertArgNotNull("itcp", itcp));
1195         return this;
1196      }
1197
1198      /**
1199       * Adds this protocol interceptor to the head of the protocol processing list.
1200       *
1201       * <h5 class='section'>Notes:</h5><ul>
1202       *    <li class='note'>This value can be overridden by the {@link #httpProcessor(HttpProcessor)} method.
1203       * </ul>
1204       *
1205       * @param itcp New property value.
1206       *    <br>Cannot be <jk>null</jk>.
1207       * @return This object.
1208       * @see HttpClientBuilder#addInterceptorFirst(HttpResponseInterceptor)
1209       */
1210      public Builder addInterceptorFirst(HttpResponseInterceptor itcp) {
1211         httpClientBuilder().addInterceptorFirst(assertArgNotNull("itcp", itcp));
1212         return this;
1213      }
1214
1215      /**
1216       * Adds this protocol interceptor to the tail of the protocol processing list.
1217       *
1218       * <h5 class='section'>Notes:</h5><ul>
1219       *    <li class='note'>This value can be overridden by the {@link #httpProcessor(HttpProcessor)} method.
1220       * </ul>
1221       *
1222       * @param itcp New property value.
1223       *    <br>Cannot be <jk>null</jk>.
1224       * @return This object.
1225       * @see HttpClientBuilder#addInterceptorLast(HttpRequestInterceptor)
1226       */
1227      public Builder addInterceptorLast(HttpRequestInterceptor itcp) {
1228         httpClientBuilder().addInterceptorLast(assertArgNotNull("itcp", itcp));
1229         return this;
1230      }
1231
1232      /**
1233       * Adds this protocol interceptor to the tail of the protocol processing list.
1234       *
1235       * <h5 class='section'>Notes:</h5><ul>
1236       *    <li class='note'>This value can be overridden by the {@link #httpProcessor(HttpProcessor)} method.
1237       * </ul>
1238       *
1239       * @param itcp New property value.
1240       *    <br>Cannot be <jk>null</jk>.
1241       * @return This object.
1242       * @see HttpClientBuilder#addInterceptorLast(HttpResponseInterceptor)
1243       */
1244      public Builder addInterceptorLast(HttpResponseInterceptor itcp) {
1245         httpClientBuilder().addInterceptorLast(assertArgNotNull("itcp", itcp));
1246         return this;
1247      }
1248
1249      /**
1250       * <i><l>Serializer</l> configuration property:&emsp;</i>  Add type attribute to root nodes.
1251       *
1252       * <p>
1253       * When enabled, <js>"_type"</js> properties will be added to top-level beans.
1254       *
1255       * <p>
1256       * When disabled, it is assumed that the parser knows the exact Java POJO type being parsed, and therefore top-level
1257       * type information that might normally be included to determine the data type will not be serialized.
1258       *
1259       * <p>
1260       * For example, when serializing a top-level POJO with a {@link Bean#typeName() @Bean(typeName)} value, a
1261       * <js>'_type'</js> attribute will only be added when this setting is enabled.
1262       *
1263       * <p>
1264       * Note the differences between the following settings:
1265       * <ul class='javatree'>
1266       *    <li class='jf'>{@link #addRootType()} - Affects whether <js>'_type'</js> is added to root node.
1267       *    <li class='jf'>{@link #addBeanTypes()} - Affects whether <js>'_type'</js> is added to any nodes.
1268       * </ul>
1269       *
1270       * <h5 class='section'>Example:</h5>
1271       * <p class='bjava'>
1272       *    <jc>// Create a JSON client that adds _type to root node.</jc>
1273       *    RestClient <jv>client</jv> = RestClient
1274       *       .<jsm>create</jsm>()
1275       *       .json()
1276       *       .addRootType()
1277       *       .build();
1278       *
1279       *    <jc>// Our bean to serialize.</jc>
1280       *    <ja>@Bean</ja>(typeName=<js>"mybean"</js>)
1281       *    <jk>public class</jk> MyBean {
1282       *       <jk>public</jk> String <jf>foo</jf> = <js>"bar"</js>;
1283       *    }
1284       *
1285       *    <jc>// Request body will contain:  {"_type":"mybean","foo":"bar"}</jc>
1286       *    <jv>client</jv>
1287       *       .post(<js>"http://localhost:10000/foo"</js>, <jk>new</jk> MyBean())
1288       *       .run();
1289       * </p>
1290       *
1291       * <h5 class='section'>See Also:</h5><ul>
1292       *    <li class='jm'>{@link org.apache.juneau.serializer.Serializer.Builder#addRootType()}
1293       * </ul>
1294       *
1295       * @return This object.
1296       */
1297      public Builder addRootType() {
1298         serializers().forEach(org.apache.juneau.serializer.Serializer.Builder::addRootType);
1299         return this;
1300      }
1301
1302      @Override /* Overridden from Builder */
1303      public Builder annotations(Annotation...values) {
1304         super.annotations(values);
1305         return this;
1306      }
1307
1308      @Override /* Overridden from Builder */
1309      public Builder apply(AnnotationWorkList work) {
1310         super.apply(work);
1311         return this;
1312      }
1313
1314      @Override /* Overridden from Builder */
1315      public Builder applyAnnotations(Class<?>...from) {
1316         super.applyAnnotations(from);
1317         return this;
1318      }
1319
1320      @Override /* Overridden from Builder */
1321      public Builder applyAnnotations(Object...from) {
1322         super.applyAnnotations(from);
1323         return this;
1324      }
1325
1326      /**
1327       * Assigns {@link BackoffManager} instance.
1328       *
1329       * @param backoffManager New property value.
1330       *    <br>Can be <jk>null</jk> (value will not be set, default behavior will be used).
1331       * @return This object.
1332       * @see HttpClientBuilder#setBackoffManager(BackoffManager)
1333       */
1334      public Builder backoffManager(BackoffManager backoffManager) {
1335         httpClientBuilder().setBackoffManager(backoffManager);
1336         return this;
1337      }
1338
1339      /**
1340       * Set up this client to use BASIC auth.
1341       *
1342       * <h5 class='section'>Example:</h5>
1343       * <p class='bjava'>
1344       *    <jc>// Construct a client that uses BASIC authentication.</jc>
1345       *    RestClient <jv>client</jv> = RestClient
1346       *       .<jsm>create</jsm>()
1347       *       .basicAuth(<js>"http://localhost"</js>, 80, <js>"me"</js>, <js>"mypassword"</js>)
1348       *       .build();
1349       * </p>
1350       *
1351       * @param host The auth scope hostname.
1352       *    <br>Can be <jk>null</jk> (will use <js>"*"</js> as the hostname).
1353       * @param port The auth scope port.
1354       * @param user The username.
1355       *    <br>Can be <jk>null</jk> (will use empty string).
1356       * @param pw The password.
1357       *    <br>Can be <jk>null</jk> (will use empty string).
1358       * @return This object.
1359       */
1360      public Builder basicAuth(String host, int port, String user, String pw) {
1361         var scope = new AuthScope(host, port);
1362         var up = new UsernamePasswordCredentials(user, pw);
1363         var p = new BasicCredentialsProvider();
1364         p.setCredentials(scope, up);
1365         defaultCredentialsProvider(p);
1366         return this;
1367      }
1368
1369      @Override /* Overridden from Builder */
1370      public Builder beanClassVisibility(Visibility value) {
1371         super.beanClassVisibility(value);
1372         return this;
1373      }
1374
1375      @Override /* Overridden from Builder */
1376      public Builder beanConstructorVisibility(Visibility value) {
1377         super.beanConstructorVisibility(value);
1378         return this;
1379      }
1380
1381      @Override /* Overridden from Builder */
1382      public Builder beanContext(BeanContext value) {
1383         super.beanContext(value);
1384         return this;
1385      }
1386
1387      @Override /* Overridden from Builder */
1388      public Builder beanContext(BeanContext.Builder value) {
1389         super.beanContext(value);
1390         return this;
1391      }
1392
1393      @Override /* Overridden from Builder */
1394      public Builder beanDictionary(java.lang.Class<?>...values) {
1395         super.beanDictionary(values);
1396         return this;
1397      }
1398
1399      @Override /* Overridden from Builder */
1400      public Builder beanFieldVisibility(Visibility value) {
1401         super.beanFieldVisibility(value);
1402         return this;
1403      }
1404
1405      @Override /* Overridden from Builder */
1406      public Builder beanInterceptor(Class<?> on, Class<? extends org.apache.juneau.swap.BeanInterceptor<?>> value) {
1407         super.beanInterceptor(on, value);
1408         return this;
1409      }
1410
1411      @Override /* Overridden from Builder */
1412      public Builder beanMethodVisibility(Visibility value) {
1413         super.beanMethodVisibility(value);
1414         return this;
1415      }
1416
1417      @Override /* Overridden from Builder */
1418      public Builder beanProperties(Class<?> beanClass, String properties) {
1419         super.beanProperties(beanClass, properties);
1420         return this;
1421      }
1422
1423      @Override /* Overridden from Builder */
1424      public Builder beanProperties(Map<String,Object> values) {
1425         super.beanProperties(values);
1426         return this;
1427      }
1428
1429      @Override /* Overridden from Builder */
1430      public Builder beanProperties(String beanClassName, String properties) {
1431         super.beanProperties(beanClassName, properties);
1432         return this;
1433      }
1434
1435      @Override /* Overridden from Builder */
1436      public Builder beanPropertiesExcludes(Class<?> beanClass, String properties) {
1437         super.beanPropertiesExcludes(beanClass, properties);
1438         return this;
1439      }
1440
1441      @Override /* Overridden from Builder */
1442      public Builder beanPropertiesExcludes(Map<String,Object> values) {
1443         super.beanPropertiesExcludes(values);
1444         return this;
1445      }
1446
1447      @Override /* Overridden from Builder */
1448      public Builder beanPropertiesExcludes(String beanClassName, String properties) {
1449         super.beanPropertiesExcludes(beanClassName, properties);
1450         return this;
1451      }
1452
1453      @Override /* Overridden from Builder */
1454      public Builder beanPropertiesReadOnly(Class<?> beanClass, String properties) {
1455         super.beanPropertiesReadOnly(beanClass, properties);
1456         return this;
1457      }
1458
1459      @Override /* Overridden from Builder */
1460      public Builder beanPropertiesReadOnly(Map<String,Object> values) {
1461         super.beanPropertiesReadOnly(values);
1462         return this;
1463      }
1464
1465      @Override /* Overridden from Builder */
1466      public Builder beanPropertiesReadOnly(String beanClassName, String properties) {
1467         super.beanPropertiesReadOnly(beanClassName, properties);
1468         return this;
1469      }
1470
1471      @Override /* Overridden from Builder */
1472      public Builder beanPropertiesWriteOnly(Class<?> beanClass, String properties) {
1473         super.beanPropertiesWriteOnly(beanClass, properties);
1474         return this;
1475      }
1476
1477      @Override /* Overridden from Builder */
1478      public Builder beanPropertiesWriteOnly(Map<String,Object> values) {
1479         super.beanPropertiesWriteOnly(values);
1480         return this;
1481      }
1482
1483      @Override /* Overridden from Builder */
1484      public Builder beanPropertiesWriteOnly(String beanClassName, String properties) {
1485         super.beanPropertiesWriteOnly(beanClassName, properties);
1486         return this;
1487      }
1488
1489      @Override /* Overridden from Builder */
1490      public Builder beansRequireDefaultConstructor() {
1491         super.beansRequireDefaultConstructor();
1492         return this;
1493      }
1494
1495      @Override /* Overridden from Builder */
1496      public Builder beansRequireSerializable() {
1497         super.beansRequireSerializable();
1498         return this;
1499      }
1500
1501      @Override /* Overridden from Builder */
1502      public Builder beansRequireSettersForGetters() {
1503         super.beansRequireSettersForGetters();
1504         return this;
1505      }
1506
1507      @Override /* Overridden from Context.Builder */
1508      public RestClient build() {
1509         return build(RestClient.class);
1510      }
1511
1512      @Override /* Overridden from Builder */
1513      public Builder cache(Cache<HashKey,? extends org.apache.juneau.Context> value) {
1514         super.cache(value);
1515         return this;
1516      }
1517
1518      /**
1519       * Returns the creator for the rest call handler.
1520       *
1521       * <p>
1522       * Allows you to provide a custom handler for making HTTP calls.
1523       *
1524       * <h5 class='section'>Example:</h5>
1525       * <p class='bjava'>
1526       *    <jc>// Create a client that handles processing of requests using a custom handler.</jc>
1527       *    <jk>public class</jk> MyRestCallHandler <jk>implements</jk> RestCallHandler {
1528       *
1529       *       <ja>@Override</ja>
1530       *       <jk>public</jk> HttpResponse run(HttpHost <jv>target</jv>, HttpRequest <jv>request</jv>, HttpContext <jv>context</jv>) <jk>throws</jk> IOException {
1531       *          <jc>// Custom handle requests.</jc>
1532       *       }
1533       *    }
1534       *
1535       *    RestClient <jv>client</jv> = RestClient
1536       *       .<jsm>create</jsm>()
1537       *       .callHandler(MyRestCallHandler.<jk>class</jk>)
1538       *       .build();
1539       * </p>
1540       *
1541       * <h5 class='section'>Notes:</h5><ul>
1542       *    <li class='note'>
1543       *       The {@link RestClient#run(HttpHost, HttpRequest, HttpContext)} method can also be overridden to produce the same results.
1544       *    <li class='note'>
1545       *       Use {@link BeanCreator#impl(Object)} to specify an already instantiated instance.
1546       *    <li class='note'>
1547       *       Use {@link BeanCreator#type(Class)} to specify a subtype to instantiate.
1548       *       <br>Subclass must have a public constructor that takes in any args available
1549       *       in the bean store of this builder (including {@link RestClient} itself).
1550       * </ul>
1551       *
1552       * <h5 class='section'>See Also:</h5><ul>
1553       *    <li class='jic'>{@link RestCallHandler}
1554       * </ul>
1555       *
1556       * @return The creator for the rest call handler.
1557       */
1558      public final BeanCreator<RestCallHandler> callHandler() {
1559         if (callHandler == null)
1560            callHandler = createCallHandler();
1561         return callHandler;
1562      }
1563
1564      /**
1565       * REST call handler class.
1566       *
1567       * <p>
1568       * Specifies a custom handler for making HTTP calls.
1569       *
1570       * <p>
1571       * This is a shortcut for <c>callHandler().type(<jv>value</jv>)</c>.
1572       *
1573       * @param value
1574       *    The new value for this setting.
1575       *    <br>Cannot be <jk>null</jk>.
1576       * @return This object.
1577       * @see #callHandler()
1578       */
1579      public Builder callHandler(Class<? extends RestCallHandler> value) {
1580         callHandler().type(assertArgNotNull("value", value));
1581         return this;
1582      }
1583
1584      /**
1585       * Sets the client version by setting the value for the <js>"Client-Version"</js> header.
1586       *
1587       * <p>
1588       * This is a shortcut for calling <c>headerData().append(ClientVersion.<jsm>of</jsm>(<jv>value</jv>))</c>.
1589       *
1590       * @param value The version string (e.g. <js>"1.2.3"</js>)
1591       *    <br>Can be <jk>null</jk> (no Client-Version header will be added).
1592       * @return This object.
1593       * @see #headers()
1594       */
1595      public Builder clientVersion(String value) {
1596         return headers(ClientVersion.of(value));
1597      }
1598
1599      /**
1600       * Assigns {@link ConnectionBackoffStrategy} instance.
1601       *
1602       * @param connectionBackoffStrategy New property value.
1603       *    <br>Can be <jk>null</jk> (value will not be set, default behavior will be used).
1604       * @return This object.
1605       * @see HttpClientBuilder#setConnectionBackoffStrategy(ConnectionBackoffStrategy)
1606       */
1607      public Builder connectionBackoffStrategy(ConnectionBackoffStrategy connectionBackoffStrategy) {
1608         httpClientBuilder().setConnectionBackoffStrategy(connectionBackoffStrategy);
1609         return this;
1610      }
1611
1612      /**
1613       * Assigns {@link HttpClientConnectionManager} instance.
1614       *
1615       * @param value New property value.
1616       *    <br>Can be <jk>null</jk> (value will not be set, a default connection manager will be created).
1617       * @return This object.
1618       * @see HttpClientBuilder#setConnectionManager(HttpClientConnectionManager)
1619       */
1620      public Builder connectionManager(HttpClientConnectionManager value) {
1621         connectionManager = value;
1622         httpClientBuilder().setConnectionManager(value);
1623         return this;
1624      }
1625
1626      /**
1627       * Defines the connection manager is to be shared by multiple client instances.
1628       *
1629       * <h5 class='section'>Notes:</h5><ul>
1630       *    <li class='note'>If the connection manager is shared its life-cycle is expected to be managed by the caller and it will not be shut down if the client is closed.
1631       * </ul>
1632       *
1633       * @param shared New property value.
1634       * @return This object.
1635       * @see HttpClientBuilder#setConnectionManagerShared(boolean)
1636       */
1637      public Builder connectionManagerShared(boolean shared) {
1638         httpClientBuilder().setConnectionManagerShared(shared);
1639         return this;
1640      }
1641
1642      /**
1643       * Assigns {@link ConnectionReuseStrategy} instance.
1644       *
1645       * @param reuseStrategy New property value.
1646       *    <br>Can be <jk>null</jk> (value will not be set, default behavior will be used).
1647       * @return This object.
1648       * @see HttpClientBuilder#setConnectionReuseStrategy(ConnectionReuseStrategy)
1649       */
1650      public Builder connectionReuseStrategy(ConnectionReuseStrategy reuseStrategy) {
1651         httpClientBuilder().setConnectionReuseStrategy(reuseStrategy);
1652         return this;
1653      }
1654
1655      /**
1656       * Sets maximum time to live for persistent connections.
1657       *
1658       * <h5 class='section'>Notes:</h5><ul>
1659       *    <li class='note'>This value can be overridden by the {@link #connectionManager(HttpClientConnectionManager)} method.
1660       * </ul>
1661       *
1662       * @param connTimeToLive New property value.
1663       * @param connTimeToLiveTimeUnit New property value.
1664       *    <br>Cannot be <jk>null</jk>.
1665       * @return This object.
1666       * @see HttpClientBuilder#setConnectionTimeToLive(long,TimeUnit)
1667       */
1668      public Builder connectionTimeToLive(long connTimeToLive, TimeUnit connTimeToLiveTimeUnit) {
1669         httpClientBuilder().setConnectionTimeToLive(connTimeToLive, connTimeToLiveTimeUnit);
1670         return this;
1671      }
1672
1673      /**
1674       * Console print stream
1675       *
1676       * <p>
1677       * Allows you to redirect the console output to a different print stream.
1678       *
1679       * @param value
1680       *    The new value for this setting.
1681       *    <br>Can be <jk>null</jk> (defaults to <c>System.err</c>).
1682       * @return This object.
1683       */
1684      public Builder console(PrintStream value) {
1685         console = value;
1686         return this;
1687      }
1688
1689      /**
1690       * Assigns a map of {@link org.apache.http.client.entity.InputStreamFactory InputStreamFactories} to be used for automatic content decompression.
1691       *
1692       * @param contentDecoderMap New property value.
1693       *    <br>Can be <jk>null</jk> (value will not be set, default behavior will be used).
1694       * @return This object.
1695       * @see HttpClientBuilder#setContentDecoderRegistry(Map)
1696       */
1697      public Builder contentDecoderRegistry(Map<String,InputStreamFactory> contentDecoderMap) {
1698         httpClientBuilder().setContentDecoderRegistry(contentDecoderMap);
1699         return this;
1700      }
1701
1702      /**
1703       * Sets the value for the <c>Content-Type</c> request header on all requests.
1704       *
1705       * <p>
1706       * This is a shortcut for calling <c>headerData().append(ContentType.<jsm>of</jsm>(<jv>value</jv>))</c>.
1707       *
1708       * <p>
1709       * This overrides the media type specified on the serializer.
1710       *
1711       * @param value The new header value.
1712       *    <br>Can be <jk>null</jk> (no Content-Type header will be added).
1713       * @return This object.
1714       * @see #headers()
1715       */
1716      public Builder contentType(String value) {
1717         return headers(ContentType.of(value));
1718      }
1719
1720      @Override /* Overridden from Context.Builder */
1721      public Builder copy() {
1722         throw new NoSuchMethodError("Not implemented.");
1723      }
1724
1725      /**
1726       * Sets the value for the <c>Debug</c> request header on all requests.
1727       *
1728       * <p>
1729       * This is a shortcut for calling <c>headerData().append(Debug.<jsm>of</jsm>(<jv>value</jv>))</c>.
1730       *
1731       * @return This object.
1732       * @see #headers()
1733       */
1734      @Override
1735      public Builder debug() {
1736         super.debug();
1737         serializers().forEach(org.apache.juneau.serializer.Serializer.Builder::debug);
1738         return headers(Debug.TRUE);
1739      }
1740
1741      /**
1742       * <i><l>Parser</l> configuration property:&emsp;</i>  Debug output lines.
1743       *
1744       * <p>
1745       * When parse errors occur, this specifies the number of lines of input before and after the
1746       * error location to be printed as part of the exception message.
1747       *
1748       * <h5 class='section'>Example:</h5>
1749       * <p class='bjava'>
1750       *    <jc>// Create a parser whose exceptions print out 100 lines before and after the parse error location.</jc>
1751       *    RestClient <jv>client</jv> = RestClient
1752       *       .<jsm>create</jsm>()
1753       *       .json()
1754       *       .debug()  <jc>// Enable debug mode to capture Reader contents as strings.</jc>
1755       *       .debugOuputLines(100)
1756       *       .build();
1757       *
1758       *    <jc>// Try to parse some bad JSON.</jc>
1759       *    <jk>try</jk> {
1760       *       <jv>client</jv>
1761       *          .get(<js>"/pathToBadJson"</js>)
1762       *          .run()
1763       *          .getContent().as(Object.<jk>class</jk>);  <jc>// Try to parse it.</jc>
1764       *    } <jk>catch</jk> (RestCallException <jv>e</jv>) {
1765       *       System.<jsf>err</jsf>.println(<jv>e</jv>.getMessage());  <jc>// Will display 200 lines of the output.</jc>
1766       *    }
1767       * </p>
1768       *
1769       * <h5 class='section'>See Also:</h5><ul>
1770       *    <li class='jm'>{@link org.apache.juneau.parser.Parser.Builder#debugOutputLines(int)}
1771       * </ul>
1772       *
1773       * @param value
1774       *    The new value for this property.
1775       *    <br>The default value is <c>5</c>.
1776       * @return This object.
1777       */
1778      public Builder debugOutputLines(int value) {
1779         parsers().forEach(x -> x.debugOutputLines(value));
1780         return this;
1781      }
1782
1783      /**
1784       * Assigns default {@link org.apache.http.auth.AuthScheme} registry which will be used for request execution if not explicitly set in the client execution context.
1785       *
1786       * @param authSchemeRegistry New property value.
1787       *    <br>Can be <jk>null</jk> (value will not be set, default behavior will be used).
1788       * @return This object.
1789       * @see HttpClientBuilder#setDefaultAuthSchemeRegistry(Lookup)
1790       */
1791      public Builder defaultAuthSchemeRegistry(Lookup<AuthSchemeProvider> authSchemeRegistry) {
1792         httpClientBuilder().setDefaultAuthSchemeRegistry(authSchemeRegistry);
1793         return this;
1794      }
1795
1796      /**
1797       * Assigns default {@link ConnectionConfig}.
1798       *
1799       * <h5 class='section'>Notes:</h5><ul>
1800       *    <li class='note'>This value can be overridden by the {@link #connectionManager(HttpClientConnectionManager)} method.
1801       * </ul>
1802       *
1803       * @param config New property value.
1804       *    <br>Can be <jk>null</jk> (value will not be set, default behavior will be used).
1805       * @return This object.
1806       * @see HttpClientBuilder#setDefaultConnectionConfig(ConnectionConfig)
1807       */
1808      public Builder defaultConnectionConfig(ConnectionConfig config) {
1809         httpClientBuilder().setDefaultConnectionConfig(config);
1810         return this;
1811      }
1812
1813      /**
1814       * Assigns default {@link CookieSpec} registry which will be used for request execution if not explicitly set in the client execution context.
1815       *
1816       * @param cookieSpecRegistry New property value.
1817       *    <br>Can be <jk>null</jk> (value will not be set, default behavior will be used).
1818       * @return This object.
1819       * @see HttpClientBuilder#setDefaultCookieSpecRegistry(Lookup)
1820       */
1821      public Builder defaultCookieSpecRegistry(Lookup<CookieSpecProvider> cookieSpecRegistry) {
1822         httpClientBuilder().setDefaultCookieSpecRegistry(cookieSpecRegistry);
1823         return this;
1824      }
1825
1826      /**
1827       * Assigns default {@link CookieStore} instance which will be used for request execution if not explicitly set in the client execution context.
1828       *
1829       * @param cookieStore New property value.
1830       *    <br>Can be <jk>null</jk> (value will not be set, default behavior will be used).
1831       * @return This object.
1832       * @see HttpClientBuilder#setDefaultCookieStore(CookieStore)
1833       */
1834      public Builder defaultCookieStore(CookieStore cookieStore) {
1835         httpClientBuilder().setDefaultCookieStore(cookieStore);
1836         return this;
1837      }
1838
1839      /**
1840       * Assigns default {@link CredentialsProvider} instance which will be used for request execution if not explicitly set in the client execution context.
1841       *
1842       * @param credentialsProvider New property value.
1843       *    <br>Can be <jk>null</jk> (value will not be set, default behavior will be used).
1844       * @return This object.
1845       * @see HttpClientBuilder#setDefaultCredentialsProvider(CredentialsProvider)
1846       */
1847      public Builder defaultCredentialsProvider(CredentialsProvider credentialsProvider) {
1848         httpClientBuilder().setDefaultCredentialsProvider(credentialsProvider);
1849         return this;
1850      }
1851
1852      /**
1853       * Assigns default {@link RequestConfig} instance which will be used for request execution if not explicitly set in the client execution context.
1854       *
1855       * @param config New property value.
1856       *    <br>Can be <jk>null</jk> (value will not be set, default behavior will be used).
1857       * @return This object.
1858       * @see HttpClientBuilder#setDefaultRequestConfig(RequestConfig)
1859       */
1860      public Builder defaultRequestConfig(RequestConfig config) {
1861         httpClientBuilder().setDefaultRequestConfig(config);
1862         return this;
1863      }
1864
1865      /**
1866       * Assigns default {@link SocketConfig}.
1867       *
1868       * <h5 class='section'>Notes:</h5><ul>
1869       *    <li class='note'>This value can be overridden by the {@link #connectionManager(HttpClientConnectionManager)} method.
1870       * </ul>
1871       *
1872       * @param config New property value.
1873       *    <br>Can be <jk>null</jk> (value will not be set, default behavior will be used).
1874       * @return This object.
1875       * @see HttpClientBuilder#setDefaultSocketConfig(SocketConfig)
1876       */
1877      public Builder defaultSocketConfig(SocketConfig config) {
1878         httpClientBuilder().setDefaultSocketConfig(config);
1879         return this;
1880      }
1881
1882      /**
1883       * <i><l>RestClient</l> configuration property:&emsp;</i>  Enable leak detection.
1884       *
1885       * <p>
1886       * Enable client and request/response leak detection.
1887       *
1888       * <p>
1889       * Causes messages to be logged to the console if clients or request/response objects are not properly closed
1890       * when the <c>finalize</c> methods are invoked.
1891       *
1892       * <p>
1893       * Automatically enabled with {@link org.apache.juneau.Context.Builder#debug()}.
1894       *
1895       * <h5 class='section'>Example:</h5>
1896       * <p class='bjava'>
1897       *    <jc>// Create a client that logs a message if </jc>
1898       *    RestClient <jv>client</jv> = RestClient
1899       *       .<jsm>create</jsm>()
1900       *       .detectLeaks()
1901       *       .logToConsole()  <jc>// Also log the error message to System.err</jc>
1902       *       .build();
1903       *
1904       *    <jv>client</jv>.closeQuietly();  <jc>// Customized HttpClient won't be closed.</jc>
1905       * </p>
1906       *
1907       * @return This object.
1908       */
1909      public Builder detectLeaks() {
1910         detectLeaks = true;
1911         return this;
1912      }
1913
1914      /**
1915       * <i><l>BeanTraverse</l> configuration property:&emsp;</i>  Automatically detect POJO recursions.
1916       *
1917       * <p>
1918       * When enabled, specifies that recursions should be checked for during traversal.
1919       *
1920       * <p>
1921       * Recursions can occur when traversing models that aren't true trees but rather contain loops.
1922       * <br>In general, unchecked recursions cause stack-overflow-errors.
1923       * <br>These show up as {@link BeanRecursionException BeanRecursionException} with the message <js>"Depth too deep.  Stack overflow occurred."</js>.
1924       *
1925       * <h5 class='section'>Notes:</h5><ul>
1926       *    <li class='note'>
1927       *       Checking for recursion can cause a small performance penalty.
1928       * </ul>
1929       *
1930       * <h5 class='section'>Example:</h5>
1931       * <p class='bjava'>
1932       *    <jc>// Create a JSON client that automatically checks for recursions.</jc>
1933       *    RestClient <jv>client</jv> = RestClient
1934       *       .<jsm>create</jsm>()
1935       *       .json()
1936       *       .detectRecursions()
1937       *       .build();
1938       *
1939       *    <jc>// Create a POJO model with a recursive loop.</jc>
1940       *    <jk>public class</jk> A {
1941       *       <jk>public</jk> Object <jf>f</jf>;
1942       *    }
1943       *    A <jv>a</jv> = <jk>new</jk> A();
1944       *    <jv>a</jv>.<jf>f</jf> = <jv>a</jv>;
1945       *
1946       * <jk>try</jk> {
1947       *       <jc>// Throws a RestCallException with an inner SerializeException and not a StackOverflowError</jc>
1948       *       <jv>client</jv>
1949       *          .post(<js>"http://localhost:10000/foo"</js>, <jv>a</jv>)
1950       *          .run();
1951       * } <jk>catch</jk> (RestCallException <jv>e</jv>} {
1952       *    <jc>// Handle exception.</jc>
1953       * }
1954       * </p>
1955       *
1956       * <h5 class='section'>See Also:</h5><ul>
1957       *    <li class='jm'>{@link org.apache.juneau.BeanTraverseContext.Builder#detectRecursions()}
1958       * </ul>
1959       *
1960       * @return This object.
1961       */
1962      public Builder detectRecursions() {
1963         serializers().forEach(org.apache.juneau.serializer.Serializer.Builder::detectRecursions);
1964         return this;
1965      }
1966
1967      @Override /* Overridden from Builder */
1968      public Builder dictionaryOn(Class<?> on, java.lang.Class<?>...values) {
1969         super.dictionaryOn(on, values);
1970         return this;
1971      }
1972
1973      /**
1974       * Disables authentication scheme caching.
1975       *
1976       * <h5 class='section'>Notes:</h5><ul>
1977       *    <li class='note'>This value can be overridden by the {@link #httpProcessor(HttpProcessor)} method.
1978       * </ul>
1979       *
1980       * @return This object.
1981       * @see HttpClientBuilder#disableAuthCaching()
1982       */
1983      public Builder disableAuthCaching() {
1984         httpClientBuilder().disableAuthCaching();
1985         return this;
1986      }
1987
1988      /**
1989       * Disables automatic request recovery and re-execution.
1990       *
1991       * @return This object.
1992       * @see HttpClientBuilder#disableAutomaticRetries()
1993       */
1994      public Builder disableAutomaticRetries() {
1995         httpClientBuilder().disableAutomaticRetries();
1996         return this;
1997      }
1998
1999      @Override /* Overridden from Builder */
2000      public Builder disableBeansRequireSomeProperties() {
2001         super.disableBeansRequireSomeProperties();
2002         return this;
2003      }
2004
2005      /**
2006       * Disables connection state tracking.
2007       *
2008       * @return This object.
2009       * @see HttpClientBuilder#disableConnectionState()
2010       */
2011      public Builder disableConnectionState() {
2012         httpClientBuilder().disableConnectionState();
2013         return this;
2014      }
2015
2016      /**
2017       * Disables automatic content decompression.
2018       *
2019       * <h5 class='section'>Notes:</h5><ul>
2020       *    <li class='note'>This value can be overridden by the {@link #httpProcessor(HttpProcessor)} method.
2021       * </ul>
2022       *
2023       * @return This object.
2024       * @see HttpClientBuilder#disableContentCompression()
2025       */
2026      public Builder disableContentCompression() {
2027         httpClientBuilder().disableContentCompression();
2028         return this;
2029      }
2030
2031      /**
2032       * Disables state (cookie) management.
2033       *
2034       * <h5 class='section'>Notes:</h5><ul>
2035       *    <li class='note'>This value can be overridden by the {@link #httpProcessor(HttpProcessor)} method.
2036       * </ul>
2037       *
2038       * @return This object.
2039       * @see HttpClientBuilder#disableCookieManagement()
2040       */
2041      public Builder disableCookieManagement() {
2042         httpClientBuilder().disableCookieManagement();
2043         return this;
2044      }
2045
2046      @Override /* Overridden from Builder */
2047      public Builder disableIgnoreMissingSetters() {
2048         super.disableIgnoreMissingSetters();
2049         return this;
2050      }
2051
2052      @Override /* Overridden from Builder */
2053      public Builder disableIgnoreTransientFields() {
2054         super.disableIgnoreTransientFields();
2055         return this;
2056      }
2057
2058      @Override /* Overridden from Builder */
2059      public Builder disableIgnoreUnknownNullBeanProperties() {
2060         super.disableIgnoreUnknownNullBeanProperties();
2061         return this;
2062      }
2063
2064      @Override /* Overridden from Builder */
2065      public Builder disableInterfaceProxies() {
2066         super.disableInterfaceProxies();
2067         return this;
2068      }
2069
2070      /**
2071       * Disables automatic redirect handling.
2072       *
2073       * @return This object.
2074       * @see HttpClientBuilder#disableRedirectHandling()
2075       */
2076      public Builder disableRedirectHandling() {
2077         httpClientBuilder().disableRedirectHandling();
2078         return this;
2079      }
2080
2081      /**
2082       * Errors codes predicate.
2083       *
2084       * <p>
2085       * Defines a predicate to test for error codes.
2086       *
2087       * <h5 class='section'>Example:</h5>
2088       * <p class='bjava'>
2089       *    <jc>// Create a client that considers any 300+ responses to be errors.</jc>
2090       *    RestClient <jv>client</jv> = RestClient
2091       *       .<jsm>create</jsm>()
2092       *       .errorCodes(<jv>x</jv> -&gt; <jv>x</jv>&gt;=300)
2093       *       .build();
2094       * </p>
2095       *
2096       * @param value
2097       *    The new value for this setting.
2098       *    <br>The default value is <code>x -&gt; x &gt;= 400</code>.
2099       *    <br>Cannot be <jk>null</jk>.
2100       * @return This object.
2101       */
2102      public Builder errorCodes(Predicate<Integer> value) {
2103         errorCodes = assertArgNotNull("value", value);
2104         return this;
2105      }
2106
2107      /**
2108       * Makes this instance of {@link HttpClient} proactively evict expired connections from the connection pool using a background thread.
2109       *
2110       * <h5 class='section'>Notes:</h5><ul>
2111       *    <li class='note'>One MUST explicitly close HttpClient with {@link CloseableHttpClient#close()} in order to stop and release the background thread.
2112       *    <li class='note'>This method has no effect if the instance of {@link HttpClient} is configured to use a shared connection manager.
2113       *    <li class='note'>This method may not be used when the instance of {@link HttpClient} is created inside an EJB container.
2114       * </ul>
2115       *
2116       * @return This object.
2117       * @see HttpClientBuilder#evictExpiredConnections()
2118       */
2119      public Builder evictExpiredConnections() {
2120         httpClientBuilder().evictExpiredConnections();
2121         return this;
2122      }
2123
2124      /**
2125       * Makes this instance of {@link HttpClient} proactively evict idle connections from the connection pool using a background thread.
2126       *
2127       * <h5 class='section'>Notes:</h5><ul>
2128       *    <li class='note'>One MUST explicitly close HttpClient with {@link CloseableHttpClient#close()} in order to stop and release the background thread.
2129       *    <li class='note'>This method has no effect if the instance of {@link HttpClient} is configured to use a shared connection manager.
2130       *    <li class='note'>This method may not be used when the instance of {@link HttpClient} is created inside an EJB container.
2131       * </ul>
2132       *
2133       * @param maxIdleTime New property value.
2134       * @param maxIdleTimeUnit New property value.
2135       *    <br>Cannot be <jk>null</jk>.
2136       * @return This object.
2137       * @see HttpClientBuilder#evictIdleConnections(long,TimeUnit)
2138       */
2139      public Builder evictIdleConnections(long maxIdleTime, TimeUnit maxIdleTimeUnit) {
2140         httpClientBuilder().evictIdleConnections(maxIdleTime, maxIdleTimeUnit);
2141         return this;
2142      }
2143
2144      /**
2145       * <i><l>RestClient</l> configuration property:&emsp;</i>  Executor service.
2146       *
2147       * <p>
2148       * Defines the executor service to use when calling future methods on the {@link RestRequest} class.
2149       *
2150       * <p>
2151       * This executor service is used to create {@link Future} objects on the following methods:
2152       * <ul>
2153       *    <li class='jm'>{@link RestRequest#runFuture()}
2154       *    <li class='jm'>{@link RestRequest#completeFuture()}
2155       *    <li class='jm'>{@link ResponseContent#asFuture(Class)} (and similar methods)
2156       * </ul>
2157       *
2158       * <p>
2159       * The default executor service is a single-threaded {@link ThreadPoolExecutor} with a 30 second timeout
2160       * and a queue size of 10.
2161       *
2162       * <h5 class='section'>Example:</h5>
2163       * <p class='bjava'>
2164       *    <jc>// Create a client with a customized executor service.</jc>
2165       *    RestClient <jv>client</jv> = RestClient
2166       *       .<jsm>create</jsm>()
2167       *       .executorService(<jk>new</jk> ThreadPoolExecutor(1, 1, 30, TimeUnit.<jsf>SECONDS</jsf>, <jk>new</jk> ArrayBlockingQueue&lt;Runnable&gt;(10)), <jk>true</jk>)
2168       *       .build();
2169       *
2170       *    <jc>// Use it to asynchronously run a request.</jc>
2171       *    Future&lt;RestResponse&gt; <jv>responseFuture</jv> = <jv>client</jv>.get(<jsf>URI</jsf>).runFuture();
2172       *
2173       *    <jc>// Do some other stuff.</jc>
2174       *
2175       *    <jc>// Now read the response.</jc>
2176       *    String <jv>body</jv> = <jv>responseFuture</jv>.get().getContent().asString();
2177       *
2178       *    <jc>// Use it to asynchronously retrieve a response.</jc>
2179       *    Future&lt;MyBean&gt; <jv>myBeanFuture</jv> = <jv>client</jv>
2180       *       .get(<jsf>URI</jsf>)
2181       *       .run()
2182       *       .getContent().asFuture(MyBean.<jk>class</jk>);
2183       *
2184       *    <jc>// Do some other stuff.</jc>
2185       *
2186       *    <jc>// Now read the response.</jc>
2187       *    MyBean <jv>bean</jv> = <jv>myBeanFuture</jv>.get();
2188       * </p>
2189       *
2190       * @param executorService The executor service.
2191       *    <br>Can be <jk>null</jk> (a default executor service will be created if needed).
2192       * @param shutdownOnClose Call {@link ExecutorService#shutdown()} when {@link RestClient#close()} is called.
2193       * @return This object.
2194       */
2195      public Builder executorService(ExecutorService executorService, boolean shutdownOnClose) {
2196         this.executorService = executorService;
2197         this.executorServiceShutdownOnClose = shutdownOnClose;
2198         return this;
2199      }
2200
2201      @Override /* Overridden from Builder */
2202      public Builder findFluentSetters() {
2203         super.findFluentSetters();
2204         return this;
2205      }
2206
2207      @Override /* Overridden from Builder */
2208      public Builder findFluentSetters(Class<?> on) {
2209         super.findFluentSetters(on);
2210         return this;
2211      }
2212
2213      /**
2214       * Returns the builder for the list of form data parameters that get applied to all requests created by this builder.
2215       *
2216       * <p>
2217       * This is the primary method for accessing the form data parameter list.
2218       * On first call, the builder is created via the method {@link #createFormData()}.
2219       *
2220       * <h5 class='section'>Example:</h5>
2221       * <p class='bjava'>
2222       *    <jc>// Create a client that adds a "foo=bar" form-data parameter on every request.</jc>
2223       *    RestClient.Builder <jv>builder</jv> = RestClient.<jsm>create</jsm>();
2224       *    <jv>builder</jv>.formData().setDefault(<js>"foo"</js>, <js>"bar"</js>));
2225       *    RestClient <jv>client</jv> = <jv>builder</jv>.build();
2226       * </p>
2227       *
2228       * <p>
2229       * The following convenience methods are also provided for updating the parameters:
2230       * <ul>
2231       *    <li class='jm'>{@link #formData(NameValuePair...)}
2232       *    <li class='jm'>{@link #formDataDefault(NameValuePair...)}
2233       *    <li class='jm'>{@link #formData(String,String)}
2234       *    <li class='jm'>{@link #formData(String,Supplier)}
2235       * </ul>
2236       *
2237       * @return The form data list builder.
2238       */
2239      public final PartList formData() {
2240         if (formData == null)
2241            formData = createFormData();
2242         return formData;
2243      }
2244
2245      /**
2246       * Appends multiple form-data parameters to the request bodies of all URL-encoded form posts.
2247       *
2248       * <h5 class='section'>Example:</h5>
2249       * <p class='bjava'>
2250       *    <jk>import static</jk> org.apache.juneau.http.HttpParts.*;
2251       *
2252       *    RestClient <jv>client</jv> = RestClient
2253       *       .<jsm>create</jsm>()
2254       *       .formData(
2255       *          <jsm>stringPart</jsm>(<js>"foo"</js>, <js>"bar"</js>),
2256       *          <jsm>booleanPart</jsm>(<js>"baz"</js>, <jk>true</jk>)
2257       *       )
2258       *       .build();
2259       * </p>
2260       *
2261       * <p>
2262       * This is a shortcut for calling <c>formData().append(<jv>parts</jv>)</c>.
2263       *
2264       * @param parts
2265       *    The form-data parameters.
2266       *    <br>Can contain <jk>null</jk> values (ignored).
2267       * @return This object.
2268       * @see #formData()
2269       */
2270      public Builder formData(NameValuePair...parts) {
2271         formData().append(parts);
2272         return this;
2273      }
2274
2275      /**
2276       * Appends a form-data parameter to all request bodies.
2277       *
2278       * <h5 class='section'>Example:</h5>
2279       * <p class='bjava'>
2280       *    RestClient <jv>client</jv> = RestClient
2281       *       .<jsm>create</jsm>()
2282       *       .formData(<js>"foo"</js>, <js>"bar"</js>)
2283       *       .build();
2284       * </p>
2285       *
2286       * <p>
2287       * This is a shortcut for calling <c>formData().append(<jv>name</jv>,<jv>value</jv>)</c>.
2288       *
2289       * @param name The parameter name.
2290       *    <br>Cannot be <jk>null</jk>.
2291       * @param value The parameter value.
2292       *    <br>Can be <jk>null</jk> (null value will be serialized).
2293       * @return This object.
2294       * @see #formData()
2295       */
2296      public Builder formData(String name, String value) {
2297         formData().append(name, value);
2298         return this;
2299      }
2300
2301      /**
2302       * Appends a form-data parameter with a dynamic value to all request bodies.
2303       *
2304       * <h5 class='section'>Example:</h5>
2305       * <p class='bjava'>
2306       *    RestClient <jv>client</jv> = RestClient
2307       *       .<jsm>create</jsm>()
2308       *       .formData(<js>"foo"</js>, ()-&gt;<js>"bar"</js>)
2309       *       .build();
2310       * </p>
2311       *
2312       * <p>
2313       * This is a shortcut for calling <c>formData().append(<jv>name</jv>,<jv>value</jv>)</c>.
2314       *
2315       * @param name The parameter name.
2316       *    <br>Cannot be <jk>null</jk>.
2317       * @param value The parameter value supplier.
2318       *    <br>Can be <jk>null</jk> (null value will be serialized).
2319       * @return This object.
2320       * @see #formData()
2321       */
2322      public Builder formData(String name, Supplier<String> value) {
2323         formData().append(name, value);
2324         return this;
2325      }
2326
2327      /**
2328       * Sets default form-data parameter values.
2329       *
2330       * <p>
2331       * Uses default values for specified parameters if not otherwise specified on the outgoing requests.
2332       *
2333       * <h5 class='section'>Example:</h5>
2334       * <p class='bjava'>
2335       *    RestClient <jv>client</jv> = RestClient
2336       *       .<jsm>create</jsm>()
2337       *       .formDataDefault(<jsm>stringPart</jsm>(<js>"foo"</js>, ()-&gt;<js>"bar"</js>));
2338       *       .build();
2339       * </p>
2340       *
2341       * <p>
2342       * This is a shortcut for calling <c>formData().setDefault(<jv>parts</jv>)</c>.
2343       *
2344       * @param parts The parts.
2345       *    <br>Can contain <jk>null</jk> values (ignored).
2346       * @return This object.
2347       * @see #formData()
2348       */
2349      public Builder formDataDefault(NameValuePair...parts) {
2350         formData().setDefault(parts);
2351         return this;
2352      }
2353
2354      /**
2355       * Returns the root URI defined for this client.
2356       *
2357       * <p>
2358       * Returns <jk>null</jk> in leu of an empty string.
2359       * Trailing slashes are trimmed.
2360       *
2361       * @return The root URI defined for this client.
2362       */
2363      public String getRootUri() { return rootUrl; }
2364
2365      /**
2366       * Appends a header to all requests.
2367       *
2368       * <h5 class='section'>Example:</h5>
2369       * <p class='bjava'>
2370       *    RestClient <jv>client</jv> = RestClient
2371       *       .<jsm>create</jsm>()
2372       *       .header(<js>"Foo"</js>, <js>"bar"</js>);
2373       *       .build();
2374       * </p>
2375       *
2376       * <p>
2377       * This is a shortcut for calling <c>headerData().append(<jv>name</jv>,<jv>value</jv>)</c>.
2378       *
2379       * @param name The header name.
2380       *    <br>Cannot be <jk>null</jk>.
2381       * @param value The header value.
2382       *    <br>Can be <jk>null</jk> (null value will be serialized).
2383       * @return This object.
2384       * @see #headers()
2385       */
2386      public Builder header(String name, String value) {
2387         headers().append(name, value);
2388         return this;
2389      }
2390
2391      /**
2392       * Appends a header to all requests using a dynamic value.
2393       *
2394       * <h5 class='section'>Example:</h5>
2395       * <p class='bjava'>
2396       *    RestClient <jv>client</jv> = RestClient
2397       *       .<jsm>create</jsm>()
2398       *       .header(<js>"Foo"</js>, ()-&gt;<js>"bar"</js>);
2399       *       .build();
2400       * </p>
2401       *
2402       * <p>
2403       * This is a shortcut for calling <c>headerData().append(<jv>name</jv>,<jv>value</jv>)</c>.
2404       *
2405       * @param name The header name.
2406       *    <br>Cannot be <jk>null</jk>.
2407       * @param value The header value supplier.
2408       *    <br>Can be <jk>null</jk> (null value will be serialized).
2409       * @return This object.
2410       * @see #headers()
2411       */
2412      public Builder header(String name, Supplier<String> value) {
2413         headers().append(name, value);
2414         return this;
2415      }
2416
2417      /**
2418       * Returns the builder for the list of headers that get applied to all requests created by this builder.
2419       *
2420       * <p>
2421       * This is the primary method for accessing the request header list.
2422       * On first call, the builder is created via the method {@link #createHeaderData()}.
2423       *
2424       * <h5 class='section'>Example:</h5>
2425       * <p class='bjava'>
2426       *    <jc>// Create a client that adds a "Foo: bar" header on every request.</jc>
2427       *    RestClient.Builder <jv>builder</jv> = RestClient.<jsm>create</jsm>();
2428       *    <jv>builder</jv>.headerData().setDefault(<js>"Foo"</js>, <js>"bar"</js>));
2429       *    RestClient <jv>client</jv> = <jv>builder</jv>.build();
2430       * </p>
2431       *
2432       * <p>
2433       * The following convenience methods are also provided for updating the headers:
2434       * <ul>
2435       *    <li class='jm'>{@link #headers(Header...)}
2436       *    <li class='jm'>{@link #headersDefault(Header...)}
2437       *    <li class='jm'>{@link #header(String,String)}
2438       *    <li class='jm'>{@link #header(String,Supplier)}
2439       *    <li class='jm'>{@link #mediaType(String)}
2440       *    <li class='jm'>{@link #mediaType(MediaType)}
2441       *    <li class='jm'>{@link #accept(String)}
2442       *    <li class='jm'>{@link #acceptCharset(String)}
2443       *    <li class='jm'>{@link #clientVersion(String)}
2444       *    <li class='jm'>{@link #contentType(String)}
2445       *    <li class='jm'>{@link #debug()}
2446       *    <li class='jm'>{@link #noTrace()}
2447       * </ul>
2448       *
2449       * @return The header list builder.
2450       */
2451      public final HeaderList headers() {
2452         if (headerData == null)
2453            headerData = createHeaderData();
2454         return headerData;
2455      }
2456
2457      /**
2458       * Appends multiple headers to all requests.
2459       *
2460       * <h5 class='section'>Example:</h5>
2461       * <p class='bjava'>
2462       *    <jk>import static</jk> org.apache.juneau.http.HttpHeaders.*;
2463       *
2464       *    RestClient <jv>client</jv> = RestClient
2465       *       .<jsm>create</jsm>()
2466       *       .headers(
2467       *          <jsf>ACCEPT_TEXT_XML</jsf>,
2468       *          <jsm>stringHeader</jsm>(<js>"Foo"</js>, <js>"bar"</js>)
2469       *       )
2470       *       .build();
2471       * </p>
2472       *
2473       * <p>
2474       * This is a shortcut for calling <c>headerData().append(<jv>parts</jv>)</c>.
2475       *
2476       * @param parts
2477       *    The header to set.
2478       *    <br>Can contain <jk>null</jk> values (ignored).
2479       * @return This object.
2480       * @see #headers()
2481       */
2482      public Builder headers(Header...parts) {
2483         headers().append(parts);
2484         return this;
2485      }
2486
2487      /**
2488       * Sets default header values.
2489       *
2490       * <p>
2491       * Uses default values for specified headers if not otherwise specified on the outgoing requests.
2492       *
2493       * <h5 class='section'>Example:</h5>
2494       * <p class='bjava'>
2495       *    RestClient <jv>client</jv> = RestClient
2496       *       .<jsm>create</jsm>()
2497       *       .headersDefault(<jsm>stringHeader</jsm>(<js>"Foo"</js>, ()-&gt;<js>"bar"</js>));
2498       *       .build();
2499       * </p>
2500       *
2501       * <p>
2502       * This is a shortcut for calling <c>headerData().setDefault(<jv>parts</jv>)</c>.
2503       *
2504       * @param parts The header values.
2505       *    <br>Can contain <jk>null</jk> values (ignored).
2506       * @return This object.
2507       * @see #headers()
2508       */
2509      public Builder headersDefault(Header...parts) {
2510         headers().setDefault(parts);
2511         return this;
2512      }
2513
2514      /**
2515       * Convenience method for specifying HTML as the marshalling transmission media type.
2516       *
2517       * <p>
2518       * POJOs are converted to HTML without any sort of doc wrappers.
2519       *
2520       * <p>
2521       *    {@link HtmlSerializer} will be used to serialize POJOs to request bodies unless overridden per request via {@link RestRequest#serializer(Serializer)}.
2522       *    <ul>
2523       *       <li>The serializer can be configured using any of the serializer property setters (e.g. {@link #sortCollections()}) or
2524       *          bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
2525       *    </ul>
2526       * <p>
2527       *    {@link HtmlParser} will be used to parse POJOs from response bodies unless overridden per request via {@link RestRequest#parser(Parser)}.
2528       *    <ul>
2529       *       <li>The parser can be configured using any of the parser property setters (e.g. {@link #strict()}) or
2530       *          bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
2531       *    </ul>
2532       * <p>
2533       *    <c>Accept</c> request header will be set to <js>"text/html"</js> unless overridden
2534       *       via {@link #headers()}, or per-request via {@link RestRequest#header(Header)}.
2535       * <p>
2536       *    <c>Content-Type</c> request header will be set to <js>"text/html"</js> unless overridden
2537       *       via {@link #headers()}, or per-request via {@link RestRequest#header(Header)}.
2538       * <p>
2539       *    Can be combined with other marshaller setters such as {@link #json()} to provide support for multiple languages.
2540       *    <ul>
2541       *       <li>When multiple languages are supported, the <c>Accept</c> and <c>Content-Type</c> headers control which marshallers are used, or uses the
2542       *       last-enabled language if the headers are not set.
2543       *    </ul>
2544       * <p>
2545       *    Identical to calling <c>serializer(HtmlSerializer.<jk>class</jk>).parser(HtmlParser.<jk>class</jk>)</c>.
2546       *
2547       * <h5 class='section'>Example:</h5>
2548       * <p class='bjava'>
2549       *    <jc>// Construct a client that uses HTML marshalling.</jc>
2550       *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().html().build();
2551       * </p>
2552       *
2553       * @return This object.
2554       */
2555      public Builder html() {
2556         return serializer(HtmlSerializer.class).parser(HtmlParser.class);
2557      }
2558
2559      /**
2560       * Convenience method for specifying HTML DOC as the marshalling transmission media type.
2561       *
2562       * <p>
2563       * POJOs are converted to fully renderable HTML pages.
2564       *
2565       * <p>
2566       *    {@link HtmlDocSerializer} will be used to serialize POJOs to request bodies unless overridden per request via {@link RestRequest#serializer(Serializer)}.
2567       *    <ul>
2568       *       <li>The serializer can be configured using any of the serializer property setters (e.g. {@link #sortCollections()} or
2569       *          bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
2570       *    </ul>
2571       * <p>
2572       *    {@link HtmlParser} will be used to parse POJOs from response bodies unless overridden per request via {@link RestRequest#parser(Parser)}.
2573       *    <ul>
2574       *       <li>The parser can be configured using any of the parser property setters (e.g. {@link #strict()}) or
2575       *          bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
2576       *    </ul>
2577       * <p>
2578       *    <c>Accept</c> request header will be set to <js>"text/html"</js> unless overridden
2579       *       via {@link #headers()}, or per-request via {@link RestRequest#header(Header)}.
2580       * <p>
2581       *    <c>Content-Type</c> request header will be set to <js>"text/html"</js> unless overridden
2582       *       via {@link #headers()}, or per-request via {@link RestRequest#header(Header)}.
2583       * <p>
2584       *    Can be combined with other marshaller setters such as {@link #json()} to provide support for multiple languages.
2585       *    <ul>
2586       *       <li>When multiple languages are supported, the <c>Accept</c> and <c>Content-Type</c> headers control which marshallers are used, or uses the
2587       *       last-enabled language if the headers are not set.
2588       *    </ul>
2589       * <p>
2590       *    Identical to calling <c>serializer(HtmlDocSerializer.<jk>class</jk>).parser(HtmlParser.<jk>class</jk>)</c>.
2591       *
2592       * <h5 class='section'>Example:</h5>
2593       * <p class='bjava'>
2594       *    <jc>// Construct a client that uses HTML Doc marshalling.</jc>
2595       *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().htmlDoc().build();
2596       * </p>
2597       *
2598       * @return This object.
2599       */
2600      public Builder htmlDoc() {
2601         return serializer(HtmlDocSerializer.class).parser(HtmlParser.class);
2602      }
2603
2604      /**
2605       * Convenience method for specifying Stripped HTML DOC as the marshalling transmission media type.
2606       *
2607       * <p>
2608       * Same as {@link #htmlDoc()} but without the header and body tags and page title and description.
2609       *
2610       * <p>
2611       *    {@link HtmlStrippedDocSerializer} will be used to serialize POJOs to request bodies unless overridden per request via {@link RestRequest#serializer(Serializer)}.
2612       *    <ul>
2613       *       <li>The serializer can be configured using any of the serializer property setters (e.g. {@link #sortCollections()}) or
2614       *          bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
2615       *    </ul>
2616       * <p>
2617       *    {@link HtmlParser} will be used to parse POJOs from response bodies unless overridden per request via {@link RestRequest#parser(Parser)}.
2618       *    <ul>
2619       *       <li>The parser can be configured using any of the parser property setters (e.g. {@link #strict()}) or
2620       *          bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
2621       *    </ul>
2622       * <p>
2623       *    <c>Accept</c> request header will be set to <js>"text/html+stripped"</js> unless overridden
2624       *       via {@link #headers()}, or per-request via {@link RestRequest#header(Header)}.
2625       * <p>
2626       *    <c>Content-Type</c> request header will be set to <js>"text/html+stripped"</js> unless overridden
2627       *       via {@link #headers()}, or per-request via {@link RestRequest#header(Header)}.
2628       * <p>
2629       *    Can be combined with other marshaller setters such as {@link #json()} to provide support for multiple languages.
2630       *    <ul>
2631       *       <li>When multiple languages are supported, the <c>Accept</c> and <c>Content-Type</c> headers control which marshallers are used, or uses the
2632       *       last-enabled language if the headers are not set.
2633       *    </ul>
2634       * <p>
2635       *    Identical to calling <c>serializer(HtmlStrippedDocSerializer.<jk>class</jk>).parser(HtmlParser.<jk>class</jk>)</c>.
2636       *
2637       * <h5 class='section'>Example:</h5>
2638       * <p class='bjava'>
2639       *    <jc>// Construct a client that uses HTML Stripped Doc marshalling.</jc>
2640       *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().htmlStrippedDoc().build();
2641       * </p>
2642       *
2643       * @return This object.
2644       */
2645      public Builder htmlStrippedDoc() {
2646         return serializer(HtmlStrippedDocSerializer.class).parser(HtmlParser.class);
2647      }
2648
2649      /**
2650       * Sets the {@link HttpClient} to be used to handle all HTTP communications with the target server.
2651       *
2652       * <p>
2653       * This can be used to bypass the client created by {@link #createHttpClient()} method.
2654       *
2655       * <h5 class='section'>Example:</h5>
2656       * <p class='bjava'>
2657       *    <jc>// Construct a client that uses a customized HttpClient.</jc>
2658       *    RestClient <jv>client</jv> = RestClient
2659       *       .<jsm>create</jsm>()
2660       *       .httpClient(HttpClientBuilder.<jsm>create</jsm>().build())
2661       *       .build();
2662       * </p>
2663       *
2664       * @param value The {@link HttpClient} to be used to handle all HTTP communications with the target server.
2665       *    <br>Can be <jk>null</jk> (a default client will be created).
2666       * @return This object.
2667       */
2668      public Builder httpClient(CloseableHttpClient value) {
2669         httpClient = value;
2670         return this;
2671      }
2672
2673      /**
2674       * Returns the HTTP client builder.
2675       *
2676       * @return The HTTP client builder.
2677       */
2678      public final HttpClientBuilder httpClientBuilder() {
2679         if (httpClientBuilder == null)
2680            httpClientBuilder = createHttpClientBuilder();
2681         return httpClientBuilder;
2682      }
2683
2684      /**
2685       * Sets the {@link HttpClientBuilder} that will be used to create the {@link HttpClient} used by {@link RestClient}.
2686       *
2687       * <p>
2688       * This can be used to bypass the builder created by {@link #createHttpClientBuilder()} method.
2689       *
2690       * <h5 class='section'>Example:</h5>
2691       * <p class='bjava'>
2692       *    <jc>// Construct a client that uses a customized HttpClientBuilder.</jc>
2693       *    RestClient <jv>client</jv> = RestClient
2694       *       .<jsm>create</jsm>()
2695       *       .httpClientBuilder(HttpClientBuilder.<jsm>create</jsm>())
2696       *       .build();
2697       * </p>
2698       *
2699       * @param value The {@link HttpClientBuilder} that will be used to create the {@link HttpClient} used by {@link RestClient}.
2700       *    <br>Can be <jk>null</jk> (a default builder will be created).
2701       * @return This object.
2702       */
2703      public Builder httpClientBuilder(HttpClientBuilder value) {
2704         httpClientBuilder = value;
2705         return this;
2706      }
2707
2708      /**
2709       * Assigns {@link HttpProcessor} instance.
2710       *
2711       * @param httpprocessor New property value.
2712       * @return This object.
2713       * @see HttpClientBuilder#setHttpProcessor(HttpProcessor)
2714       */
2715      public Builder httpProcessor(HttpProcessor httpprocessor) {
2716         httpClientBuilder().setHttpProcessor(httpprocessor);
2717         return this;
2718      }
2719
2720      /**
2721       * Ignore errors.
2722       *
2723       * <p>
2724       * When enabled, HTTP error response codes (e.g. <l>&gt;=400</l>) will not cause a {@link RestCallException} to
2725       * be thrown.
2726       * <p>
2727       * Note that this is equivalent to <c>builder.errorCodes(x -&gt; <jk>false</jk>);</c>
2728       *
2729       * <h5 class='section'>Example:</h5>
2730       * <p class='bjava'>
2731       *    <jc>// Create a client that doesn't throws a RestCallException when a 500 error occurs.</jc>
2732       *    RestClient
2733       *       .<jsm>create</jsm>()
2734       *       .ignoreErrors()
2735       *       .build()
2736       *       .get(<js>"/error"</js>)  <jc>// Throws a 500 error</jc>
2737       *       .run()
2738       *       .assertStatus().is(500);
2739       * </p>
2740       *
2741       * @return This object.
2742       */
2743      public Builder ignoreErrors() {
2744         ignoreErrors = true;
2745         return this;
2746      }
2747
2748      @Override /* Overridden from Builder */
2749      public Builder ignoreInvocationExceptionsOnGetters() {
2750         super.ignoreInvocationExceptionsOnGetters();
2751         return this;
2752      }
2753
2754      @Override /* Overridden from Builder */
2755      public Builder ignoreInvocationExceptionsOnSetters() {
2756         super.ignoreInvocationExceptionsOnSetters();
2757         return this;
2758      }
2759
2760      /**
2761       * <i><l>BeanTraverse</l> configuration property:&emsp;</i>  Ignore recursion errors.
2762       *
2763       * <p>
2764       * When enabled, when we encounter the same object when traversing a tree, we set the value to <jk>null</jk>.
2765       *
2766       * <p>
2767       * For example, if a model contains the links A-&gt;B-&gt;C-&gt;A, then the JSON generated will look like
2768       *    the following when <jsf>BEANTRAVERSE_ignoreRecursions</jsf> is <jk>true</jk>...
2769       *
2770       * <p class='bjson'>
2771       *    {A:{B:{C:<jk>null</jk>}}}
2772       * </p>
2773       *
2774       * <h5 class='section'>Notes:</h5><ul>
2775       *    <li class='note'>
2776       *       Checking for recursion can cause a small performance penalty.
2777       * </ul>
2778       *
2779       * <h5 class='section'>Example:</h5>
2780       * <p class='bjava'>
2781       *    <jc>// Create a JSON client that ignores recursions.</jc>
2782       *    RestClient <jv>client</jv> = RestClient
2783       *       .<jsm>create</jsm>()
2784       *       .json()
2785       *       .ignoreRecursions()
2786       *       .build();
2787       *
2788       *    <jc>// Create a POJO model with a recursive loop.</jc>
2789       *    <jk>public class</jk> A {
2790       *       <jk>public</jk> Object <jf>f</jf>;
2791       *    }
2792       *    A <jv>a</jv> = <jk>new</jk> A();
2793       *    <jv>a</jv>.<jf>f</jf> = <jv>a</jv>;
2794       *
2795       *    <jc>// Produces request body "{f:null}"</jc>
2796       *    <jv>client</jv>
2797       *       .post(<js>"http://localhost:10000/foo"</js>, <jv>a</jv>)
2798       *       .run();
2799       * </p>
2800       *
2801       * <h5 class='section'>See Also:</h5><ul>
2802       *    <li class='jm'>{@link org.apache.juneau.BeanTraverseContext.Builder#ignoreRecursions()}
2803       * </ul>
2804       *
2805       * @return This object.
2806       */
2807      public Builder ignoreRecursions() {
2808         serializers().forEach(org.apache.juneau.serializer.Serializer.Builder::ignoreRecursions);
2809         return this;
2810      }
2811
2812      @Override /* Overridden from Builder */
2813      public Builder ignoreUnknownBeanProperties() {
2814         super.ignoreUnknownBeanProperties();
2815         return this;
2816      }
2817
2818      @Override /* Overridden from Builder */
2819      public Builder ignoreUnknownEnumValues() {
2820         super.ignoreUnknownEnumValues();
2821         return this;
2822      }
2823
2824      @Override /* Overridden from Builder */
2825      public Builder impl(Context value) {
2826         super.impl(value);
2827         return this;
2828      }
2829
2830      @Override /* Overridden from Builder */
2831      public Builder implClass(Class<?> interfaceClass, Class<?> implClass) {
2832         super.implClass(interfaceClass, implClass);
2833         return this;
2834      }
2835
2836      @Override /* Overridden from Builder */
2837      public Builder implClasses(Map<Class<?>,Class<?>> values) {
2838         super.implClasses(values);
2839         return this;
2840      }
2841
2842      /**
2843       * <i><l>BeanTraverse</l> configuration property:&emsp;</i>  Initial depth.
2844       *
2845       * <p>
2846       * The initial indentation level at the root.
2847       *
2848       * <p>
2849       * Useful when constructing document fragments that need to be indented at a certain level when whitespace is enabled.
2850       *
2851       * <h5 class='section'>Example:</h5>
2852       * <p class='bjava'>
2853       *    <jc>// Create a REST client with JSON serializer with whitespace enabled and an initial depth of 2.</jc>
2854       *    RestClient <jv>client</jv> = RestClient
2855       *       .<jsm>create</jsm>()
2856       *       .json()
2857       *       .ws()
2858       *       .initialDepth(2)
2859       *       .build();
2860       *
2861       *    <jc>// Our bean to serialize.</jc>
2862       *    <jk>public class</jk> MyBean {
2863       *       <jk>public</jk> String <jf>foo</jf> = <jk>null</jk>;
2864       *    }
2865       *
2866       *    <jc>// Produces request body "\t\t{\n\t\t\t'foo':'bar'\n\t\t}\n"</jc>
2867       *    <jv>client</jv>
2868       *       .post(<js>"http://localhost:10000/foo"</js>, <jk>new</jk> MyBean())
2869       *       .run();
2870       * </p>
2871       *
2872       * <h5 class='section'>See Also:</h5><ul>
2873       *    <li class='jm'>{@link org.apache.juneau.BeanTraverseContext.Builder#initialDepth(int)}
2874       * </ul>
2875       *
2876       * @param value
2877       *    The new value for this property.
2878       *    <br>The default is <c>0</c>.
2879       * @return This object.
2880       */
2881      public Builder initialDepth(int value) {
2882         serializers().forEach(x -> x.initialDepth(value));
2883         return this;
2884      }
2885
2886      /**
2887       * <i><l>RestClient</l> configuration property:&emsp;</i>  Call interceptors.
2888       *
2889       * <p>
2890       * Adds an interceptor that can be called to hook into specified events in the lifecycle of a single request.
2891       *
2892       * <h5 class='section'>Example:</h5>
2893       * <p class='bjava'>
2894       *   <jc>// Customized interceptor (note you can also extend from BasicRestCallInterceptor as well.</jc>
2895       *    <jk>public class</jk> MyRestCallInterceptor <jk>implements</jk> RestCallInterceptor {
2896       *
2897       *       <ja>@Override</ja>
2898       *       <jk>public void</jk> onInit(RestRequest <jv>req</jv>) <jk>throws</jk> Exception {
2899       *       <jc>// Intercept immediately after RestRequest object is created and all headers/query/form-data has been
2900       *       // set on the request from the client.</jc>
2901       *    }
2902       *
2903       *    <ja>@Override</ja>
2904       *    <jk>public void</jk> onConnect(RestRequest <jv>req</jv>, RestResponse <jv>res</jv>) <jk>throws</jk> Exception {
2905       *       <jc>// Intercept immediately after an HTTP response has been received.</jc>
2906       *    }
2907       *
2908       *    <ja>@Override</ja>
2909       *    <jk>public void</jk> onClose(RestRequest <jv>req</jv>, RestResponse <jv>res</jv>) <jk>throws</jk> Exception {
2910       *          <jc>// Intercept when the response body is consumed.</jc>
2911       *       }
2912       *    }
2913       *
2914       *    <jc>// Create a client with a customized interceptor.</jc>
2915       *    RestClient <jv>client</jv> = RestClient
2916       *       .<jsm>create</jsm>()
2917       *       .interceptors(MyRestCallInterceptor.<jk>class</jk>)
2918       *       .build();
2919       * </p>
2920       *
2921       * <h5 class='section'>Notes:</h5><ul>
2922       *    <li class='note'>The {@link RestClient#onCallInit(RestRequest)}, {@link RestClient#onCallConnect(RestRequest,RestResponse)}, and
2923       * {@link RestClient#onCallClose(RestRequest,RestResponse)} methods can also be overridden to produce the same results.
2924       * </ul>
2925       *
2926       * @param values
2927       *    The values to add to this setting.
2928       *    <br>Can be implementations of any of the following:
2929       *    <ul>
2930       *       <li class='jic'>{@link RestCallInterceptor}
2931       *       <li class='jic'>{@link HttpRequestInterceptor}
2932       *       <li class='jic'>{@link HttpResponseInterceptor}
2933       *    </ul>
2934       *    <br>Can contain <jk>null</jk> values (ignored).
2935       * @return This object.
2936       * @throws Exception If one or more interceptors could not be created.
2937       */
2938      public Builder interceptors(Class<?>...values) throws Exception {
2939         for (var c : values) {
2940            if (c == null)
2941               continue;
2942            var ci = ClassInfo.of(c);
2943            if (nn(ci)) {
2944               if (ci.isChildOfAny(RestCallInterceptor.class, HttpRequestInterceptor.class, HttpResponseInterceptor.class))
2945                  interceptors(ci.newInstance());
2946               else
2947                  throw new ConfigException("Invalid class of type ''{0}'' passed to interceptors().", ci.getName());
2948            }
2949         }
2950         return this;
2951      }
2952
2953      /**
2954       * Call interceptors.
2955       *
2956       * <p>
2957       * Adds an interceptor that gets called immediately after a connection is made.
2958       *
2959       * <h5 class='section'>Example:</h5>
2960       * <p class='bjava'>
2961       *    <jc>// Create a client with a customized interceptor.</jc>
2962       *    RestClient <jv>client</jv> = RestClient
2963       *       .<jsm>create</jsm>()
2964       *       .interceptors(
2965       *          <jk>new</jk> RestCallInterceptor() {
2966       *
2967       *             <ja>@Override</ja>
2968       *             <jk>public void</jk> onInit(RestRequest <jv>req</jv>) <jk>throws</jk> Exception {
2969       *             <jc>// Intercept immediately after RestRequest object is created and all headers/query/form-data has been
2970       *             // set on the request from the client.</jc>
2971       *          }
2972       *
2973       *          <ja>@Override</ja>
2974       *          <jk>public void</jk> onConnect(RestRequest <jv>req</jv>, RestResponse <jv>res</jv>) <jk>throws</jk> Exception {
2975       *             <jc>// Intercept immediately after an HTTP response has been received.</jc>
2976       *          }
2977       *
2978       *          <ja>@Override</ja>
2979       *          <jk>public void</jk> onClose(RestRequest <jv>req</jv>, RestResponse <jv>res</jv>) <jk>throws</jk> Exception {
2980       *                <jc>// Intercept when the response body is consumed.</jc>
2981       *             }
2982       *          }
2983       *       )
2984       *       .build();
2985       * </p>
2986       *
2987       * <h5 class='section'>Notes:</h5><ul>
2988       *    <li class='note'>The {@link RestClient#onCallInit(RestRequest)}, {@link RestClient#onCallConnect(RestRequest,RestResponse)}, and
2989       * {@link RestClient#onCallClose(RestRequest,RestResponse)} methods can also be overridden to produce the same results.
2990       * </ul>
2991       *
2992       * @param value
2993       *    The values to add to this setting.
2994       *    <br>Can be implementations of any of the following:
2995       *    <ul>
2996       *       <li class='jic'>{@link RestCallInterceptor}
2997       *       <li class='jic'>{@link HttpRequestInterceptor}
2998       *       <li class='jic'>{@link HttpResponseInterceptor}
2999       *    </ul>
3000       *    <br>Can contain <jk>null</jk> values (ignored).
3001       * @return This object.
3002       */
3003      public Builder interceptors(Object...value) {
3004         List<RestCallInterceptor> l = list();
3005         for (var o : value) {
3006            if (o == null)
3007               continue;
3008            ClassInfo ci = ClassInfo.of(o);
3009            if (nn(ci)) {
3010               if (! ci.isChildOfAny(HttpRequestInterceptor.class, HttpResponseInterceptor.class, RestCallInterceptor.class))
3011                  throw new ConfigException("Invalid object of type ''{0}'' passed to interceptors().", ci.getName());
3012               if (o instanceof HttpRequestInterceptor o2)
3013                  addInterceptorLast(o2);
3014               if (o instanceof HttpResponseInterceptor o3)
3015                  addInterceptorLast(o3);
3016               if (o instanceof RestCallInterceptor o4)
3017                  l.add(o4);
3018            }
3019         }
3020         if (interceptors == null)
3021            interceptors = l;
3022         else
3023            interceptors.addAll(0, l);
3024         return this;
3025      }
3026
3027      @Override /* Overridden from Builder */
3028      public Builder interfaceClass(Class<?> on, Class<?> value) {
3029         super.interfaceClass(on, value);
3030         return this;
3031      }
3032
3033      @Override /* Overridden from Builder */
3034      public Builder interfaces(java.lang.Class<?>...value) {
3035         super.interfaces(value);
3036         return this;
3037      }
3038
3039      /**
3040       * Convenience method for specifying JSON as the marshalling transmission media type.
3041       *
3042       * <p>
3043       * {@link JsonSerializer} will be used to serialize POJOs to request bodies unless overridden per request via {@link RestRequest#serializer(Serializer)}.
3044       *    <ul>
3045       *       <li>The serializer can be configured using any of the serializer property setters (e.g. {@link #sortCollections()}) or
3046       *          bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
3047       *    </ul>
3048       * <p>
3049       *    {@link JsonParser} will be used to parse POJOs from response bodies unless overridden per request via {@link RestRequest#parser(Parser)}.
3050       *    <ul>
3051       *       <li>The parser can be configured using any of the parser property setters (e.g. {@link #strict()}) or
3052       *          bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
3053       *    </ul>
3054       * <p>
3055       *    <c>Accept</c> request header will be set to <js>"application/json"</js> unless overridden
3056       *       via {@link #headers()}, or per-request via {@link RestRequest#header(Header)}}.
3057       * <p>
3058       *    <c>Content-Type</c> request header will be set to <js>"application/json"</js> unless overridden
3059       *       via {@link #headers()}, or per-request via {@link RestRequest#header(Header)}.
3060       * <p>
3061       *    Can be combined with other marshaller setters such as {@link #xml()} to provide support for multiple languages.
3062       *    <ul>
3063       *       <li>When multiple languages are supported, the <c>Accept</c> and <c>Content-Type</c> headers control which marshallers are used, or uses the
3064       *       last-enabled language if the headers are not set.
3065       *    </ul>
3066       * <p>
3067       *    Identical to calling <c>serializer(JsonSerializer.<jk>class</jk>).parser(JsonParser.<jk>class</jk>)</c>.
3068       *
3069       * <h5 class='section'>Example:</h5>
3070       * <p class='bjava'>
3071       *    <jc>// Construct a client that uses JSON marshalling.</jc>
3072       *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().json().build();
3073       * </p>
3074       *
3075       * @return This object.
3076       */
3077      public Builder json() {
3078         return serializer(JsonSerializer.class).parser(JsonParser.class);
3079      }
3080
3081      /**
3082       * Convenience method for specifying Simplified JSON as the marshalling transmission media type.
3083       *
3084       * <p>
3085       * Simplified JSON is typically useful for automated tests because you can do simple string comparison of results
3086       * without having to escape lots of quotes.
3087       *
3088       * <p>
3089       *    {@link Json5Serializer} will be used to serialize POJOs to request bodies unless overridden per request via {@link RestRequest#serializer(Serializer)}.
3090       *    <ul>
3091       *       <li>The serializer can be configured using any of the serializer property setters (e.g. {@link #sortCollections()}) or
3092       *          bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
3093       *    </ul>
3094       * <p>
3095       *    {@link Json5Parser} will be used to parse POJOs from response bodies unless overridden per request via {@link RestRequest#parser(Parser)}.
3096       *    <ul>
3097       *       <li>The parser can be configured using any of the parser property setters (e.g. {@link #strict()}) or
3098       *          bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
3099       *    </ul>
3100       * <p>
3101       *    <c>Accept</c> request header will be set to <js>"application/json"</js> unless overridden
3102       *       via {@link #headers()}, or per-request via {@link RestRequest#header(Header)}.
3103       * <p>
3104       *    <c>Content-Type</c> request header will be set to <js>"application/json5"</js> unless overridden
3105       *       via {@link #headers()}, or per-request via {@link RestRequest#header(Header)}.
3106       * <p>
3107       *    Can be combined with other marshaller setters such as {@link #xml()} to provide support for multiple languages.
3108       *    <ul>
3109       *       <li>When multiple languages are supported, the <c>Accept</c> and <c>Content-Type</c> headers control which marshallers are used, or uses the
3110       *       last-enabled language if the headers are not set.
3111       *    </ul>
3112       * <p>
3113       *    Identical to calling <c>serializer(Json5Serializer.<jk>class</jk>).parser(Json5Parser.<jk>class</jk>)</c>.
3114       *
3115       * <h5 class='section'>Example:</h5>
3116       * <p class='bjava'>
3117       *    <jc>// Construct a client that uses Simplified JSON marshalling.</jc>
3118       *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().json5().build();
3119       * </p>
3120       *
3121       * @return This object.
3122       */
3123      public Builder json5() {
3124         return serializer(Json5Serializer.class).parser(Json5Parser.class);
3125      }
3126
3127      /**
3128       * Assigns {@link ConnectionKeepAliveStrategy} instance.
3129       *
3130       * @param keepAliveStrategy New property value.
3131       *    <br>Can be <jk>null</jk> (value will not be set, default behavior will be used).
3132       * @return This object.
3133       * @see HttpClientBuilder#setKeepAliveStrategy(ConnectionKeepAliveStrategy)
3134       */
3135      public Builder keepAliveStrategy(ConnectionKeepAliveStrategy keepAliveStrategy) {
3136         httpClientBuilder().setKeepAliveStrategy(keepAliveStrategy);
3137         return this;
3138      }
3139
3140      /**
3141       * <i><l>RestClient</l> configuration property:&emsp;</i>  Keep HttpClient open.
3142       *
3143       * <p>
3144       * Don't close this client when the {@link RestClient#close()} method is called.
3145       *
3146       * <h5 class='section'>Example:</h5>
3147       * <p class='bjava'>
3148       *    <jc>// Create a client with a customized client and don't close the client  service.</jc>
3149       *    RestClient <jv>client</jv> = RestClient
3150       *       .<jsm>create</jsm>()
3151       *       .httpClient(<jv>myHttpClient</jv>)
3152       *       .keepHttpClientOpen()
3153       *       .build();
3154       *
3155       *    <jv>client</jv>.closeQuietly();  <jc>// Customized HttpClient won't be closed.</jc>
3156       * </p>
3157       *
3158       * @return This object.
3159       */
3160      public Builder keepHttpClientOpen() {
3161         keepHttpClientOpen = true;
3162         return this;
3163      }
3164
3165      /**
3166       * <i><l>Serializer</l> configuration property:&emsp;</i>  Don't trim null bean property values.
3167       *
3168       * <p>
3169       * When enabled, null bean values will be serialized to the output.
3170       *
3171       * <h5 class='section'>Notes:</h5><ul>
3172       *    <li class='note'>Not enabling this setting will cause <c>Map</c>s with <jk>null</jk> values to be lost during parsing.
3173       * </ul>
3174       *
3175       * <h5 class='section'>Example:</h5>
3176       * <p class='bjava'>
3177       *    <jc>// Create a REST client with JSON serializer that serializes null properties.</jc>
3178       *    RestClient <jv>client</jv> = RestClient
3179       *       .<jsm>create</jsm>()
3180       *       .json()
3181       *       .keepNullProperties()
3182       *       .build();
3183       *
3184       *    <jc>// Our bean to serialize.</jc>
3185       *    <jk>public class</jk> MyBean {
3186       *       <jk>public</jk> String <jf>foo</jf> = <jk>null</jk>;
3187       *    }
3188       *
3189       *    <jc>// Request body will contain:  {foo:null}</jc>
3190       *    <jv>client</jv>
3191       *       .post(<js>"http://localhost:10000/foo"</js>, <jk>new</jk> MyBean())
3192       *       .run();
3193       * </p>
3194       *
3195       * <h5 class='section'>See Also:</h5><ul>
3196       *    <li class='jm'>{@link org.apache.juneau.serializer.Serializer.Builder#keepNullProperties()}
3197       * </ul>
3198       *
3199       * @return This object.
3200       */
3201      public Builder keepNullProperties() {
3202         serializers().forEach(org.apache.juneau.serializer.Serializer.Builder::keepNullProperties);
3203         return this;
3204      }
3205
3206      @Override /* Overridden from Builder */
3207      public Builder locale(Locale value) {
3208         super.locale(value);
3209         return this;
3210      }
3211
3212      /**
3213       * Logger.
3214       *
3215       * <p>
3216       * Specifies the logger to use for logging.
3217       *
3218       * <p>
3219       * If not specified, uses the following logger:
3220       * <p class='bjava'>
3221       *    Logger.<jsm>getLogger</jsm>(RestClient.<jk>class</jk>.getName());
3222       * </p>
3223       *
3224       * <h5 class='section'>Example:</h5>
3225       * <p class='bjava'>
3226       *    <jc>// Construct a client that logs messages to a special logger.</jc>
3227       *    RestClient <jv>client</jv> = RestClient
3228       *       .<jsm>create</jsm>()
3229       *       .logger(Logger.<jsm>getLogger</jsm>(<js>"MyLogger"</js>))  <jc>// Log to MyLogger logger.</jc>
3230       *       .logToConsole()  <jc>// Also log to console.</jc>
3231       *       .logRequests(<jsf>FULL</jsf>, <jsf>WARNING</jsf>)  <jc>// Log requests with full detail at WARNING level.</jc>
3232       *       .build();
3233       * </p>
3234       *
3235       * @param value The logger to use for logging.
3236       *    <br>Can be <jk>null</jk> (defaults to <c>Logger.getLogger(RestClient.class.getName())</c>).
3237       * @return This object.
3238       */
3239      public Builder logger(Logger value) {
3240         logger = value;
3241         return this;
3242      }
3243
3244      /**
3245       * Log requests.
3246       *
3247       * <p>
3248       * Causes requests/responses to be logged at the specified log level at the end of the request.
3249       *
3250       * <p>
3251       * <jsf>SIMPLE</jsf> detail produces a log message like the following:
3252       * <p class='bconsole'>
3253       *    POST http://localhost:10000/testUrl, HTTP/1.1 200 OK
3254       * </p>
3255       *
3256       * <p>
3257       * <jsf>FULL</jsf> detail produces a log message like the following:
3258       * <p class='bconsole'>
3259       *    === HTTP Call (outgoing) =======================================================
3260       *    === REQUEST ===
3261       *    POST http://localhost:10000/testUrl
3262       *    ---request headers---
3263       *       Debug: true
3264       *       No-Trace: true
3265       *       Accept: application/json
3266       *    ---request entity---
3267       *       Content-Type: application/json
3268       *    ---request content---
3269       *    {"foo":"bar","baz":123}
3270       *    === RESPONSE ===
3271       *    HTTP/1.1 200 OK
3272       *    ---response headers---
3273       *       Content-Type: application/json;charset=utf-8
3274       *       Content-Length: 21
3275       *       Server: Jetty(8.1.0.v20120127)
3276       *    ---response content---
3277       *    {"message":"OK then"}
3278       *    === END ========================================================================
3279       * </p>
3280       *
3281       * <p>
3282       * By default, the message is logged to the default logger.  It can be logged to a different logger via the
3283       * {@link #logger(Logger)} method or logged to the console using the
3284       * {@link #logToConsole()} method.
3285       *
3286       * @param detail The detail level of logging.
3287       * @param level The log level.
3288       * @param test A predicate to use per-request to see if the request should be logged.  If <jk>null</jk>, always logs.
3289       * @return This object.
3290       */
3291      public Builder logRequests(DetailLevel detail, Level level, BiPredicate<RestRequest,RestResponse> test) {
3292         logRequests = detail;
3293         logRequestsLevel = level;
3294         logRequestsPredicate = test;
3295         return this;
3296      }
3297
3298      /**
3299       * Log to console.
3300       *
3301       * <p>
3302       * Specifies to log messages to the console.
3303       *
3304       * <h5 class='section'>Example:</h5>
3305       * <p class='bjava'>
3306       *    <jc>// Construct a client that logs messages to a special logger.</jc>
3307       *    RestClient <jv>client</jv> = RestClient
3308       *       .<jsm>create</jsm>()
3309       *       .logToConsole()
3310       *       .logRequests(<jsf>FULL</jsf>, <jsf>INFO</jsf>)  <jc>// Level is ignored when logging to console.</jc>
3311       *       .build();
3312       * </p>
3313       *
3314       * @return This object.
3315       */
3316      public Builder logToConsole() {
3317         logToConsole = true;
3318         return this;
3319      }
3320
3321      /**
3322       * <i><l>RestClient</l> configuration property:&emsp;</i>  Marshaller
3323       *
3324       * <p>
3325       * Shortcut for specifying the serializers and parsers
3326       * using the serializer and parser defined in a marshaller.
3327       *
3328       * <h5 class='section'>Notes:</h5><ul>
3329       *    <li class='note'>When using this method that takes in a pre-instantiated serializers and parsers, the serializer property setters (e.g. {@link #sortCollections()}),
3330       *    parser property setters (e.g. {@link #strict()}), or bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class have no effect.
3331       * </ul>
3332       *
3333       * <h5 class='section'>Example:</h5>
3334       * <p class='bjava'>
3335       *    <jc>// Create a client that uses Simplified-JSON transport using an existing marshaller.</jc>
3336       *    RestClient <jv>client</jv> = RestClient
3337       *       .<jsm>create</jsm>()
3338       *       .marshaller(Json5.<jsf>DEFAULT_READABLE</jsf>)
3339       *       .build();
3340       * </p>
3341       *
3342       * @param value The values to add to this setting.
3343       *    <br>Can be <jk>null</jk> (value will not be set, existing serializers and parsers will be kept).
3344       * @return This object.
3345       */
3346      public Builder marshaller(Marshaller value) {
3347         if (nn(value))
3348            serializer(value.getSerializer()).parser(value.getParser());
3349         return this;
3350      }
3351
3352      /**
3353       * <i><l>RestClient</l> configuration property:&emsp;</i>  Marshalls
3354       *
3355       * <p>
3356       * Shortcut for specifying the serializers and parsers
3357       * using the serializer and parser defined in a marshaller.
3358       *
3359       * <h5 class='section'>Notes:</h5><ul>
3360       *    <li class='note'>When using this method that takes in a pre-instantiated serializers and parsers, the serializer property setters (e.g. {@link #sortCollections()}),
3361       *    parser property setters (e.g. {@link #strict()}), or bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class have no effect.
3362       * </ul>
3363       *
3364       * <h5 class='section'>Example:</h5>
3365       * <p class='bjava'>
3366       *    <jc>// Create a client that uses JSON and XML transport using existing marshalls.</jc>
3367       *    RestClient <jv>client</jv> = RestClient
3368       *       .<jsm>create</jsm>()
3369       *       .marshaller(Json.<jsf>DEFAULT_READABLE</jsf>, Xml.<jsf>DEFAULT_READABLE</jsf>)
3370       *       .build();
3371       * </p>
3372       *
3373       * @param value The values to add to this setting.
3374       *    <br>Can contain <jk>null</jk> values (ignored).
3375       * @return This object.
3376       */
3377      public Builder marshallers(Marshaller...value) {
3378         for (var m : value)
3379            if (nn(m))
3380               serializer(m.getSerializer()).parser(m.getParser());
3381         return this;
3382      }
3383
3384      /**
3385       * Assigns maximum connection per route value.
3386       *
3387       * <h5 class='section'>Notes:</h5><ul>
3388       *    <li class='note'>This value can be overridden by the {@link #connectionManager(HttpClientConnectionManager)} method.
3389       * </ul>
3390       *
3391       * @param maxConnPerRoute New property value.
3392       * @return This object.
3393       * @see HttpClientBuilder#setMaxConnPerRoute(int)
3394       */
3395      public Builder maxConnPerRoute(int maxConnPerRoute) {
3396         httpClientBuilder().setMaxConnPerRoute(maxConnPerRoute);
3397         return this;
3398      }
3399
3400      /**
3401       * Assigns maximum total connection value.
3402       *
3403       * <h5 class='section'>Notes:</h5><ul>
3404       *    <li class='note'>This value can be overridden by the {@link #connectionManager(HttpClientConnectionManager)} method.
3405       * </ul>
3406       *
3407       * @param maxConnTotal New property value.
3408       * @return This object.
3409       * @see HttpClientBuilder#setMaxConnTotal(int)
3410       */
3411      public Builder maxConnTotal(int maxConnTotal) {
3412         httpClientBuilder().setMaxConnTotal(maxConnTotal);
3413         return this;
3414      }
3415
3416      /**
3417       * <i><l>BeanTraverse</l> configuration property:&emsp;</i>  Max serialization depth.
3418       *
3419       * <p>
3420       * When enabled, abort traversal if specified depth is reached in the POJO tree.
3421       *
3422       * <p>
3423       * If this depth is exceeded, an exception is thrown.
3424       *
3425       * <p>
3426       * This prevents stack overflows from occurring when trying to traverse models with recursive references.
3427       *
3428       * <h5 class='section'>Example:</h5>
3429       * <p class='bjava'>
3430       *    <jc>// Create a REST client with JSON serializer that throws an exception if the depth reaches greater than 20.</jc>
3431       *    RestClient <jv>client</jv> = RestClient
3432       *       .<jsm>create</jsm>()
3433       *       .json()
3434       *       .maxDepth(20)
3435       *       .build();
3436       * </p>
3437       *
3438       * <h5 class='section'>See Also:</h5><ul>
3439       *    <li class='jm'>{@link org.apache.juneau.BeanTraverseContext.Builder#maxDepth(int)}
3440       * </ul>
3441       *
3442       * @param value
3443       *    The new value for this property.
3444       *    <br>The default is <c>100</c>.
3445       * @return This object.
3446       */
3447      public Builder maxDepth(int value) {
3448         serializers().forEach(x -> x.maxDepth(value));
3449         return this;
3450      }
3451
3452      /**
3453       * <i><l>WriterSerializer</l> configuration property:&emsp;</i>  Maximum indentation.
3454       *
3455       * <p>
3456       * Specifies the maximum indentation level in the serialized document.
3457       *
3458       * <h5 class='section'>Notes:</h5><ul>
3459       *    <li class='note'>This setting does not apply to the RDF serializers.
3460       * </ul>
3461       *
3462       * <h5 class='section'>Example:</h5>
3463       * <p class='bjava'>
3464       *    <jc>// Create a REST client with JSON serializer that indents a maximum of 20 tabs.</jc>
3465       *    RestClient <jv>client</jv> = RestClient
3466       *       .<jsm>create</jsm>()
3467       *       .json()
3468       *       .ws()  <jc>// Enable whitespace</jc>
3469       *       .maxIndent(20)
3470       *       .build();
3471       * </p>
3472       *
3473       * <h5 class='section'>See Also:</h5><ul>
3474       *    <li class='jm'>{@link org.apache.juneau.serializer.WriterSerializer.Builder#maxIndent(int)}
3475       * </ul>
3476       *
3477       * @param value
3478       *    The new value for this property.
3479       *    <br>The default is <c>100</c>.
3480       * @return This object.
3481       */
3482      public Builder maxIndent(int value) {
3483         serializers().forEachWS(x -> x.maxIndent(value));
3484         return this;
3485      }
3486
3487      /**
3488       * Appends the <c>Accept</c> and <c>Content-Type</c> headers on all requests made by this client.
3489       *
3490       * <p>
3491       * Headers are appended to the end of the current header list.
3492       *
3493       * <p>
3494       * This is a shortcut for calling <c>headerData().append(Accept.<jsm>of</jsm>(<jv>value</jv>), ContentType.<jsm>of</jsm>(<jv>value</jv>))</c>.
3495       *
3496       * @param value The new header values.
3497       *    <br>Can be <jk>null</jk> (no Accept or Content-Type headers will be added).
3498       * @return This object.
3499       * @see #headers()
3500       */
3501      @Override
3502      public Builder mediaType(MediaType value) {
3503         super.mediaType(value);
3504         return headers(Accept.of(value), ContentType.of(value));
3505      }
3506
3507      /**
3508       * Appends the <c>Accept</c> and <c>Content-Type</c> headers on all requests made by this client.
3509       *
3510       * <p>
3511       * Headers are appended to the end of the current header list.
3512       *
3513       * <p>
3514       * This is a shortcut for calling <c>headerData().append(Accept.<jsm>of</jsm>(<jv>value</jv>), ContentType.<jsm>of</jsm>(<jv>value</jv>))</c>.
3515       *
3516       * @param value The new header values.
3517       *    <br>Can be <jk>null</jk> (no Accept or Content-Type headers will be added).
3518       * @return This object.
3519       * @see #headers()
3520       */
3521      public Builder mediaType(String value) {
3522         super.mediaType(MediaType.of(value));
3523         return headers(Accept.of(value), ContentType.of(value));
3524      }
3525
3526      /**
3527       * Convenience method for specifying MessagePack as the marshalling transmission media type.
3528       *
3529       * <p>
3530       * MessagePack is a binary equivalent to JSON that takes up considerably less space than JSON.
3531       *
3532       * <p>
3533       *    {@link MsgPackSerializer} will be used to serialize POJOs to request bodies unless overridden per request via {@link RestRequest#serializer(Serializer)}.
3534       *    <ul>
3535       *       <li>The serializer can be configured using any of the serializer property setters (e.g. {@link #sortCollections()}) or
3536       *          bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
3537       *    </ul>
3538       * <p>
3539       *    {@link MsgPackParser} will be used to parse POJOs from response bodies unless overridden per request via {@link RestRequest#parser(Parser)}.
3540       *    <ul>
3541       *       <li>The parser can be configured using any of the parser property setters (e.g. {@link #strict()}) or
3542       *          bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
3543       *    </ul>
3544       * <p>
3545       *    <c>Accept</c> request header will be set to <js>"octal/msgpack"</js> unless overridden
3546       *       via {@link #headers()}, or per-request via {@link RestRequest#header(Header)}.
3547       * <p>
3548       *    <c>Content-Type</c> request header will be set to <js>"octal/msgpack"</js> unless overridden
3549       *       via {@link #headers()}, or per-request via {@link RestRequest#header(Header)}.
3550       * <p>
3551       *    Can be combined with other marshaller setters such as {@link #json()} to provide support for multiple languages.
3552       *    <ul>
3553       *       <li>When multiple languages are supported, the <c>Accept</c> and <c>Content-Type</c> headers control which marshallers are used, or uses the
3554       *       last-enabled language if the headers are not set.
3555       *    </ul>
3556       * <p>
3557       *    Identical to calling <c>serializer(MsgPackSerializer.<jk>class</jk>).parser(MsgPackParser.<jk>class</jk>)</c>.
3558       *
3559       * <h5 class='section'>Example:</h5>
3560       * <p class='bjava'>
3561       *    <jc>// Construct a client that uses MessagePack marshalling.</jc>
3562       *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().msgPack().build();
3563       * </p>
3564       *
3565       * @return This object.
3566       */
3567      public Builder msgPack() {
3568         return serializer(MsgPackSerializer.class).parser(MsgPackParser.class);
3569      }
3570
3571      @Override /* Overridden from Builder */
3572      public Builder notBeanClasses(java.lang.Class<?>...values) {
3573         super.notBeanClasses(values);
3574         return this;
3575      }
3576
3577      @Override /* Overridden from Builder */
3578      public Builder notBeanPackages(String...values) {
3579         super.notBeanPackages(values);
3580         return this;
3581      }
3582
3583      /**
3584       * When called, <c>No-Trace: true</c> is added to requests.
3585       *
3586       * <p>
3587       * This gives the opportunity for the servlet to not log errors on invalid requests.
3588       * This is useful for testing purposes when you don't want your log file to show lots of errors that are simply the
3589       * results of testing.
3590       *
3591       * <p>
3592       * It's up to the server to decide whether to allow for this.
3593       * The <c>BasicTestRestLogger</c> class watches for this header and prevents logging of status 400+ responses to
3594       * prevent needless logging of test scenarios.
3595       *
3596       * @return This object.
3597       * @see #headers()
3598       */
3599      public Builder noTrace() {
3600         return headers(NoTrace.of(true));
3601      }
3602
3603      /**
3604       * <i><l>OpenApiCommon</l> configuration property:&emsp;</i>  Default collection format for HTTP parts.
3605       *
3606       * <p>
3607       * Specifies the collection format to use for HTTP parts when not otherwise specified via {@link org.apache.juneau.annotation.Schema#collectionFormat()} for the
3608       * OpenAPI serializer and parser on this client.
3609       *
3610       * <h5 class='section'>Example:</h5>
3611       * <p class='bjava'>
3612       *    <jc>// Create a REST client with CSV format for http parts.</jc>
3613       *    RestClient <jv>client</jv> = RestClient
3614       *       .<jsm>create</jsm>()
3615       *       .collectionFormat(<jsf>CSV</jsf>)
3616       *       .build();
3617       *
3618       *    <jc>// An arbitrary data structure.</jc>
3619       *    AList <jv>list</jv> = AList.<jsm>of</jsm>(
3620       *       <js>"foo"</js>,
3621       *       <js>"bar"</js>,
3622       *       AMap.<jsm>of</jsm>(
3623       *          <js>"baz"</js>, AList.<jsm>of</jsm>(<js>"qux"</js>,<js>"true"</js>,<js>"123"</js>)
3624       *    )
3625       * );
3626       *
3627       *    <jc>// Set a header with a comma-separated list.</jc>
3628       *    <jv>client</jv>
3629       *       .get(<js>"/uri"</js>)
3630       *       .header(<js>"Foo"</js>, <jv>list</jv>)  <jc>// Will be serialized as: foo=bar,baz=qux\,true\,123</jc>
3631       *       .run();
3632       * </p>
3633       *
3634       * <ul class='values javatree'>
3635       *    <li class='jc'>{@link HttpPartCollectionFormat}
3636       *    <ul>
3637       *       <li class='jf'>{@link HttpPartCollectionFormat#CSV CSV} - (default) Comma-separated values (e.g. <js>"foo,bar"</js>).
3638       *       <li class='jf'>{@link HttpPartCollectionFormat#SSV SSV} - Space-separated values (e.g. <js>"foo bar"</js>).
3639       *       <li class='jf'>{@link HttpPartCollectionFormat#TSV TSV} - Tab-separated values (e.g. <js>"foo\tbar"</js>).
3640       *       <li class='jf'>{@link HttpPartCollectionFormat#PIPES PIPES} - Pipe-separated values (e.g. <js>"foo|bar"</js>).
3641       *       <li class='jf'>{@link HttpPartCollectionFormat#MULTI MULTI} - Corresponds to multiple parameter instances instead of multiple values for a single instance (e.g. <js>"foo=bar&amp;foo=baz"</js>).
3642       *       <li class='jf'>{@link HttpPartCollectionFormat#UONC UONC} - UON collection notation (e.g. <js>"@(foo,bar)"</js>).
3643       *    </ul>
3644       * </ul>
3645       *
3646       * <h5 class='section'>See Also:</h5><ul>
3647       *    <li class='jm'>{@link org.apache.juneau.oapi.OpenApiSerializer.Builder#collectionFormat(HttpPartCollectionFormat)}
3648       *    <li class='jm'>{@link org.apache.juneau.oapi.OpenApiParser.Builder#collectionFormat(HttpPartCollectionFormat)}
3649       * </ul>
3650       *
3651       * @param value
3652       *    The new value for this property.
3653       *    <br>The default value is {@link HttpPartCollectionFormat#NO_COLLECTION_FORMAT}.
3654       *    <br>Cannot be <jk>null</jk>.
3655       * @return This object.
3656       */
3657      public Builder oapiCollectionFormat(HttpPartCollectionFormat value) {
3658         serializers().forEach(OpenApiSerializer.Builder.class, x -> x.collectionFormat(value));
3659         parsers().forEach(OpenApiParser.Builder.class, x -> x.collectionFormat(value));
3660         partSerializer().builder(OpenApiSerializer.Builder.class, x -> x.collectionFormat(value));
3661         partParser().builder(OpenApiParser.Builder.class, x -> x.collectionFormat(value));
3662         return this;
3663      }
3664
3665      /**
3666       * <i><l>OpenApiCommon</l> configuration property:&emsp;</i>  Default OpenAPI format for HTTP parts.
3667       *
3668       * <p>
3669       * Specifies the format to use for HTTP parts when not otherwise specified via {@link org.apache.juneau.annotation.Schema#format()} for
3670       * the OpenAPI serializer and parser on this client.
3671       *
3672       * <h5 class='section'>Example:</h5>
3673       * <p class='bjava'>
3674       *    <jc>// Create a REST client with UON part serialization and parsing.</jc>
3675       *    RestClient <jv>client</jv>  = RestClient
3676       *       .<jsm>create</jsm>()
3677       *       .oapiFormat(<jsf>UON</jsf>)
3678       *       .build();
3679       *
3680       *    <jc>// Set a header with a value in UON format.</jc>
3681       *    <jv>client</jv>
3682       *       .get(<js>"/uri"</js>)
3683       *       .header(<js>"Foo"</js>, <js>"bar baz"</js>)  <jc>// Will be serialized as:  'bar baz'</jc>
3684       *       .run();
3685       * </p>
3686       *
3687       * <ul class='values javatree'>
3688       *    <li class='jc'>{@link org.apache.juneau.httppart.HttpPartFormat}
3689       *    <ul>
3690       *       <li class='jf'>{@link org.apache.juneau.httppart.HttpPartFormat#UON UON} - UON notation (e.g. <js>"'foo bar'"</js>).
3691       *       <li class='jf'>{@link org.apache.juneau.httppart.HttpPartFormat#INT32 INT32} - Signed 32 bits.
3692       *       <li class='jf'>{@link org.apache.juneau.httppart.HttpPartFormat#INT64 INT64} - Signed 64 bits.
3693       *       <li class='jf'>{@link org.apache.juneau.httppart.HttpPartFormat#FLOAT FLOAT} - 32-bit floating point number.
3694       *       <li class='jf'>{@link org.apache.juneau.httppart.HttpPartFormat#DOUBLE DOUBLE} - 64-bit floating point number.
3695       *       <li class='jf'>{@link org.apache.juneau.httppart.HttpPartFormat#BYTE BYTE} - BASE-64 encoded characters.
3696       *       <li class='jf'>{@link org.apache.juneau.httppart.HttpPartFormat#BINARY BINARY} - Hexadecimal encoded octets (e.g. <js>"00FF"</js>).
3697       *       <li class='jf'>{@link org.apache.juneau.httppart.HttpPartFormat#BINARY_SPACED BINARY_SPACED} - Spaced-separated hexadecimal encoded octets (e.g. <js>"00 FF"</js>).
3698       *       <li class='jf'>{@link org.apache.juneau.httppart.HttpPartFormat#DATE DATE} - An <a href='http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14'>RFC3339 full-date</a>.
3699       *       <li class='jf'>{@link org.apache.juneau.httppart.HttpPartFormat#DATE_TIME DATE_TIME} - An <a href='http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14'>RFC3339 date-time</a>.
3700       *       <li class='jf'>{@link org.apache.juneau.httppart.HttpPartFormat#PASSWORD PASSWORD} - Used to hint UIs the input needs to be obscured.
3701       *       <li class='jf'>{@link org.apache.juneau.httppart.HttpPartFormat#NO_FORMAT NO_FORMAT} - (default) Not specified.
3702       *    </ul>
3703       * </ul>
3704       *
3705       * <h5 class='section'>See Also:</h5><ul>
3706       *    <li class='jm'>{@link org.apache.juneau.oapi.OpenApiSerializer.Builder#format(HttpPartFormat)}
3707       *    <li class='jm'>{@link org.apache.juneau.oapi.OpenApiParser.Builder#format(HttpPartFormat)}
3708       * </ul>
3709       *
3710       * @param value
3711       *    The new value for this property.
3712       *    <br>The default value is {@link HttpPartFormat#NO_FORMAT}.
3713       *    <br>Cannot be <jk>null</jk>.
3714       * @return This object.
3715       */
3716      public Builder oapiFormat(HttpPartFormat value) {
3717         serializers().forEach(OpenApiSerializer.Builder.class, x -> x.format(value));
3718         parsers().forEach(OpenApiParser.Builder.class, x -> x.format(value));
3719         partSerializer().builder(OpenApiSerializer.Builder.class).ifPresent(x -> x.format(value));
3720         partParser().builder(OpenApiParser.Builder.class).ifPresent(x -> x.format(value));
3721         return this;
3722      }
3723
3724      /**
3725       * Convenience method for specifying OpenAPI as the marshalling transmission media type.
3726       *
3727       * <p>
3728       * OpenAPI is a language that allows serialization to formats that use {@link HttpPartSchema} objects to describe their structure.
3729       *
3730       * <p>
3731       *    {@link OpenApiSerializer} will be used to serialize POJOs to request bodies unless overridden per request via {@link RestRequest#serializer(Serializer)}.
3732       *    <ul>
3733       *       <li>The serializer can be configured using any of the serializer property setters (e.g. {@link #sortCollections()}) or
3734       *          bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
3735       *       <li>Typically the {@link RestRequest#content(Object, HttpPartSchema)} method will be used to specify the body of the request with the
3736       *          schema describing it's structure.
3737       *    </ul>
3738       * <p>
3739       *    {@link OpenApiParser} will be used to parse POJOs from response bodies unless overridden per request via {@link RestRequest#parser(Parser)}.
3740       *    <ul>
3741       *       <li>The parser can be configured using any of the parser property setters (e.g. {@link #strict()}) or
3742       *          bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
3743       *       <li>Typically the {@link ResponseContent#schema(HttpPartSchema)} method will be used to specify the structure of the response body.
3744       *    </ul>
3745       * <p>
3746       *    <c>Accept</c> request header will be set to <js>"text/openapi"</js> unless overridden
3747       *       via {@link #headers()}, or per-request via {@link RestRequest#header(Header)}.
3748       * <p>
3749       *    <c>Content-Type</c> request header will be set to <js>"text/openapi"</js> unless overridden
3750       *       via {@link #headers()}, or per-request via {@link RestRequest#header(Header)}.
3751       * <p>
3752       *    Can be combined with other marshaller setters such as {@link #json()} to provide support for multiple languages.
3753       *    <ul>
3754       *       <li>When multiple languages are supported, the <c>Accept</c> and <c>Content-Type</c> headers control which marshallers are used, or uses the
3755       *       last-enabled language if the headers are not set.
3756       *    </ul>
3757       * <p>
3758       *    Identical to calling <c>serializer(OpenApiSerializer.<jk>class</jk>).parser(OpenApiParser.<jk>class</jk>)</c>.
3759       *
3760       * <h5 class='section'>Example:</h5>
3761       * <p class='bjava'>
3762       *    <jc>// Construct a client that uses OpenAPI marshalling.</jc>
3763       *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().openApi().build();
3764       * </p>
3765       *
3766       * @return This object.
3767       */
3768      public Builder openApi() {
3769         return serializer(OpenApiSerializer.class).parser(OpenApiParser.class);
3770      }
3771
3772      /**
3773       * <i><l>UonSerializer</l> configuration property:&emsp;</i>  Parameter format.
3774       *
3775       * <p>
3776       * Specifies the format of parameters when using the {@link UrlEncodingSerializer} to serialize Form Posts.
3777       *
3778       * <p>
3779       * Specifies the format to use for GET parameter keys and values.
3780       *
3781       * <h5 class='section'>Example:</h5>
3782       * <p class='bjava'>
3783       *    <jc>// Create a REST client with URL-Encoded serializer that serializes values in plain-text format.</jc>
3784       *    RestClient <jv>client</jv> = RestClient
3785       *       .<jsm>create</jsm>()
3786       *       .urlEnc()
3787       *       .paramFormat(<jsf>PLAINTEXT</jsf>)
3788       *       .build();
3789       *
3790       *    <jc>// An arbitrary data structure.</jc>
3791       *    AMap <jv>map</jv> = AMap.<jsm>of</jsm>(
3792       *       <js>"foo"</js>, <js>"bar"</js>,
3793       *       <js>"baz"</js>, <jk>new</jk> String[]{<js>"qux"</js>, <js>"true"</js>, <js>"123"</js>}
3794       *    );
3795       *
3796       *    <jc>// Request body will be serialized as:  foo=bar,baz=qux,true,123</jc>
3797       *    <jv>client</jv>
3798       *       .post(<js>"/uri"</js>, <jv>map</jv>)
3799       *       .run();
3800       * </p>
3801       *
3802       * <ul class='values javatree'>
3803       *    <li class='jf'>{@link ParamFormat#UON} (default) - Use UON notation for parameters.
3804       *    <li class='jf'>{@link ParamFormat#PLAINTEXT} - Use plain text for parameters.
3805       * </ul>
3806       *
3807       * <h5 class='section'>See Also:</h5><ul>
3808       *    <li class='jm'>{@link org.apache.juneau.uon.UonSerializer.Builder#paramFormat(ParamFormat)}
3809       * </ul>
3810       *
3811       * @param value The new value for this property.
3812       *    <br>Cannot be <jk>null</jk>.
3813       * @return This object.
3814       */
3815      public Builder paramFormat(ParamFormat value) {
3816         serializers().forEach(UonSerializer.Builder.class, x -> x.paramFormat(value));
3817         return this;
3818      }
3819
3820      /**
3821       * <i><l>UonSerializer</l> configuration property:&emsp;</i>  Parameter format.
3822       *
3823       * <p>
3824       * Specifies the format of parameters when using the {@link UrlEncodingSerializer} to serialize Form Posts.
3825       *
3826       * <p>
3827       * Specifies plaintext as the format to use for GET parameter keys and values.
3828       *
3829       * <h5 class='section'>Example:</h5>
3830       * <p class='bjava'>
3831       *    <jc>// Create a REST client with URL-Encoded serializer that serializes values in plain-text format.</jc>
3832       *    RestClient <jv>client</jv> = RestClient
3833       *       .<jsm>create</jsm>()
3834       *       .urlEnc()
3835       *       .build();
3836       *
3837       *    <jc>// An arbitrary data structure.</jc>
3838       *    AMap <jv>map</jv> = AMap.<jsm>of</jsm>(
3839       *       <js>"foo"</js>, <js>"bar"</js>,
3840       *       <js>"baz"</js>, <jk>new</jk> String[]{<js>"qux"</js>, <js>"true"</js>, <js>"123"</js>}
3841       *    );
3842       *
3843       *    <jc>// Request body will be serialized as:  foo=bar,baz=qux,true,123</jc>
3844       *    <jv>client</jv>
3845       *       .post(<js>"/uri"</js>, <jv>map</jv>)
3846       *       .run();
3847       * </p>
3848       *
3849       * <h5 class='section'>See Also:</h5><ul>
3850       *    <li class='jm'>{@link org.apache.juneau.uon.UonSerializer.Builder#paramFormatPlain()}
3851       * </ul>
3852       *
3853       * @return This object.
3854       */
3855      public Builder paramFormatPlain() {
3856         serializers().forEach(UonSerializer.Builder.class, org.apache.juneau.uon.UonSerializer.Builder::paramFormatPlain);
3857         return this;
3858      }
3859
3860      /**
3861       * Parser.
3862       *
3863       * <p>
3864       * Associates the specified {@link Parser Parser} with the HTTP client.
3865       *
3866       * <p>
3867       * The parser is used to parse the HTTP response body into a POJO.
3868       *
3869       * <h5 class='section'>Notes:</h5><ul>
3870       *    <li class='note'>When using this method that takes in a class, the parser can be configured using any of the parser property setters (e.g. {@link #strict()}) or
3871       *    bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
3872       * </ul>
3873       *
3874       * <h5 class='section'>Example:</h5>
3875       * <p class='bjava'>
3876       *    <jc>// Create a client that uses JSON transport for response bodies.</jc>
3877       *    RestClient <jv>client</jv> = RestClient
3878       *       .<jsm>create</jsm>()
3879       *       .parser(JsonParser.<jk>class</jk>)
3880       *       .strict()  <jc>// Enable strict mode on JsonParser.</jc>
3881       *       .build();
3882       * </p>
3883       *
3884       * @param value
3885       *    The new value for this setting.
3886       *    <br>The default value is {@link JsonParser#DEFAULT}.
3887       * @return This object.
3888       */
3889      @SuppressWarnings("unchecked")
3890      public Builder parser(Class<? extends Parser> value) {
3891         return parsers(value);
3892      }
3893
3894      /**
3895       * Parser.
3896       *
3897       * <p>
3898       * Associates the specified {@link Parser Parser} with the HTTP client.
3899       *
3900       * <p>
3901       * The parser is used to parse the HTTP response body into a POJO.
3902       *
3903       * <h5 class='section'>Notes:</h5><ul>
3904       *    <li class='note'>When using this method that takes in a pre-instantiated parser, the parser property setters (e.g. {@link #strict()}) or
3905       *    bean context property setters (e.g. {@link #swaps(Class...)}) defined
3906       *    on this builder class have no effect.
3907       * </ul>
3908       *
3909       * <h5 class='section'>Example:</h5>
3910       * <p class='bjava'>
3911       *    <jc>// Create a client that uses a predefined JSON parser for response bodies.</jc>
3912       *    RestClient <jv>client</jv> = RestClient
3913       *       .<jsm>create</jsm>()
3914       *       .parser(JsonParser.<jsf>DEFAULT_STRICT</jsf>)
3915       *       .build();
3916       * </p>
3917       *
3918       * @param value
3919       *    The new value for this setting.
3920       *    <br>The default value is {@link JsonParser#DEFAULT}.
3921       *    <br>Cannot be <jk>null</jk>.
3922       * @return This object.
3923       */
3924      public Builder parser(Parser value) {
3925         return parsers(value);
3926      }
3927
3928      /**
3929       * Returns the parser group sub-builder.
3930       *
3931       * @return The parser group sub-builder.
3932       */
3933      public final ParserSet.Builder parsers() {
3934         if (parsers == null)
3935            parsers = createParsers();
3936         return parsers;
3937      }
3938
3939      /**
3940       * Parsers.
3941       *
3942       * <p>
3943       * Associates the specified {@link Parser Parsers} with the HTTP client.
3944       *
3945       * <p>
3946       * The parsers are used to parse the HTTP response body into a POJO.
3947       *
3948       * <p>
3949       * The parser that best matches the <c>Accept</c> header will be used to parse the response body.
3950       * <br>If no <c>Accept</c> header is specified, the first parser in the list will be used.
3951       *
3952       * <h5 class='section'>Notes:</h5><ul>
3953       *    <li class='note'>When using this method that takes in classes, the parsers can be configured using any of the parser property setters (e.g. {@link #strict()}) or
3954       *    bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
3955       * </ul>
3956       *
3957       * <h5 class='section'>Example:</h5>
3958       * <p class='bjava'>
3959       *    <jc>// Create a client that uses JSON and XML transport for response bodies.</jc>
3960       *    RestClient <jv>client</jv> = RestClient
3961       *       .<jsm>create</jsm>()
3962       *       .parser(JsonParser.<jk>class</jk>, XmlParser.<jk>class</jk>)
3963       *       .strict()  <jc>// Enable strict mode on parsers.</jc>
3964       *       .build();
3965       * </p>
3966       *
3967       * @param value
3968       *    The new value for this setting.
3969       *    <br>The default value is {@link JsonParser#DEFAULT}.
3970       * @return This object.
3971       */
3972      @SuppressWarnings("unchecked")
3973      public Builder parsers(Class<? extends Parser>...value) {
3974         assertArgNoNulls("value", value);
3975         parsers().add(value);
3976         return this;
3977      }
3978
3979      /**
3980       * Parsers.
3981       *
3982       * <p>
3983       * Associates the specified {@link Parser Parsers} with the HTTP client.
3984       *
3985       * <p>
3986       * The parsers are used to parse the HTTP response body into a POJO.
3987       *
3988       * <p>
3989       * The parser that best matches the <c>Accept</c> header will be used to parse the response body.
3990       * <br>If no <c>Accept</c> header is specified, the first parser in the list will be used.
3991       *
3992       * <h5 class='section'>Notes:</h5><ul>
3993       *    <li class='note'>When using this method that takes in pre-instantiated parsers, the parser property setters (e.g. {@link #strict()}) or
3994       *    bean context property setters (e.g. {@link #swaps(Class...)}) defined
3995       *    on this builder class have no effect.
3996       * </ul>
3997       *
3998       * <h5 class='section'>Example:</h5>
3999       * <p class='bjava'>
4000       *    <jc>// Create a client that uses JSON and XML transport for response bodies.</jc>
4001       *    RestClient <jv>client</jv> = RestClient
4002       *       .<jsm>create</jsm>()
4003       *       .parser(JsonParser.<jsf>DEFAULT_STRICT</jsf>, XmlParser.<jsf>DEFAULT</jsf>)
4004       *       .build();
4005       * </p>
4006       *
4007       * @param value
4008       *    The new value for this setting.
4009       *    <br>The default value is {@link JsonParser#DEFAULT}.
4010       * @return This object.
4011       */
4012      public Builder parsers(Parser...value) {
4013         assertArgNoNulls("value", value);
4014         parsers().add(value);
4015         return this;
4016      }
4017
4018      /**
4019       * Returns the part parser sub-builder.
4020       *
4021       * @return The part parser sub-builder.
4022       */
4023      public final HttpPartParser.Creator partParser() {
4024         if (partParser == null)
4025            partParser = createPartParser();
4026         return partParser;
4027      }
4028
4029      /**
4030       * Part parser.
4031       *
4032       * <p>
4033       * The parser to use for parsing POJOs from form data, query parameters, headers, and path variables.
4034       *
4035       * <p>
4036       * The default part parser is {@link OpenApiParser} which allows for schema-driven marshalling.
4037       *
4038       * <h5 class='section'>Example:</h5>
4039       * <p class='bjava'>
4040       *    <jc>// Create a client that uses UON format by default for incoming HTTP parts.</jc>
4041       *    RestClient <jv>client</jv> = RestClient
4042       *       .<jsm>create</jsm>()
4043       *       .partParser(UonParser.<jk>class</jk>)
4044       *       .build();
4045       * </p>
4046       *
4047       * @param value
4048       *    The new value for this setting.
4049       *    <br>The default value is {@link OpenApiParser}.
4050       *    <br>Cannot be <jk>null</jk>.
4051       * @return This object.
4052       */
4053      public Builder partParser(Class<? extends HttpPartParser> value) {
4054         partParser().type(assertArgNotNull("value", value));
4055         return this;
4056      }
4057
4058      /**
4059       * Part parser.
4060       *
4061       * <p>
4062       * The parser to use for parsing POJOs from form data, query parameters, headers, and path variables.
4063       *
4064       * <p>
4065       * The default part parser is {@link OpenApiParser} which allows for schema-driven marshalling.
4066       *
4067       * <h5 class='section'>Example:</h5>
4068       * <p class='bjava'>
4069       *    <jc>// Create a client that uses UON format by default for incoming HTTP parts.</jc>
4070       *    RestClient <jv>client</jv> = RestClient
4071       *       .<jsm>create</jsm>()
4072       *       .partParser(UonParser.<jsf>DEFAULT</jsf>)
4073       *       .build();
4074       * </p>
4075       *
4076       * @param value
4077       *    The new value for this setting.
4078       *    <br>The default value is {@link OpenApiParser}.
4079       *    <br>Cannot be <jk>null</jk>.
4080       * @return This object.
4081       */
4082      public Builder partParser(HttpPartParser value) {
4083         partParser().impl(assertArgNotNull("value", value));
4084         return this;
4085      }
4086
4087      /**
4088       * Returns the part serializer sub-builder.
4089       *
4090       * @return The part serializer sub-builder.
4091       */
4092      public final HttpPartSerializer.Creator partSerializer() {
4093         if (partSerializer == null)
4094            partSerializer = createPartSerializer();
4095         return partSerializer;
4096      }
4097
4098      /**
4099       * Part serializer.
4100       *
4101       * <p>
4102       * The serializer to use for serializing POJOs in form data, query parameters, headers, and path variables.
4103       *
4104       * <p>
4105       * The default part serializer is {@link OpenApiSerializer} which allows for schema-driven marshalling.
4106       *
4107       * <h5 class='section'>Example:</h5>
4108       * <p class='bjava'>
4109       *    <jc>// Create a client that uses UON format by default for outgoing HTTP parts.</jc>
4110       *    RestClient <jv>client</jv> = RestClient
4111       *       .<jsm>create</jsm>()
4112       *       .partSerializer(UonSerializer.<jk>class</jk>)
4113       *       .build();
4114       * </p>
4115       *
4116       * @param value
4117       *    The new value for this setting.
4118       *    <br>The default value is {@link OpenApiSerializer}.
4119       *    <br>Cannot be <jk>null</jk>.
4120       * @return This object.
4121       */
4122      public Builder partSerializer(Class<? extends HttpPartSerializer> value) {
4123         partSerializer().type(assertArgNotNull("value", value));
4124         return this;
4125      }
4126
4127      /**
4128       * Part serializer.
4129       *
4130       * <p>
4131       * The serializer to use for serializing POJOs in form data, query parameters, headers, and path variables.
4132       *
4133       * <p>
4134       * The default part serializer is {@link OpenApiSerializer} which allows for schema-driven marshalling.
4135       *
4136       * <h5 class='section'>Example:</h5>
4137       * <p class='bjava'>
4138       *    <jc>// Create a client that uses UON format by default for outgoing HTTP parts.</jc>
4139       *    RestClient <jv>client</jv> = RestClient
4140       *       .<jsm>create</jsm>()
4141       *       .partSerializer(UonSerializer.<jsf>DEFAULT</jsf>)
4142       *       .build();
4143       * </p>
4144       *
4145       * @param value
4146       *    The new value for this setting.
4147       *    <br>The default value is {@link OpenApiSerializer}.
4148       *    <br>Cannot be <jk>null</jk>.
4149       * @return This object.
4150       */
4151      public Builder partSerializer(HttpPartSerializer value) {
4152         partSerializer().impl(assertArgNotNull("value", value));
4153         return this;
4154      }
4155
4156      /**
4157       * Returns the builder for the list of path data parameters that get applied to all requests created by this builder.
4158       *
4159       * <p>
4160       * This is the primary method for accessing the path data parameter list.
4161       * On first call, the builder is created via the method {@link #createFormData()}.
4162       *
4163       * <h5 class='section'>Example:</h5>
4164       * <p class='bjava'>
4165       *    <jc>// Create a client that uses "bar" for the "{foo}" path variable on every request.</jc>
4166       *    RestClient.Builder <jv>builder</jv> = RestClient.<jsm>create</jsm>();
4167       *    <jv>builder</jv>.pathData().setDefault(<js>"foo"</js>, <js>"bar"</js>));
4168       *    RestClient <jv>client</jv> = <jv>builder</jv>.build();
4169       * </p>
4170       *
4171       * <p>
4172       * The following convenience methods are also provided for updating the parameters:
4173       * <ul>
4174       *    <li class='jm'>{@link #pathData(NameValuePair...)}
4175       *    <li class='jm'>{@link #pathDataDefault(NameValuePair...)}
4176       *    <li class='jm'>{@link #pathData(String,String)}
4177       *    <li class='jm'>{@link #pathData(String,Supplier)}
4178       * </ul>
4179       *
4180       * @return The form data list builder.
4181       */
4182      public final PartList pathData() {
4183         if (pathData == null)
4184            pathData = createPathData();
4185         return pathData;
4186      }
4187
4188      /**
4189       * Sets multiple path parameters on all requests.
4190       *
4191       * <h5 class='section'>Example:</h5>
4192       * <p class='bjava'>
4193       *    <jk>import static</jk> org.apache.juneau.http.HttpParts.*;
4194       *
4195       *    RestClient <jv>client</jv> = RestClient
4196       *       .<jsm>create</jsm>()
4197       *       .pathData(
4198       *          <jsm>stringPart</jsm>(<js>"foo"</js>, <js>"bar"</js>),
4199       *          <jsm>booleanPart</jsm>(<js>"baz"</js>, <jk>true</jk>)
4200       *       )
4201       *       .build();
4202       * </p>
4203       *
4204       * <p>
4205       * This is a shortcut for calling <c>pathData().append(<jv>parts</jv>)</c>.
4206       *
4207       * @param parts
4208       *    The path parameters.
4209       *    <br>Can contain <jk>null</jk> values (ignored).
4210       * @return This object.
4211       * @see #pathData()
4212       */
4213      public Builder pathData(NameValuePair...parts) {
4214         pathData().append(parts);
4215         return this;
4216      }
4217
4218      /**
4219       * Appends a path parameter to all request bodies.
4220       *
4221       * <h5 class='section'>Example:</h5>
4222       * <p class='bjava'>
4223       *    RestClient <jv>client</jv> = RestClient
4224       *       .<jsm>create</jsm>()
4225       *       .pathData(<js>"foo"</js>, <js>"bar"</js>)
4226       *       .build();
4227       * </p>
4228       *
4229       * <p>
4230       * This is a shortcut for calling <c>pathData().append(<jv>name</jv>,<jv>value</jv>)</c>.
4231       *
4232       * @param name The parameter name.
4233       *    <br>Cannot be <jk>null</jk>.
4234       * @param value The parameter value.
4235       *    <br>Can be <jk>null</jk> (null value will be serialized).
4236       * @return This object.
4237       * @see #pathData()
4238       */
4239      public Builder pathData(String name, String value) {
4240         pathData().append(name, value);
4241         return this;
4242      }
4243
4244      /**
4245       * Sets a path parameter with a dynamic value to all request bodies.
4246       *
4247       * <h5 class='section'>Example:</h5>
4248       * <p class='bjava'>
4249       *    RestClient <jv>client</jv> = RestClient
4250       *       .<jsm>create</jsm>()
4251       *       .pathData(<js>"foo"</js>, ()-&gt;<js>"bar"</js>)
4252       *       .build();
4253       * </p>
4254       *
4255       * <p>
4256       * This is a shortcut for calling <c>pathData().append(<jv>name</jv>,<jv>value</jv>)</c>.
4257       *
4258       * @param name The parameter name.
4259       *    <br>Cannot be <jk>null</jk>.
4260       * @param value The parameter value supplier.
4261       *    <br>Can be <jk>null</jk> (null value will be serialized).
4262       * @return This object.
4263       * @see #pathData()
4264       */
4265      public Builder pathData(String name, Supplier<String> value) {
4266         pathData().set(name, value);
4267         return this;
4268      }
4269
4270      /**
4271       * Sets default path parameter values.
4272       *
4273       * <p>
4274       * Uses default values for specified parameters if not otherwise specified on the outgoing requests.
4275       *
4276       * <h5 class='section'>Example:</h5>
4277       * <p class='bjava'>
4278       *    RestClient <jv>client</jv> = RestClient
4279       *       .<jsm>create</jsm>()
4280       *       .pathDataDefault(<jsm>stringPart</jsm>(<js>"foo"</js>, ()-&gt;<js>"bar"</js>));
4281       *       .build();
4282       * </p>
4283       *
4284       * <p>
4285       * This is a shortcut for calling <c>pathData().setDefault(<jv>parts</jv>)</c>.
4286       *
4287       * @param parts The parts.
4288       *    <br>Can contain <jk>null</jk> values (ignored).
4289       * @return This object.
4290       * @see #pathData()
4291       */
4292      public Builder pathDataDefault(NameValuePair...parts) {
4293         pathData().setDefault(parts);
4294         return this;
4295      }
4296
4297      /**
4298       * Convenience method for specifying Plain Text as the marshalling transmission media type.
4299       *
4300       * <p>
4301       * Plain text marshalling typically only works on simple POJOs that can be converted to and from strings using
4302       * swaps, swap methods, etc...
4303       *
4304       * <p>
4305       *    {@link PlainTextSerializer} will be used to serialize POJOs to request bodies unless overridden per request via {@link RestRequest#serializer(Serializer)}.
4306       *    <ul>
4307       *       <li>The serializer can be configured using any of the serializer property setters (e.g. {@link #sortCollections()}) or
4308       *          bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
4309       *    </ul>
4310       * <p>
4311       *    {@link PlainTextParser} will be used to parse POJOs from response bodies unless overridden per request via {@link RestRequest#parser(Parser)}.
4312       *    <ul>
4313       *       <li>The parser can be configured using any of the parser property setters (e.g. {@link #strict()}) or
4314       *          bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
4315       *    </ul>
4316       * <p>
4317       *    <c>Accept</c> request header will be set to <js>"text/plain"</js> unless overridden
4318       *       via {@link #headers()}, or per-request via {@link RestRequest#header(Header)}.
4319       * <p>
4320       *    <c>Content-Type</c> request header will be set to <js>"text/plain"</js> unless overridden
4321       *       via {@link #headers()}, or per-request via {@link RestRequest#header(Header)}.
4322       * <p>
4323       *    Can be combined with other marshaller setters such as {@link #json()} to provide support for multiple languages.
4324       *    <ul>
4325       *       <li>When multiple languages are supported, the <c>Accept</c> and <c>Content-Type</c> headers control which marshallers are used, or uses the
4326       *       last-enabled language if the headers are not set.
4327       *    </ul>
4328       * <p>
4329       *    Identical to calling <c>serializer(PlainTextSerializer.<jk>class</jk>).parser(PlainTextParser.<jk>class</jk>)</c>.
4330       *
4331       * <h5 class='section'>Example:</h5>
4332       * <p class='bjava'>
4333       *    <jc>// Construct a client that uses Plain Text marshalling.</jc>
4334       *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().plainText().build();
4335       * </p>
4336       *
4337       * @return This object.
4338       */
4339      public Builder plainText() {
4340         return serializer(PlainTextSerializer.class).parser(PlainTextParser.class);
4341      }
4342
4343      /**
4344       * When called, the {@link #createConnectionManager()} method will return a {@link PoolingHttpClientConnectionManager}
4345       * instead of a {@link BasicHttpClientConnectionManager}.
4346       *
4347       * <h5 class='section'>Example:</h5>
4348       * <p class='bjava'>
4349       *    <jc>// Construct a client that uses pooled connections.</jc>
4350       *    RestClient <jv>client</jv> = RestClient
4351       *       .<jsm>create</jsm>()
4352       *       .pooled()
4353       *       .build();
4354       * </p>
4355       *
4356       * @return This object.
4357       */
4358      public Builder pooled() {
4359         this.pooled = true;
4360         return this;
4361      }
4362
4363      @Override /* Overridden from Builder */
4364      public Builder propertyNamer(Class<?> on, Class<? extends org.apache.juneau.PropertyNamer> value) {
4365         super.propertyNamer(on, value);
4366         return this;
4367      }
4368
4369      @Override /* Overridden from Builder */
4370      public Builder propertyNamer(Class<? extends org.apache.juneau.PropertyNamer> value) {
4371         super.propertyNamer(value);
4372         return this;
4373      }
4374
4375      /**
4376       * Assigns default proxy value.
4377       *
4378       * <h5 class='section'>Notes:</h5><ul>
4379       *    <li class='note'>This value can be overridden by the {@link #routePlanner(HttpRoutePlanner)} method.
4380       * </ul>
4381       *
4382       * @param proxy New property value.
4383       *    <br>Can be <jk>null</jk> (value will not be set, default behavior will be used).
4384       * @return This object.
4385       * @see HttpClientBuilder#setProxy(HttpHost)
4386       */
4387      public Builder proxy(HttpHost proxy) {
4388         httpClientBuilder().setProxy(proxy);
4389         return this;
4390      }
4391
4392      /**
4393       * Assigns {@link AuthenticationStrategy} instance for proxy authentication.
4394       *
4395       * @param proxyAuthStrategy New property value.
4396       *    <br>Can be <jk>null</jk> (value will not be set, default behavior will be used).
4397       * @return This object.
4398       * @see HttpClientBuilder#setProxyAuthenticationStrategy(AuthenticationStrategy)
4399       */
4400      public Builder proxyAuthenticationStrategy(AuthenticationStrategy proxyAuthStrategy) {
4401         httpClientBuilder().setProxyAuthenticationStrategy(proxyAuthStrategy);
4402         return this;
4403      }
4404
4405      /**
4406       * Assigns file containing public suffix matcher.
4407       *
4408       * <h5 class='section'>Notes:</h5><ul>
4409       *    <li class='note'>Instances of this class can be created with {@link PublicSuffixMatcherLoader}.
4410       * </ul>
4411       *
4412       * @param publicSuffixMatcher New property value.
4413       *    <br>Can be <jk>null</jk> (value will not be set, default behavior will be used).
4414       * @return This object.
4415       * @see HttpClientBuilder#setPublicSuffixMatcher(PublicSuffixMatcher)
4416       */
4417      public Builder publicSuffixMatcher(PublicSuffixMatcher publicSuffixMatcher) {
4418         httpClientBuilder().setPublicSuffixMatcher(publicSuffixMatcher);
4419         return this;
4420      }
4421
4422      /**
4423       * Returns the builder for the list of query parameters that get applied to all requests created by this builder.
4424       *
4425       * <p>
4426       * This is the primary method for accessing the query parameter list.
4427       * On first call, the builder is created via the method {@link #createQueryData()}.
4428       *
4429       * <h5 class='section'>Example:</h5>
4430       * <p class='bjava'>
4431       *    <jc>// Create a client that adds a "foo=bar" query parameter on every request.</jc>
4432       *    RestClient.Builder <jv>builder</jv> = RestClient.<jsm>create</jsm>();
4433       *    <jv>builder</jv>.queryData().setDefault(<js>"foo"</js>, <js>"bar"</js>));
4434       *    RestClient <jv>client</jv> = <jv>builder</jv>.build();
4435       * </p>
4436       *
4437       * <p>
4438       * The following convenience methods are also provided for updating the parameters:
4439       * <ul>
4440       *    <li class='jm'>{@link #queryData(NameValuePair...)}
4441       *    <li class='jm'>{@link #queryDataDefault(NameValuePair...)}
4442       *    <li class='jm'>{@link #queryData(String,String)}
4443       *    <li class='jm'>{@link #queryData(String,Supplier)}
4444       * </ul>
4445       *
4446       * @return The query data list builder.
4447       */
4448      public final PartList queryData() {
4449         if (queryData == null)
4450            queryData = createQueryData();
4451         return queryData;
4452      }
4453
4454      /**
4455       * Appends multiple query parameters to the URI of all requests.
4456       *
4457       * <h5 class='section'>Example:</h5>
4458       * <p class='bjava'>
4459       *    <jk>import static</jk> org.apache.juneau.http.HttpParts.*;
4460       *
4461       *    RestClient <jv>client</jv> = RestClient
4462       *       .<jsm>create</jsm>()
4463       *       .queryData(
4464       *          <jsm>stringPart</jsm>(<js>"foo"</js>, <js>"bar"</js>),
4465       *          <jsm>booleanPart</jsm>(<js>"baz"</js>, <jk>true</jk>)
4466       *       )
4467       *       .build();
4468       * </p>
4469       *
4470       * <p>
4471       * This is a shortcut for calling <c>queryData().append(<jv>parts</jv>)</c>.
4472       *
4473       * @param parts
4474       *    The query parameters.
4475       *    <br>Can contain <jk>null</jk> values (ignored).
4476       * @return This object.
4477       * @see #queryData()
4478       */
4479      public Builder queryData(NameValuePair...parts) {
4480         queryData().append(parts);
4481         return this;
4482      }
4483
4484      /**
4485       * Appends a query parameter to the URI.
4486       *
4487       * <h5 class='section'>Example:</h5>
4488       * <p class='bjava'>
4489       *    RestClient <jv>client</jv> = RestClient
4490       *       .<jsm>create</jsm>()
4491       *       .queryData(<js>"foo"</js>, <js>"bar"</js>)
4492       *       .build();
4493       * </p>
4494       *
4495       * <p>
4496       * This is a shortcut for calling <c>queryData().append(<jv>name</jv>,<jv>value</jv>)</c>.
4497       *
4498       * @param name The parameter name.
4499       *    <br>Cannot be <jk>null</jk>.
4500       * @param value The parameter value.
4501       *    <br>Can be <jk>null</jk> (null value will be serialized).
4502       * @return This object.
4503       * @see #queryData()
4504       */
4505      public Builder queryData(String name, String value) {
4506         queryData().append(name, value);
4507         return this;
4508      }
4509
4510      /**
4511       * Appends a query parameter with a dynamic value to the URI.
4512       *
4513       * <h5 class='section'>Example:</h5>
4514       * <p class='bjava'>
4515       *    RestClient <jv>client</jv> = RestClient
4516       *       .<jsm>create</jsm>()
4517       *       .queryData(<js>"foo"</js>, ()-&gt;<js>"bar"</js>)
4518       *       .build();
4519       * </p>
4520       *
4521       * <p>
4522       * This is a shortcut for calling <c>queryData().append(<jv>name</jv>,<jv>value</jv>)</c>.
4523       *
4524       * @param name The parameter name.
4525       *    <br>Cannot be <jk>null</jk>.
4526       * @param value The parameter value supplier.
4527       *    <br>Can be <jk>null</jk> (null value will be serialized).
4528       * @return This object.
4529       * @see #queryData()
4530       */
4531      public Builder queryData(String name, Supplier<String> value) {
4532         queryData().append(name, value);
4533         return this;
4534      }
4535
4536      /**
4537       * Sets default query parameter values.
4538       *
4539       * <p>
4540       * Uses default values for specified parameters if not otherwise specified on the outgoing requests.
4541       *
4542       * <h5 class='section'>Example:</h5>
4543       * <p class='bjava'>
4544       *    RestClient <jv>client</jv> = RestClient
4545       *       .<jsm>create</jsm>()
4546       *       .queryDataDefault(<jsm>stringPart</jsm>(<js>"foo"</js>, ()-&gt;<js>"bar"</js>));
4547       *       .build();
4548       * </p>
4549       *
4550       * <p>
4551       * This is a shortcut for calling <c>queryData().setDefault(<jv>parts</jv>)</c>.
4552       *
4553       * @param parts The parts.
4554       *    <br>Can contain <jk>null</jk> values (ignored).
4555       * @return This object.
4556       * @see #queryData()
4557       */
4558      public Builder queryDataDefault(NameValuePair...parts) {
4559         queryData().setDefault(parts);
4560         return this;
4561      }
4562
4563      /**
4564       * <i><l>WriterSerializer</l> configuration property:&emsp;</i>  Quote character.
4565       *
4566       * <p>
4567       * Specifies the character to use for quoting attributes and values.
4568       *
4569       * <h5 class='section'>Notes:</h5><ul>
4570       *    <li class='note'>This setting does not apply to the RDF serializers.
4571       * </ul>
4572       *
4573       * <h5 class='section'>Example:</h5>
4574       * <p class='bjava'>
4575       *    <jc>// Create a REST client with JSON serializer that uses single quotes.</jc>
4576       *    RestClient <jv>client</jv> = RestClient
4577       *       .<jsm>create</jsm>()
4578       *       .json()
4579       *       .quoteChar(<js>'\''</js>)
4580       *       .build();
4581       *
4582       *    <jc>// A bean with a single property</jc>
4583       *    <jk>public class</jk> MyBean {
4584       *       <jk>public</jk> String <jf>foo</jf> = <js>"bar"</js>;
4585       *    }
4586       *
4587       *    <jc>// Request body will contain:  {'foo':'bar'}</jc>
4588       *    <jv>client</jv>
4589       *       .post(<js>"http://localhost:10000/foo"</js>, <jk>new</jk> MyBean())
4590       *       .run();
4591       * </p>
4592       *
4593       * <h5 class='section'>See Also:</h5><ul>
4594       *    <li class='jm'>{@link org.apache.juneau.serializer.WriterSerializer.Builder#quoteChar(char)}
4595       * </ul>
4596       *
4597       * @param value
4598       *    The new value for this property.
4599       *    <br>The default is <js>'"'</js>.
4600       * @return This object.
4601       */
4602      public Builder quoteChar(char value) {
4603         serializers().forEachWS(x -> x.quoteChar(value));
4604         return this;
4605      }
4606
4607      /**
4608       * Assigns {@link RedirectStrategy} instance.
4609       *
4610       * <h5 class='section'>Notes:</h5><ul>
4611       *    <li class='note'>This value can be overridden by the {@link #disableRedirectHandling()} method.
4612       * </ul>
4613       *
4614       * @param redirectStrategy New property value.
4615       *    <br>Can be <jk>null</jk> (value will not be set, default behavior will be used).
4616       * @return This object.
4617       * @see HttpClientBuilder#setRedirectStrategy(RedirectStrategy)
4618       */
4619      public Builder redirectStrategy(RedirectStrategy redirectStrategy) {
4620         httpClientBuilder().setRedirectStrategy(redirectStrategy);
4621         return this;
4622      }
4623
4624      /**
4625       * Assigns {@link HttpRequestExecutor} instance.
4626       *
4627       * @param requestExec New property value.
4628       *    <br>Can be <jk>null</jk> (value will not be set, default behavior will be used).
4629       * @return This object.
4630       * @see HttpClientBuilder#setRequestExecutor(HttpRequestExecutor)
4631       */
4632      public Builder requestExecutor(HttpRequestExecutor requestExec) {
4633         httpClientBuilder().setRequestExecutor(requestExec);
4634         return this;
4635      }
4636
4637      /**
4638       * Assigns {@link HttpRequestRetryHandler} instance.
4639       *
4640       * <h5 class='section'>Notes:</h5><ul>
4641       *    <li class='note'>This value can be overridden by the {@link #disableAutomaticRetries()} method.
4642       * </ul>
4643       *
4644       * @param retryHandler New property value.
4645       *    <br>Can be <jk>null</jk> (value will not be set, default behavior will be used).
4646       * @return This object.
4647       * @see HttpClientBuilder#setRetryHandler(HttpRequestRetryHandler)
4648       */
4649      public Builder retryHandler(HttpRequestRetryHandler retryHandler) {
4650         httpClientBuilder().setRetryHandler(retryHandler);
4651         return this;
4652      }
4653
4654      /**
4655       * <i><l>RestClient</l> configuration property:&emsp;</i>  Root URI.
4656       *
4657       * <p>
4658       * When set, relative URI strings passed in through the various rest call methods (e.g. {@link RestClient#get(Object)}
4659       * will be prefixed with the specified root.
4660       * <br>This root URI is ignored on those methods if you pass in a {@link URL}, {@link URI}, or an absolute URI string.
4661       *
4662       * <h5 class='section'>Example:</h5>
4663       * <p class='bjava'>
4664       *    <jc>// Create a client that uses UON format by default for HTTP parts.</jc>
4665       *    RestClient <jv>client</jv> = RestClient
4666       *       .<jsm>create</jsm>()
4667       *       .rootUrl(<js>"http://localhost:10000/foo"</js>)
4668       *       .build();
4669       *
4670       *    Bar <jv>bar</jv> = <jv>client</jv>
4671       *       .get(<js>"/bar"</js>)  <jc>// Relative to http://localhost:10000/foo</jc>
4672       *       .run()
4673       *       .getContent().as(Bar.<jk>class</jk>);
4674       * </p>
4675       *
4676       * @param value
4677       *    The root URI to prefix to relative URI strings.
4678       *    <br>Trailing slashes are trimmed.
4679       *    <br>Usually a <c>String</c> but you can also pass in <c>URI</c> and <c>URL</c> objects as well.
4680       *    <br>Can be <jk>null</jk> (no root URL will be set).
4681       * @return This object.
4682       */
4683      public Builder rootUrl(Object value) {
4684         var s = s(value);
4685         if (ne(s))
4686            s = s.replaceAll("\\/$", "");
4687         if (isEmpty(s))
4688            rootUrl = null;
4689         else if (s.indexOf("://") == -1)
4690            throw rex("Invalid rootUrl value: ''{0}''.  Must be a valid absolute URL.", value);
4691         else
4692            rootUrl = s;
4693         return this;
4694      }
4695
4696      /**
4697       * Assigns {@link HttpRoutePlanner} instance.
4698       *
4699       * @param routePlanner New property value.
4700       *    <br>Can be <jk>null</jk> (value will not be set, default behavior will be used).
4701       * @return This object.
4702       * @see HttpClientBuilder#setRoutePlanner(HttpRoutePlanner)
4703       */
4704      public Builder routePlanner(HttpRoutePlanner routePlanner) {
4705         httpClientBuilder().setRoutePlanner(routePlanner);
4706         return this;
4707      }
4708
4709      /**
4710       * Assigns {@link SchemePortResolver} instance.
4711       *
4712       * @param schemePortResolver New property value.
4713       *    <br>Can be <jk>null</jk> (value will not be set, default behavior will be used).
4714       * @return This object.
4715       * @see HttpClientBuilder#setSchemePortResolver(SchemePortResolver)
4716       */
4717      public Builder schemePortResolver(SchemePortResolver schemePortResolver) {
4718         httpClientBuilder().setSchemePortResolver(schemePortResolver);
4719         return this;
4720      }
4721
4722      /**
4723       * Serializer.
4724       *
4725       * <p>
4726       * Associates the specified {@link Serializer Serializer} with the HTTP client.
4727       *
4728       * <p>
4729       * The serializer is used to serialize POJOs into the HTTP request body.
4730       *
4731       * <h5 class='section'>Notes:</h5><ul>
4732       *    <li class='note'>When using this method that takes in a class, the serializer can be configured using any of the serializer property setters (e.g. {@link #sortCollections()}) or
4733       *    bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
4734       * </ul>
4735       *
4736       * <h5 class='section'>Example:</h5>
4737       * <p class='bjava'>
4738       *    <jc>// Create a client that uses JSON transport for request bodies.</jc>
4739       *    RestClient <jv>client</jv> = RestClient
4740       *       .<jsm>create</jsm>()
4741       *       .serializer(JsonSerializer.<jk>class</jk>)
4742       *       .sortCollections()  <jc>// Sort any collections being serialized.</jc>
4743       *       .build();
4744       * </p>
4745       *
4746       * @param value
4747       *    The new value for this setting.
4748       *    <br>The default is {@link JsonSerializer}.
4749       * @return This object.
4750       */
4751      @SuppressWarnings("unchecked")
4752      public Builder serializer(Class<? extends Serializer> value) {
4753         return serializers(value);
4754      }
4755
4756      /**
4757       * Serializer.
4758       *
4759       * <p>
4760       * Associates the specified {@link Serializer Serializer} with the HTTP client.
4761       *
4762       * <p>
4763       * The serializer is used to serialize POJOs into the HTTP request body.
4764       *
4765       * <h5 class='section'>Notes:</h5><ul>
4766       *    <li class='note'>When using this method that takes in a pre-instantiated serializer, the serializer property setters (e.g. {@link #sortCollections()}) or
4767       *    bean context property setters (e.g. {@link #swaps(Class...)}) defined
4768       *    on this builder class have no effect.
4769       * </ul>
4770       *
4771       * <h5 class='section'>Example:</h5>
4772       * <p class='bjava'>
4773       *    <jc>// Create a client that uses a predefined JSON serializer request bodies.</jc>
4774       *    RestClient <jv>client</jv> = RestClient
4775       *       .<jsm>create</jsm>()
4776       *       .serializer(JsonSerializer.<jsf>DEFAULT_READABLE</jsf>)
4777       *       .build();
4778       * </p>
4779       *
4780       * @param value
4781       *    The new value for this setting.
4782       *    <br>The default is {@link JsonSerializer}.
4783       *    <br>Cannot be <jk>null</jk>.
4784       * @return This object.
4785       */
4786      public Builder serializer(Serializer value) {
4787         return serializers(value);
4788      }
4789
4790      /**
4791       * Returns the serializer group sub-builder.
4792       *
4793       * @return The serializer group sub-builder.
4794       */
4795      public final SerializerSet.Builder serializers() {
4796         if (serializers == null)
4797            serializers = createSerializers();
4798         return serializers;
4799      }
4800
4801      /**
4802       * Serializers.
4803       *
4804       * <p>
4805       * Associates the specified {@link Serializer Serializers} with the HTTP client.
4806       *
4807       * <p>
4808       * The serializer is used to serialize POJOs into the HTTP request body.
4809       *
4810       * <p>
4811       * The serializer that best matches the <c>Content-Type</c> header will be used to serialize the request body.
4812       * <br>If no <c>Content-Type</c> header is specified, the first serializer in the list will be used.
4813       *
4814       * <h5 class='section'>Notes:</h5><ul>
4815       *    <li class='note'>When using this method that takes in classes, the serializers can be configured using any of the serializer property setters (e.g. {@link #sortCollections()}) or
4816       *    bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
4817       * </ul>
4818       *
4819       * <h5 class='section'>Example:</h5>
4820       * <p class='bjava'>
4821       *    <jc>// Create a client that uses JSON and XML transport for request bodies.</jc>
4822       *    RestClient <jv>client</jv> = RestClient
4823       *       .<jsm>create</jsm>()
4824       *       .serializers(JsonSerializer.<jk>class</jk>, XmlSerializer.<jk>class</jk>)
4825       *       .sortCollections()  <jc>// Sort any collections being serialized.</jc>
4826       *       .build();
4827       * </p>
4828       *
4829       * @param value
4830       *    The new value for this setting.
4831       *    <br>The default is {@link JsonSerializer}.
4832       * @return This object.
4833       */
4834      @SuppressWarnings("unchecked")
4835      public Builder serializers(Class<? extends Serializer>...value) {
4836         assertArgNoNulls("value", value);
4837         serializers().add(value);
4838         return this;
4839      }
4840
4841      /**
4842       * Serializers.
4843       *
4844       * <p>
4845       * Associates the specified {@link Serializer Serializers} with the HTTP client.
4846       *
4847       * <p>
4848       * The serializer is used to serialize POJOs into the HTTP request body.
4849       *
4850       * <p>
4851       * The serializer that best matches the <c>Content-Type</c> header will be used to serialize the request body.
4852       * <br>If no <c>Content-Type</c> header is specified, the first serializer in the list will be used.
4853       *
4854       * <h5 class='section'>Notes:</h5><ul>
4855       *    <li class='note'>When using this method that takes in a pre-instantiated serializers, the serializer property setters (e.g. {@link #sortCollections()}) or
4856       *    bean context property setters (e.g. {@link #swaps(Class...)}) defined
4857       *    on this builder class have no effect.
4858       * </ul>
4859       *
4860       * <h5 class='section'>Example:</h5>
4861       * <p class='bjava'>
4862       *    <jc>// Create a client that uses predefined JSON and XML serializers for request bodies.</jc>
4863       *    RestClient <jv>client</jv> = RestClient
4864       *       .<jsm>create</jsm>()
4865       *       .serializers(JsonSerializer.<jsf>DEFAULT_READABLE</jsf>, XmlSerializer.<jsf>DEFAULT_READABLE</jsf>)
4866       *       .build();
4867       * </p>
4868       *
4869       * @param value
4870       *    The new value for this setting.
4871       *    <br>The default is {@link JsonSerializer}.
4872       * @return This object.
4873       */
4874      public Builder serializers(Serializer...value) {
4875         assertArgNoNulls("value", value);
4876         serializers().add(value);
4877         return this;
4878      }
4879
4880      /**
4881       * Assigns {@link ServiceUnavailableRetryStrategy} instance.
4882       *
4883       * @param serviceUnavailStrategy New property value.
4884       *    <br>Can be <jk>null</jk> (value will not be set, default behavior will be used).
4885       * @return This object.
4886       * @see HttpClientBuilder#setServiceUnavailableRetryStrategy(ServiceUnavailableRetryStrategy)
4887       */
4888      public Builder serviceUnavailableRetryStrategy(ServiceUnavailableRetryStrategy serviceUnavailStrategy) {
4889         httpClientBuilder().setServiceUnavailableRetryStrategy(serviceUnavailStrategy);
4890         return this;
4891      }
4892
4893      /**
4894       * Skip empty form data.
4895       *
4896       * <p>
4897       * When enabled, form data consisting of empty strings will be skipped on requests.
4898       * Note that <jk>null</jk> values are already skipped.
4899       *
4900       * <p>
4901       * The {@link Schema#skipIfEmpty()} annotation overrides this setting.
4902       *
4903       * @return This object.
4904       */
4905      public Builder skipEmptyFormData() {
4906         return skipEmptyFormData(true);
4907      }
4908
4909      /**
4910       * Skip empty form data.
4911       *
4912       * <p>
4913       * When enabled, form data consisting of empty strings will be skipped on requests.
4914       * Note that <jk>null</jk> values are already skipped.
4915       *
4916       * <p>
4917       * The {@link Schema#skipIfEmpty()} annotation overrides this setting.
4918       *
4919       * @param value
4920       *    The new value for this setting.
4921       *    <br>The default is <jk>false</jk>.
4922       * @return This object.
4923       */
4924      public Builder skipEmptyFormData(boolean value) {
4925         skipEmptyFormData = true;
4926         return this;
4927      }
4928
4929      /**
4930       * Skip empty header data.
4931       *
4932       * <p>
4933       * When enabled, headers consisting of empty strings will be skipped on requests.
4934       * Note that <jk>null</jk> values are already skipped.
4935       *
4936       * <p>
4937       * The {@link Schema#skipIfEmpty()} annotation overrides this setting.
4938       *
4939       * @return This object.
4940       */
4941      public Builder skipEmptyHeaderData() {
4942         return skipEmptyHeaderData(true);
4943      }
4944
4945      /**
4946       * Skip empty header data.
4947       *
4948       * <p>
4949       * When enabled, headers consisting of empty strings will be skipped on requests.
4950       * Note that <jk>null</jk> values are already skipped.
4951       *
4952       * <p>
4953       * The {@link Schema#skipIfEmpty()} annotation overrides this setting.
4954       *
4955       * @param value
4956       *    The new value for this setting.
4957       *    <br>The default is <jk>false</jk>.
4958       * @return This object.
4959       */
4960      public Builder skipEmptyHeaderData(boolean value) {
4961         skipEmptyHeaderData = true;
4962         return this;
4963      }
4964
4965      /**
4966       * Skip empty query data.
4967       *
4968       * <p>
4969       * When enabled, query parameters consisting of empty strings will be skipped on requests.
4970       * Note that <jk>null</jk> values are already skipped.
4971       *
4972       * <p>
4973       * The {@link Schema#skipIfEmpty()} annotation overrides this setting.
4974       *
4975       * @return This object.
4976       */
4977      public Builder skipEmptyQueryData() {
4978         return skipEmptyQueryData(true);
4979      }
4980
4981      /**
4982       * Skip empty query data.
4983       *
4984       * <p>
4985       * When enabled, query parameters consisting of empty strings will be skipped on requests.
4986       * Note that <jk>null</jk> values are already skipped.
4987       *
4988       * <p>
4989       * The {@link Schema#skipIfEmpty()} annotation overrides this setting.
4990       *
4991       * @param value
4992       *    The new value for this setting.
4993       *    <br>The default is <jk>false</jk>.
4994       * @return This object.
4995       */
4996      public Builder skipEmptyQueryData(boolean value) {
4997         skipEmptyQueryData = true;
4998         return this;
4999      }
5000
5001      /**
5002       * <i><l>Serializer</l> configuration property:&emsp;</i>  Sort arrays and collections alphabetically.
5003       *
5004       * <p>
5005       * When enabled, copies and sorts the contents of arrays and collections before serializing them.
5006       *
5007       * <p>
5008       * Note that this introduces a performance penalty since it requires copying the existing collection.
5009       *
5010       * <h5 class='section'>Example:</h5>
5011       * <p class='bjava'>
5012       *    <jc>// Create a REST client with JSON serializer that sorts arrays and collections before serialization.</jc>
5013       *    RestClient <jv>client</jv> = RestClient
5014       *       .<jsm>create</jsm>()
5015       *       .json()
5016       *       .sortCollections()
5017       *       .build();
5018       *
5019       *    <jc>// An unsorted array</jc>
5020       *    String[] <jv>array</jv> = {<js>"foo"</js>,<js>"bar"</js>,<js>"baz"</js>}
5021       *
5022       *    <jc>// Request body will contain:  ["bar","baz","foo"]</jc>
5023       *    <jv>client</jv>
5024       *       .post(<js>"http://localhost:10000/foo"</js>, <jv>array</jv>)
5025       *       .run();
5026       * </p>
5027       *
5028       * <h5 class='section'>See Also:</h5><ul>
5029       *    <li class='jm'>{@link org.apache.juneau.serializer.Serializer.Builder#sortCollections()}
5030       * </ul>
5031       *
5032       * @return This object.
5033       */
5034      public Builder sortCollections() {
5035         serializers().forEach(org.apache.juneau.serializer.Serializer.Builder::sortCollections);
5036         return this;
5037      }
5038
5039      /**
5040       * <i><l>Serializer</l> configuration property:&emsp;</i>  Sort maps alphabetically.
5041       *
5042       * <p>
5043       * When enabled, copies and sorts the contents of maps by their keys before serializing them.
5044       *
5045       * <p>
5046       * Note that this introduces a performance penalty.
5047       *
5048       * <h5 class='section'>Example:</h5>
5049       * <p class='bjava'>
5050       *    <jc>// Create a REST client with JSON serializer that sorts maps before serialization.</jc>
5051       *    RestClient <jv>client</jv> = RestClient
5052       *       .<jsm>create</jsm>()
5053       *       .json()
5054       *       .sortMaps()
5055       *       .build();
5056       *
5057       *    <jc>// An unsorted map.</jc>
5058       *    AMap <jv>map</jv> = AMap.<jsm>of</jsm>(<js>"foo"</js>,1,<js>"bar"</js>,2,<js>"baz"</js>,3);
5059       *
5060       *    <jc>// Request body will contain:  {"bar":2,"baz":3,"foo":1}</jc>
5061       *    <jv>client</jv>
5062       *       .post(<js>"http://localhost:10000/foo"</js>, <jv>map</jv>)
5063       *       .run();
5064       * </p>
5065       *
5066       * <h5 class='section'>See Also:</h5><ul>
5067       *    <li class='jm'>{@link org.apache.juneau.serializer.Serializer.Builder#sortMaps()}
5068       * </ul>
5069       *
5070       * @return This object.
5071       */
5072      public Builder sortMaps() {
5073         serializers().forEach(org.apache.juneau.serializer.Serializer.Builder::sortMaps);
5074         return this;
5075      }
5076
5077      @Override /* Overridden from Builder */
5078      public Builder sortProperties() {
5079         super.sortProperties();
5080         return this;
5081      }
5082
5083      @Override /* Overridden from Builder */
5084      public Builder sortProperties(java.lang.Class<?>...on) {
5085         super.sortProperties(on);
5086         return this;
5087      }
5088
5089      /**
5090       * <i><l>WriterSerializer</l> configuration property:&emsp;</i>  Quote character.
5091       *
5092       * <p>
5093       * Specifies to use single quotes for quoting attributes and values.
5094       *
5095       * <h5 class='section'>Notes:</h5><ul>
5096       *    <li class='note'>This setting does not apply to the RDF serializers.
5097       * </ul>
5098       *
5099       * <h5 class='section'>Example:</h5>
5100       * <p class='bjava'>
5101       *    <jc>// Create a REST client with JSON serializer that uses single quotes.</jc>
5102       *    RestClient <jv>client</jv> = RestClient
5103       *       .<jsm>create</jsm>()
5104       *       .json()
5105       *       .sq()
5106       *       .build();
5107       *
5108       *    <jc>// A bean with a single property</jc>
5109       *    <jk>public class</jk> MyBean {
5110       *       <jk>public</jk> String <jf>foo</jf> = <js>"bar"</js>;
5111       *    }
5112       *
5113       *    <jc>// Request body will contain:  {'foo':'bar'}</jc>
5114       *    <jv>client</jv>
5115       *       .post(<js>"http://localhost:10000/foo"</js>, <jk>new</jk> MyBean())
5116       *       .run();
5117       * </p>
5118       *
5119       * <h5 class='section'>See Also:</h5><ul>
5120       *    <li class='jm'>{@link org.apache.juneau.serializer.WriterSerializer.Builder#quoteChar(char)}
5121       * </ul>
5122       *
5123       * @return This object.
5124       */
5125      public Builder sq() {
5126         serializers().forEachWS(org.apache.juneau.serializer.WriterSerializer.Builder::sq);
5127         return this;
5128      }
5129
5130      /**
5131       * Assigns {@link SSLContext} instance.
5132       *
5133       * <h5 class='section'>Notes:</h5><ul>
5134       *    <li class='note'>This value can be overridden by the {@link #connectionManager(HttpClientConnectionManager)}
5135       *    and the {@link #sslSocketFactory(LayeredConnectionSocketFactory)} methods.
5136       * </ul>
5137       *
5138       * @param sslContext New property value.
5139       *    <br>Can be <jk>null</jk> (value will not be set, default behavior will be used).
5140       * @return This object.
5141       * @see HttpClientBuilder#setSSLContext(SSLContext)
5142       */
5143      public Builder sslContext(SSLContext sslContext) {
5144         httpClientBuilder().setSSLContext(sslContext);
5145         return this;
5146      }
5147
5148      /**
5149       * Assigns {@link javax.net.ssl.HostnameVerifier} instance.
5150       *
5151       * <h5 class='section'>Notes:</h5><ul>
5152       *    <li class='note'>This value can be overridden by the {@link #connectionManager(HttpClientConnectionManager)}
5153       *       and the {@link #sslSocketFactory(LayeredConnectionSocketFactory)} methods.
5154       * </ul>
5155       *
5156       * @param hostnameVerifier New property value.
5157       *    <br>Can be <jk>null</jk> (value will not be set, default behavior will be used).
5158       * @return This object.
5159       * @see HttpClientBuilder#setSSLHostnameVerifier(HostnameVerifier)
5160       */
5161      public Builder sslHostnameVerifier(HostnameVerifier hostnameVerifier) {
5162         httpClientBuilder().setSSLHostnameVerifier(hostnameVerifier);
5163         return this;
5164      }
5165
5166      /**
5167       * Assigns {@link LayeredConnectionSocketFactory} instance.
5168       *
5169       * <h5 class='section'>Notes:</h5><ul>
5170       *    <li class='note'>This value can be overridden by the {@link #connectionManager(HttpClientConnectionManager)} method.
5171       * </ul>
5172       *
5173       * @param sslSocketFactory New property value.
5174       *    <br>Can be <jk>null</jk> (value will not be set, default behavior will be used).
5175       * @return This object.
5176       * @see HttpClientBuilder#setSSLSocketFactory(LayeredConnectionSocketFactory)
5177       */
5178      public Builder sslSocketFactory(LayeredConnectionSocketFactory sslSocketFactory) {
5179         httpClientBuilder().setSSLSocketFactory(sslSocketFactory);
5180         return this;
5181      }
5182
5183      @Override /* Overridden from Builder */
5184      public Builder stopClass(Class<?> on, Class<?> value) {
5185         super.stopClass(on, value);
5186         return this;
5187      }
5188
5189      /**
5190       * <i><l>Parser</l> configuration property:&emsp;</i>  Strict mode.
5191       *
5192       * <p>
5193       * When enabled, strict mode for the parser is enabled.
5194       *
5195       * <p>
5196       * Strict mode can mean different things for different parsers.
5197       *
5198       * <table class='styled'>
5199       *    <tr><th>Parser class</th><th>Strict behavior</th></tr>
5200       *    <tr>
5201       *       <td>All reader-based parsers</td>
5202       *       <td>
5203       *          When enabled, throws {@link ParseException ParseExceptions} on malformed charset input.
5204       *          Otherwise, malformed input is ignored.
5205       *       </td>
5206       *    </tr>
5207       *    <tr>
5208       *       <td>{@link JsonParser}</td>
5209       *       <td>
5210       *          When enabled, throws exceptions on the following invalid JSON syntax:
5211       *          <ul>
5212       *             <li>Unquoted attributes.
5213       *             <li>Missing attribute values.
5214       *             <li>Concatenated strings.
5215       *             <li>Javascript comments.
5216       *             <li>Numbers and booleans when Strings are expected.
5217       *             <li>Numbers valid in Java but not JSON (e.g. octal notation, etc...)
5218       *          </ul>
5219       *       </td>
5220       *    </tr>
5221       * </table>
5222       *
5223       * <h5 class='section'>Example:</h5>
5224       * <p class='bjava'>
5225       *    <jc>// Create a REST client with JSON parser using strict mode.</jc>
5226       *    RestClient <jv>client</jv> = RestClient
5227       *       .<jsm>create</jsm>()
5228       *       .json()
5229       *       .strict()
5230       *       .build();
5231       *
5232       *    <jc>// Try to parse some bad JSON.</jc>
5233       *    <jk>try</jk> {
5234       *       <jv>client</jv>
5235       *          .get(<js>"/pathToBadJson"</js>)
5236       *          .run()
5237       *          .getContent().as(Object.<jk>class</jk>);  <jc>// Try to parse it.</jc>
5238       *    } <jk>catch</jk> (RestCallException <jv>e</jv>) {
5239       *       <jc>// Handle exception.</jc>
5240       *    }
5241       * </p>
5242       *
5243       * <h5 class='section'>See Also:</h5><ul>
5244       *    <li class='jm'>{@link org.apache.juneau.parser.Parser.Builder#strict()}
5245       * </ul>
5246       *
5247       * @return This object.
5248       */
5249      public Builder strict() {
5250         parsers().forEach(org.apache.juneau.parser.Parser.Builder::strict);
5251         return this;
5252      }
5253
5254      @Override /* Overridden from Builder */
5255      public <T,S> Builder swap(Class<T> normalClass, Class<S> swappedClass, ThrowingFunction<T,S> swapFunction) {
5256         super.swap(normalClass, swappedClass, swapFunction);
5257         return this;
5258      }
5259
5260      @Override /* Overridden from Builder */
5261      public <T,S> Builder swap(Class<T> normalClass, Class<S> swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> unswapFunction) {
5262         super.swap(normalClass, swappedClass, swapFunction, unswapFunction);
5263         return this;
5264      }
5265
5266      @Override /* Overridden from Builder */
5267      public Builder swaps(Class<?>...values) {
5268         super.swaps(values);
5269         return this;
5270      }
5271
5272      @Override /* Overridden from Builder */
5273      public Builder swaps(Object...values) {
5274         super.swaps(values);
5275         return this;
5276      }
5277
5278      /**
5279       * Assigns {@link AuthenticationStrategy} instance for target host authentication.
5280       *
5281       * @param targetAuthStrategy New property value.
5282       *    <br>Can be <jk>null</jk> (value will not be set, default behavior will be used).
5283       * @return This object.
5284       * @see HttpClientBuilder#setTargetAuthenticationStrategy(AuthenticationStrategy)
5285       */
5286      public Builder targetAuthenticationStrategy(AuthenticationStrategy targetAuthStrategy) {
5287         httpClientBuilder().setTargetAuthenticationStrategy(targetAuthStrategy);
5288         return this;
5289      }
5290
5291      @Override /* Overridden from Builder */
5292      public Builder timeZone(TimeZone value) {
5293         super.timeZone(value);
5294         return this;
5295      }
5296
5297      /**
5298       * <i><l>Serializer</l> configuration property:&emsp;</i>  Trim empty lists and arrays.
5299       *
5300       * <p>
5301       * When enabled, empty lists and arrays will not be serialized.
5302       *
5303       * <p>
5304       * Note that enabling this setting has the following effects on parsing:
5305       * <ul class='spaced-list'>
5306       *    <li>
5307       *       Map entries with empty list values will be lost.
5308       *    <li>
5309       *       Bean properties with empty list values will not be set.
5310       * </ul>
5311       *
5312       * <h5 class='section'>Example:</h5>
5313       * <p class='bjava'>
5314       *    <jc>// Create a serializer that skips empty arrays and collections.</jc>
5315       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
5316       *       .<jsm>create</jsm>()
5317       *       .trimEmptyCollections()
5318       *       .build();
5319       *
5320       *    <jc>// A bean with a field with an empty array.</jc>
5321       *    <jk>public class</jk> MyBean {
5322       *       <jk>public</jk> String[] <jf>foo</jf> = {};
5323       *    }
5324       *
5325       *    <jc>// Request body will contain:  {}</jc>
5326       *    <jv>client</jv>
5327       *       .post(<js>"http://localhost:10000/foo"</js>, <jk>new</jk> MyBean())
5328       *       .run();
5329       * </p>
5330       *
5331       * <h5 class='section'>See Also:</h5><ul>
5332       *    <li class='jm'>{@link org.apache.juneau.serializer.Serializer.Builder#trimEmptyCollections()}
5333       * </ul>
5334       *
5335       * @return This object.
5336       */
5337      public Builder trimEmptyCollections() {
5338         serializers().forEach(org.apache.juneau.serializer.Serializer.Builder::trimEmptyCollections);
5339         return this;
5340      }
5341
5342      /**
5343       * <i><l>Serializer</l> configuration property:&emsp;</i>  Trim empty maps.
5344       *
5345       * <p>
5346       * When enabled, empty map values will not be serialized to the output.
5347       *
5348       * <p>
5349       * Note that enabling this setting has the following effects on parsing:
5350       * <ul class='spaced-list'>
5351       *    <li>
5352       *       Bean properties with empty map values will not be set.
5353       * </ul>
5354       *
5355       * <h5 class='section'>Example:</h5>
5356       * <p class='bjava'>
5357       *    <jc>// Create a REST client with JSON serializer that skips empty maps.</jc>
5358       *    RestClient <jv>client</jv> = RestClient
5359       *       .<jsm>create</jsm>()
5360       *       .json()
5361       *       .trimEmptyMaps()
5362       *       .build();
5363       *
5364       *    <jc>// A bean with a field with an empty map.</jc>
5365       *    <jk>public class</jk> MyBean {
5366       *       <jk>public</jk> AMap <jf>foo</jf> = AMap.<jsm>of</jsm>();
5367       *    }
5368       *
5369       *    <jc>// Request body will contain:  {}</jc>
5370       *    <jv>client</jv>
5371       *       .post(<js>"http://localhost:10000/foo"</js>, <jk>new</jk> MyBean())
5372       *       .run();
5373       * </p>
5374       *
5375       * <h5 class='section'>See Also:</h5><ul>
5376       *    <li class='jm'>{@link org.apache.juneau.serializer.Serializer.Builder#trimEmptyMaps()}
5377       * </ul>
5378       *
5379       * @return This object.
5380       */
5381      public Builder trimEmptyMaps() {
5382         serializers().forEach(org.apache.juneau.serializer.Serializer.Builder::trimEmptyMaps);
5383         return this;
5384      }
5385
5386      /**
5387       * <i><l>Parser</l> configuration property:&emsp;</i>  Trim parsed strings.
5388       *
5389       * <p>
5390       * When enabled, string values will be trimmed of whitespace using {@link String#trim()} before being added to
5391       * the POJO.
5392       *
5393       * <h5 class='section'>Example:</h5>
5394       * <p class='bjava'>
5395       *    <jc>// Create a REST client with JSON parser with trim-strings enabled.</jc>
5396       *    RestClient <jv>client</jv> = RestClient
5397       *       .<jsm>create</jsm>()
5398       *       .json()
5399       *       .trimStringsOnRead()
5400       *       .build();
5401       *
5402       *    <jc>// Try to parse JSON containing {" foo ":" bar "}.</jc>
5403       *    Map&lt;String,String&gt; <jv>map</jv> = <jv>client</jv>
5404       *       .get(<js>"/pathToJson"</js>)
5405       *       .run()
5406       *       .getContent().as(HashMap.<jk>class</jk>, String.<jk>class</jk>, String.<jk>class</jk>);
5407       *
5408       *    <jc>// Make sure strings are trimmed.</jc>
5409       *    <jsm>assertEquals</jsm>(<js>"bar"</js>, <jv>map</jv>.get(<js>"foo"</js>));
5410       * </p>
5411       *
5412       * <h5 class='section'>See Also:</h5><ul>
5413       *    <li class='jm'>{@link org.apache.juneau.parser.Parser.Builder#trimStrings()}
5414       * </ul>
5415       *
5416       * @return This object.
5417       */
5418      public Builder trimStringsOnRead() {
5419         parsers().forEach(org.apache.juneau.parser.Parser.Builder::trimStrings);
5420         return this;
5421      }
5422
5423      /**
5424       * <i><l>Serializer</l> configuration property:&emsp;</i>  Trim strings.
5425       *
5426       * <p>
5427       * When enabled, string values will be trimmed of whitespace using {@link String#trim()} before being serialized.
5428       *
5429       * <h5 class='section'>Example:</h5>
5430       * <p class='bjava'>
5431       *    <jc>// Create a REST client with JSON serializer that trims strings before serialization.</jc>
5432       *    RestClient <jv>client</jv> = RestClient
5433       *       .<jsm>create</jsm>()
5434       *       .json()
5435       *       .trimStrings()
5436       *       .build();
5437       *
5438       * <jc>// A map with space-padded keys/values</jc>
5439       *    AMap <jv>map</jv> = AMap.<jsm>of</jsm>(<js>" foo "</js>, <js>" bar "</js>);
5440       *
5441       *    <jc>// Request body will contain:  {"foo":"bar"}</jc>
5442       *    <jv>client</jv>
5443       *       .post(<js>"http://localhost:10000/foo"</js>, <jv>map</jv>)
5444       *       .run();
5445       * </p>
5446       *
5447       * <h5 class='section'>See Also:</h5><ul>
5448       *    <li class='jm'>{@link org.apache.juneau.serializer.Serializer.Builder#trimStrings()}
5449       * </ul>
5450       *
5451       * @return This object.
5452       */
5453      public Builder trimStringsOnWrite() {
5454         serializers().forEach(org.apache.juneau.serializer.Serializer.Builder::trimStrings);
5455         return this;
5456      }
5457
5458      @Override /* Overridden from Builder */
5459      public Builder type(Class<? extends org.apache.juneau.Context> value) {
5460         super.type(value);
5461         return this;
5462      }
5463
5464      @Override /* Overridden from Builder */
5465      public Builder typeName(Class<?> on, String value) {
5466         super.typeName(on, value);
5467         return this;
5468      }
5469
5470      @Override /* Overridden from Builder */
5471      public Builder typePropertyName(Class<?> on, String value) {
5472         super.typePropertyName(on, value);
5473         return this;
5474      }
5475
5476      @Override /* Overridden from Builder */
5477      public Builder typePropertyName(String value) {
5478         super.typePropertyName(value);
5479         return this;
5480      }
5481
5482      /**
5483       * Convenience method for specifying all available transmission types.
5484       *
5485       * <p>
5486       *    All basic Juneau serializers will be used to serialize POJOs to request bodies unless overridden per request via {@link RestRequest#serializer(Serializer)}.
5487       *    <ul>
5488       *       <li>The serializers can be configured using any of the serializer property setters (e.g. {@link #sortCollections()}) or
5489       *          bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
5490       *    </ul>
5491       * <p>
5492       *    All basic Juneau parsers will be used to parse POJOs from response bodies unless overridden per request via {@link RestRequest#parser(Parser)}.
5493       *    <ul>
5494       *       <li>The parsers can be configured using any of the parser property setters (e.g. {@link #strict()}) or
5495       *          bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
5496       *    </ul>
5497       * <p>
5498       *    <c>Accept</c> request header must be set via {@link #headers()}, or per-request
5499       *       via {@link RestRequest#header(Header)} in order for the correct parser to be selected.
5500       * <p>
5501       *    <c>Content-Type</c> request header must be set via {@link #headers()},
5502       *       or per-request via {@link RestRequest#header(Header)} in order for the correct serializer to be selected.
5503       * <p>
5504       *    Similar to calling <c>json().json5().html().xml().uon().urlEnc().openApi().msgPack().plainText()</c>.
5505       *
5506       * <h5 class='section'>Example:</h5>
5507       * <p class='bjava'>
5508       *    <jc>// Construct a client that uses universal marshalling.</jc>
5509       *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().universal().build();
5510       * </p>
5511       *
5512       * @return This object.
5513       */
5514      @SuppressWarnings("unchecked")
5515      public Builder universal() {
5516         // @formatter:off
5517         return
5518            serializers(
5519               JsonSerializer.class,
5520               Json5Serializer.class,
5521               HtmlSerializer.class,
5522               XmlSerializer.class,
5523               UonSerializer.class,
5524               UrlEncodingSerializer.class,
5525               OpenApiSerializer.class,
5526               MsgPackSerializer.class,
5527               PlainTextSerializer.class
5528            )
5529            .parsers(
5530               JsonParser.class,
5531               Json5Parser.class,
5532               XmlParser.class,
5533               HtmlParser.class,
5534               UonParser.class,
5535               UrlEncodingParser.class,
5536               OpenApiParser.class,
5537               MsgPackParser.class,
5538               PlainTextParser.class
5539            );
5540         // @formatter:on
5541      }
5542
5543      /**
5544       * Convenience method for specifying UON as the marshalling transmission media type.
5545       *
5546       * <p>
5547       * UON is Url-Encoding Object notation that is equivalent to JSON but suitable for transmission as URL-encoded
5548       * query and form post values.
5549       *
5550       * <p>
5551       *    {@link UonSerializer} will be used to serialize POJOs to request bodies unless overridden per request via {@link RestRequest#serializer(Serializer)}.
5552       *    <ul>
5553       *       <li>The serializer can be configured using any of the serializer property setters (e.g. {@link #sortCollections()}) or
5554       *          bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
5555       *    </ul>
5556       * <p>
5557       *    {@link UonParser} will be used to parse POJOs from response bodies unless overridden per request via {@link RestRequest#parser(Parser)}.
5558       *    <ul>
5559       *       <li>The parser can be configured using any of the parser property setters (e.g. {@link #strict()}) or
5560       *          bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
5561       *    </ul>
5562       * <p>
5563       *    <c>Accept</c> request header will be set to <js>"text/uon"</js> unless overridden
5564       *       via {@link #headers()}, or per-request via {@link RestRequest#header(Header)}.
5565       * <p>
5566       *    <c>Content-Type</c> request header will be set to <js>"text/uon"</js> unless overridden
5567       *       via {@link #headers()}, or per-request via {@link RestRequest#header(Header)}.
5568       * <p>
5569       *    Can be combined with other marshaller setters such as {@link #json()} to provide support for multiple languages.
5570       *    <ul>
5571       *       <li>When multiple languages are supported, the <c>Accept</c> and <c>Content-Type</c> headers control which marshallers are used, or uses the
5572       *       last-enabled language if the headers are not set.
5573       *    </ul>
5574       * <p>
5575       *    Identical to calling <c>serializer(UonSerializer.<jk>class</jk>).parser(UonParser.<jk>class</jk>)</c>.
5576       *
5577       * <h5 class='section'>Example:</h5>
5578       * <p class='bjava'>
5579       *    <jc>// Construct a client that uses UON marshalling.</jc>
5580       *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().uon().build();
5581       * </p>
5582       *
5583       * @return This object.
5584       */
5585      public Builder uon() {
5586         return serializer(UonSerializer.class).parser(UonParser.class);
5587      }
5588
5589      /**
5590       * <i><l>Serializer</l> configuration property:&emsp;</i>  URI context bean.
5591       *
5592       * <p>
5593       * Bean used for resolution of URIs to absolute or root-relative form.
5594       *
5595       * <h5 class='section'>Example:</h5>
5596       * <p class='bjava'>
5597       *    <jc>// Our URI contextual information.</jc>
5598       *    String <jv>authority</jv> = <js>"http://localhost:10000"</js>;
5599       *    String <jv>contextRoot</jv> = <js>"/myContext"</js>;
5600       *    String <jv>servletPath</jv> = <js>"/myServlet"</js>;
5601       *    String <jv>pathInfo</jv> = <js>"/foo"</js>;
5602       *
5603       *    <jc>// Create a UriContext object.</jc>
5604       *    UriContext <jv>uriContext</jv> = <jk>new</jk> UriContext(<jv>authority</jv>, <jv>contextRoot</jv>, <jv>servletPath</jv>, <jv>pathInfo</jv>);
5605       *
5606       *    <jc>// Create a REST client with JSON serializer and associate our context.</jc>
5607       *    RestClient <jv>client</jv> = RestClient
5608       *       .<jsm>create</jsm>()
5609       *       .json()
5610       *       .uriContext(<jv>uriContext</jv>)
5611       *       .uriRelativity(<jsf>RESOURCE</jsf>)  <jc>// Assume relative paths are relative to servlet.</jc>
5612       *       .uriResolution(<jsf>ABSOLUTE</jsf>)  <jc>// Serialize URIs as absolute paths.</jc>
5613       *       .build();
5614       *
5615       *    <jc>// A relative URI</jc>
5616       *    URI <jv>uri</jv> = <jk>new</jk> URI(<js>"bar"</js>);
5617       *
5618       *    <jc>// Request body will contain:  "http://localhost:10000/myContext/myServlet/foo/bar"</jc>
5619       *    <jv>client</jv>
5620       *       .post(<js>"http://localhost:10000/foo"</js>, <jv>uri</jv>)
5621       *       .run();
5622       * </p>
5623       *
5624       * <h5 class='section'>See Also:</h5><ul>
5625       *    <li class='jm'>{@link org.apache.juneau.serializer.Serializer.Builder#uriContext(UriContext)}
5626       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/MarshallingUris">URIs</a>
5627       * </ul>
5628       *
5629       * @param value The new value for this property.
5630       *    <br>Cannot be <jk>null</jk>.
5631       * @return This object.
5632       */
5633      public Builder uriContext(UriContext value) {
5634         serializers().forEach(x -> x.uriContext(assertArgNotNull("value", value)));
5635         return this;
5636      }
5637
5638      /**
5639       * <i><l>Serializer</l> configuration property:&emsp;</i>  URI relativity.
5640       *
5641       * <p>
5642       * Defines what relative URIs are relative to when serializing any of the following:
5643       * <ul>
5644       *    <li>{@link java.net.URI}
5645       *    <li>{@link java.net.URL}
5646       *    <li>Properties and classes annotated with {@link Uri @Uri}
5647       * </ul>
5648       *
5649       * <p>
5650       * See {@link #uriContext(UriContext)} for examples.
5651       *
5652       * <ul class='values javatree'>
5653       *    <li class='jf'>{@link org.apache.juneau.UriRelativity#RESOURCE}
5654       *       - Relative URIs should be considered relative to the servlet URI.
5655       *    <li class='jf'>{@link org.apache.juneau.UriRelativity#PATH_INFO}
5656       *       - Relative URIs should be considered relative to the request URI.
5657       * </ul>
5658       *
5659       * <h5 class='section'>See Also:</h5><ul>
5660       *    <li class='jm'>{@link org.apache.juneau.serializer.Serializer.Builder#uriRelativity(UriRelativity)}
5661       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/MarshallingUris">URIs</a>
5662       * </ul>
5663       *
5664       * @param value
5665       *    The new value for this property.
5666       *    <br>The default is {@link UriRelativity#RESOURCE}
5667       *    <br>Cannot be <jk>null</jk>.
5668       * @return This object.
5669       */
5670      public Builder uriRelativity(UriRelativity value) {
5671         serializers().forEach(x -> x.uriRelativity(assertArgNotNull("value", value)));
5672         return this;
5673      }
5674
5675      /**
5676       * <i><l>Serializer</l> configuration property:&emsp;</i>  URI resolution.
5677       *
5678       * <p>
5679       * Defines the resolution level for URIs when serializing any of the following:
5680       * <ul>
5681       *    <li>{@link java.net.URI}
5682       *    <li>{@link java.net.URL}
5683       *    <li>Properties and classes annotated with {@link Uri @Uri}
5684       * </ul>
5685       *
5686       * <p>
5687       * See {@link #uriContext(UriContext)} for examples.
5688       *
5689       * <ul class='values'>
5690       *    <li class='jf'>{@link UriResolution#ABSOLUTE}
5691       *       - Resolve to an absolute URI (e.g. <js>"http://host:port/context-root/servlet-path/path-info"</js>).
5692       *    <li class='jf'>{@link UriResolution#ROOT_RELATIVE}
5693       *       - Resolve to a root-relative URI (e.g. <js>"/context-root/servlet-path/path-info"</js>).
5694       *    <li class='jf'>{@link UriResolution#NONE}
5695       *       - Don't do any URI resolution.
5696       * </ul>
5697       *
5698       * <h5 class='section'>See Also:</h5><ul>
5699       *    <li class='jm'>{@link org.apache.juneau.serializer.Serializer.Builder#uriResolution(UriResolution)}
5700       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/MarshallingUris">URIs</a>
5701       * </ul>
5702       *
5703       * @param value
5704       *    The new value for this property.
5705       *    <br>The default is {@link UriResolution#NONE}
5706       *    <br>Cannot be <jk>null</jk>.
5707       * @return This object.
5708       */
5709      public Builder uriResolution(UriResolution value) {
5710         serializers().forEach(x -> x.uriResolution(assertArgNotNull("value", value)));
5711         return this;
5712      }
5713
5714      /**
5715       * Convenience method for specifying URL-Encoding as the marshalling transmission media type.
5716       *
5717       * <p>
5718       *    {@link UrlEncodingSerializer} will be used to serialize POJOs to request bodies unless overridden per request via {@link RestRequest#serializer(Serializer)}.
5719       *    <ul>
5720       *       <li>The serializer can be configured using any of the serializer property setters (e.g. {@link #sortCollections()}) or
5721       *          bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
5722       *       <li>This serializer is NOT used when using the {@link RestRequest#formData(String, Object)} (and related) methods for constructing
5723       *          the request body.  Instead, the part serializer specified via {@link #partSerializer(Class)} is used.
5724       *    </ul>
5725       * <p>
5726       *    {@link UrlEncodingParser} will be used to parse POJOs from response bodies unless overridden per request via {@link RestRequest#parser(Parser)}.
5727       *    <ul>
5728       *       <li>The parser can be configured using any of the parser property setters (e.g. {@link #strict()}) or
5729       *          bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
5730       *    </ul>
5731       * <p>
5732       *    <c>Accept</c> request header will be set to <js>"application/x-www-form-urlencoded"</js> unless overridden
5733       *       via {@link #headers()}, or per-request via {@link RestRequest#header(Header)}.
5734       * <p>
5735       *    <c>Content-Type</c> request header will be set to <js>"application/x-www-form-urlencoded"</js> unless overridden
5736       *       via {@link #headers()}, or per-request via {@link RestRequest#header(Header)}.
5737       * <p>
5738       *    Can be combined with other marshaller setters such as {@link #json()} to provide support for multiple languages.
5739       *    <ul>
5740       *       <li>When multiple languages are supported, the <c>Accept</c> and <c>Content-Type</c> headers control which marshallers are used, or uses the
5741       *       last-enabled language if the headers are not set.
5742       *    </ul>
5743       * <p>
5744       *    Identical to calling <c>serializer(UrlEncodingSerializer.<jk>class</jk>).parser(UrlEncodingParser.<jk>class</jk>)</c>.
5745       *
5746       * <h5 class='section'>Example:</h5>
5747       * <p class='bjava'>
5748       *    <jc>// Construct a client that uses URL-Encoded marshalling.</jc>
5749       *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().urlEnc().build();
5750       * </p>
5751       *
5752       * @return This object.
5753       */
5754      public Builder urlEnc() {
5755         return serializer(UrlEncodingSerializer.class).parser(UrlEncodingParser.class);
5756      }
5757
5758      /**
5759       * Returns the URL-encoding serializer sub-builder.
5760       *
5761       * @return The URL-encoding serializer sub-builder.
5762       */
5763      public final UrlEncodingSerializer.Builder urlEncodingSerializer() {
5764         if (urlEncodingSerializer == null)
5765            urlEncodingSerializer = createUrlEncodingSerializer();
5766         return urlEncodingSerializer;
5767      }
5768
5769      @Override /* Overridden from Builder */
5770      public Builder useEnumNames() {
5771         super.useEnumNames();
5772         return this;
5773      }
5774
5775      @Override /* Overridden from Builder */
5776      public Builder useJavaBeanIntrospector() {
5777         super.useJavaBeanIntrospector();
5778         return this;
5779      }
5780
5781      /**
5782       * Assigns {@link UserTokenHandler} instance.
5783       *
5784       * <h5 class='section'>Notes:</h5><ul>
5785       *    <li class='note'>This value can be overridden by the {@link #disableConnectionState()} method.
5786       * </ul>
5787       *
5788       * @param userTokenHandler New property value.
5789       *    <br>Can be <jk>null</jk> (value will not be set, default behavior will be used).
5790       * @return This object.
5791       * @see HttpClientBuilder#setUserTokenHandler(UserTokenHandler)
5792       */
5793      public Builder userTokenHandler(UserTokenHandler userTokenHandler) {
5794         httpClientBuilder().setUserTokenHandler(userTokenHandler);
5795         return this;
5796      }
5797
5798      /**
5799       * Use system properties when creating and configuring default implementations.
5800       *
5801       * @return This object.
5802       * @see HttpClientBuilder#useSystemProperties()
5803       */
5804      public Builder useSystemProperties() {
5805         httpClientBuilder().useSystemProperties();
5806         return this;
5807      }
5808
5809      /**
5810       * <i><l>WriterSerializer</l> configuration property:&emsp;</i>  Use whitespace.
5811       *
5812       * <p>
5813       * When enabled, whitespace is added to the output to improve readability.
5814       *
5815       * <h5 class='section'>Example:</h5>
5816       * <p class='bjava'>
5817       *    <jc>// Create a REST client with JSON serializer with whitespace enabled.</jc>
5818       *    RestClient <jv>client</jv> = RestClient
5819       *       .<jsm>create</jsm>()
5820       *       .json()
5821       *       .useWhitespace()
5822       *       .build();
5823       *
5824       *    <jc>// A bean with a single property</jc>
5825       *    <jk>public class</jk> MyBean {
5826       *       <jk>public</jk> String <jf>foo</jf> = <js>"bar"</js>;
5827       *    }
5828       *
5829       *    <jc>// Request body will contain:  {\n\t"foo": "bar"\n\}\n</jc>
5830       *    <jv>client</jv>
5831       *       .post(<js>"http://localhost:10000/foo"</js>, <jk>new</jk> MyBean())
5832       *       .run();
5833       * </p>
5834       *
5835       * <h5 class='section'>See Also:</h5><ul>
5836       *    <li class='jm'>{@link org.apache.juneau.serializer.WriterSerializer.Builder#useWhitespace()}
5837       * </ul>
5838       * @return This object.
5839       */
5840      public Builder useWhitespace() {
5841         serializers().forEachWS(org.apache.juneau.serializer.WriterSerializer.Builder::useWhitespace);
5842         return this;
5843      }
5844
5845      /**
5846       * <i><l>WriterSerializer</l> configuration property:&emsp;</i>  Use whitespace.
5847       *
5848       * <p>
5849       * When enabled, whitespace is added to the output to improve readability.
5850       *
5851       * <h5 class='section'>Example:</h5>
5852       * <p class='bjava'>
5853       *    <jc>// Create a REST client with JSON serializer with whitespace enabled.</jc>
5854       *    RestClient <jv>client</jv> = RestClient
5855       *       .<jsm>create</jsm>()
5856       *       .json()
5857       *       .ws()
5858       *       .build();
5859       *
5860       *    <jc>// A bean with a single property</jc>
5861       *    <jk>public class</jk> MyBean {
5862       *       <jk>public</jk> String <jf>foo</jf> = <js>"bar"</js>;
5863       *    }
5864       *
5865       *    <jc>// Request body will contain:  {\n\t"foo": "bar"\n\}\n</jc>
5866       *    <jv>client</jv>
5867       *       .post(<js>"http://localhost:10000/foo"</js>, <jk>new</jk> MyBean())
5868       *       .run();
5869       * </p>
5870       *
5871       * <h5 class='section'>See Also:</h5><ul>
5872       *    <li class='jm'>{@link org.apache.juneau.serializer.WriterSerializer.Builder#useWhitespace()}
5873       * </ul>
5874       *
5875       * @return This object.
5876       */
5877      public Builder ws() {
5878         serializers().forEachWS(org.apache.juneau.serializer.WriterSerializer.Builder::ws);
5879         return this;
5880      }
5881
5882      /**
5883       * Convenience method for specifying XML as the marshalling transmission media type.
5884       *
5885       * <p>
5886       * {@link XmlSerializer} will be used to serialize POJOs to request bodies unless overridden per request via {@link RestRequest#serializer(Serializer)}.
5887       *    <ul>
5888       *       <li>The serializer can be configured using any of the serializer property setters (e.g. {@link #sortCollections()}) or
5889       *          bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
5890       *    </ul>
5891       * <p>
5892       *    {@link XmlParser} will be used to parse POJOs from response bodies unless overridden per request via {@link RestRequest#parser(Parser)}.
5893       *    <ul>
5894       *       <li>The parser can be configured using any of the parser property setters (e.g. {@link #strict()}) or
5895       *          bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
5896       *    </ul>
5897       * <p>
5898       *    <c>Accept</c> request header will be set to <js>"text/xml"</js> unless overridden
5899       *       via {@link #headers()}, or per-request via {@link RestRequest#header(Header)}.
5900       * <p>
5901       *    <c>Content-Type</c> request header will be set to <js>"text/xml"</js> unless overridden
5902       *       via {@link #headers()}, or per-request via {@link RestRequest#header(Header)}.
5903       * <p>
5904       *    Can be combined with other marshaller setters such as {@link #json()} to provide support for multiple languages.
5905       *    <ul>
5906       *       <li>When multiple languages are supported, the <c>Accept</c> and <c>Content-Type</c> headers control which marshallers are used, or uses the
5907       *       last-enabled language if the headers are not set.
5908       *    </ul>
5909       * <p>
5910       *    Identical to calling <c>serializer(XmlSerializer.<jk>class</jk>).parser(XmlParser.<jk>class</jk>)</c>.
5911       *
5912       * <h5 class='section'>Example:</h5>
5913       * <p class='bjava'>
5914       *    <jc>// Construct a client that uses XML marshalling.</jc>
5915       *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().xml().build();
5916       * </p>
5917       *
5918       * @return This object.
5919       */
5920      public Builder xml() {
5921         return serializer(XmlSerializer.class).parser(XmlParser.class);
5922      }
5923
5924      /**
5925       * Creates the creator for the rest call handler.
5926       *
5927       * <p>
5928       * Subclasses can override this method to provide their own implementation.
5929       *
5930       * <p>
5931       * The default behavior creates a bean creator initialized to return a {@link BasicRestCallHandler}.
5932       *
5933       * @return The creator for the rest call handler.
5934       * @see #callHandler()
5935       */
5936      protected BeanCreator<RestCallHandler> createCallHandler() {
5937         return beanStore.createBean(RestCallHandler.class).type(BasicRestCallHandler.class);
5938      }
5939
5940      /**
5941       * Creates the {@link HttpClientConnectionManager} returned by {@link #createConnectionManager()}.
5942       *
5943       * <p>
5944       * Subclasses can override this method to provide their own connection manager.
5945       *
5946       * <p>
5947       * The default implementation returns an instance of a {@link PoolingHttpClientConnectionManager} if {@link #pooled()}
5948       * was called or {@link BasicHttpClientConnectionManager} if not..
5949       *
5950       * <h5 class='section'>Example:</h5>
5951       * <p class='bjava'>
5952       *    <jc>// A Builder that provides it's own customized HttpClientConnectionManager.</jc>
5953       *    <jk>public class</jk> MyBuilder <jk>extends</jk> Builder {
5954       *       <ja>@Override</ja>
5955       *       <jk>protected</jk> HttpClientConnectionManager createConnectionManager() {
5956       *          <jk>return new</jk> PoolingHttpClientConnectionManager();
5957       *       }
5958       *    }
5959       *
5960       *    <jc>// Instantiate.</jc>
5961       *    RestClient <jv>client</jv> = <jk>new</jk> MyBuilder().build();
5962       * </p>
5963       *
5964       * @return The HTTP client builder to use to create the HTTP client.
5965       */
5966      protected HttpClientConnectionManager createConnectionManager() {
5967         return (pooled ? new PoolingHttpClientConnectionManager() : new BasicHttpClientConnectionManager());
5968      }
5969
5970      /**
5971       * Creates the builder for the form data list.
5972       *
5973       * <p>
5974       * Subclasses can override this method to provide their own implementation.
5975       *
5976       * <p>
5977       * The default behavior creates an empty builder.
5978       *
5979       * @return The query data list builder.
5980       * @see #formData()
5981       */
5982      protected PartList createFormData() {
5983         return PartList.create();
5984      }
5985
5986      /**
5987       * Creates the builder for the header list.
5988       *
5989       * <p>
5990       * Subclasses can override this method to provide their own implementation.
5991       *
5992       * <p>
5993       * The default behavior creates an empty builder.
5994       *
5995       * @return The header list builder.
5996       * @see #headers()
5997       */
5998      protected HeaderList createHeaderData() {
5999         return HeaderList.create();
6000      }
6001
6002      /**
6003       * Creates an instance of an {@link HttpClient} to be used to handle all HTTP communications with the target server.
6004       *
6005       * <p>
6006       * This HTTP client is used when the HTTP client is not specified through one of the constructors or the
6007       * {@link #httpClient(CloseableHttpClient)} method.
6008       *
6009       * <p>
6010       * Subclasses can override this method to provide specially-configured HTTP clients to handle stuff such as
6011       * SSL/TLS certificate handling, authentication, etc.
6012       *
6013       * <p>
6014       * The default implementation returns an instance of {@link HttpClient} using the client builder returned by
6015       * {@link #createHttpClientBuilder()}.
6016       *
6017       * <h5 class='section'>Example:</h5>
6018       * <p class='bjava'>
6019       *    <jc>// A Builder that provides it's own customized HttpClient.</jc>
6020       *    <jk>public class</jk> MyBuilder <jk>extends</jk> Builder {
6021       *       <ja>@Override</ja>
6022       *       <jk>protected</jk> HttpClientBuilder createHttpClient() {
6023       *          <jk>return</jk> HttpClientBuilder.<jsm>create</jsm>().build();
6024       *       }
6025       *    }
6026       *
6027       *    <jc>// Instantiate.</jc>
6028       *    RestClient <jv>client</jv> = <jk>new</jk> MyBuilder().build();
6029       * </p>
6030       *
6031       * @return The HTTP client to use.
6032       */
6033      protected CloseableHttpClient createHttpClient() {
6034         if (connectionManager == null)
6035            connectionManager = createConnectionManager();
6036         httpClientBuilder().setConnectionManager(connectionManager);
6037         return httpClientBuilder().build();
6038      }
6039
6040      /**
6041       * Creates an instance of an {@link HttpClientBuilder} to be used to create the {@link HttpClient}.
6042       *
6043       * <p>
6044       * Subclasses can override this method to provide their own client builder.
6045       * The builder can also be specified using the {@link #httpClientBuilder(HttpClientBuilder)} method.
6046       *
6047       * <h5 class='section'>Example:</h5>
6048       * <p class='bjava'>
6049       *    <jc>// A Builder that provides it's own customized HttpClientBuilder.</jc>
6050       *    <jk>public class</jk> MyBuilder <jk>extends</jk> Builder {
6051       *       <ja>@Override</ja>
6052       *       <jk>protected</jk> HttpClientBuilder createHttpClientBuilder() {
6053       *          <jk>return</jk> HttpClientBuilder.<jsm>create</jsm>();
6054       *       }
6055       *    }
6056       *
6057       *    <jc>// Instantiate.</jc>
6058       *    RestClient <jv>client</jv> = <jk>new</jk> MyBuilder().build();
6059       * </p>
6060       *
6061       * @return The HTTP client builder to use to create the HTTP client.
6062       */
6063      protected HttpClientBuilder createHttpClientBuilder() {
6064         return HttpClientBuilder.create();
6065      }
6066
6067      /**
6068       * Instantiates the parser group sub-builder.
6069       *
6070       * @return A new parser group sub-builder.
6071       */
6072      protected ParserSet.Builder createParsers() {
6073         return ParserSet.create().beanContext(beanContext());
6074      }
6075
6076      /**
6077       * Instantiates the part parser sub-builder.
6078       *
6079       * @return A new part parser sub-builder.
6080       */
6081      protected HttpPartParser.Creator createPartParser() {
6082         return HttpPartParser.creator().type(OpenApiParser.class).beanContext(beanContext());
6083      }
6084
6085      /**
6086       * Instantiates the part serializer sub-builder.
6087       *
6088       * @return A new part serializer sub-builder.
6089       */
6090      protected HttpPartSerializer.Creator createPartSerializer() {
6091         return HttpPartSerializer.creator().type(OpenApiSerializer.class).beanContext(beanContext());
6092      }
6093
6094      /**
6095       * Creates the builder for the path data list.
6096       *
6097       * <p>
6098       * Subclasses can override this method to provide their own implementation.
6099       *
6100       * <p>
6101       * The default behavior creates an empty builder.
6102       *
6103       * @return The query data list builder.
6104       * @see #pathData()
6105       */
6106      protected PartList createPathData() {
6107         return PartList.create();
6108      }
6109
6110      /**
6111       * Creates the builder for the query data list.
6112       *
6113       * <p>
6114       * Subclasses can override this method to provide their own implementation.
6115       *
6116       * <p>
6117       * The default behavior creates an empty builder.
6118       *
6119       * @return The query data list builder.
6120       * @see #queryData()
6121       */
6122      protected PartList createQueryData() {
6123         return PartList.create();
6124      }
6125
6126      /**
6127       * Instantiates the serializer group sub-builder.
6128       *
6129       * @return A new serializer group sub-builder.
6130       */
6131      protected SerializerSet.Builder createSerializers() {
6132         return SerializerSet.create().beanContext(beanContext());
6133      }
6134
6135      /**
6136       * Instantiates the URL-encoding serializer sub-builder.
6137       *
6138       * @return A new URL-encoding serializer sub-builder.
6139       */
6140      protected UrlEncodingSerializer.Builder createUrlEncodingSerializer() {
6141         return UrlEncodingSerializer.create().beanContext(beanContext());
6142      }
6143
6144      final CloseableHttpClient getHttpClient() { return nn(httpClient) ? httpClient : createHttpClient(); }
6145   }
6146
6147   private static final RestCallInterceptor[] EMPTY_REST_CALL_INTERCEPTORS = {};
6148   private static final ConcurrentHashMap<Class<?>,Context> requestContexts = new ConcurrentHashMap<>();
6149   private static final BiPredicate<RestRequest,RestResponse> LOG_REQUESTS_PREDICATE_DEFAULT = (req, res) -> true;
6150
6151   /**
6152    * Instantiates a new clean-slate {@link Builder} object.
6153    *
6154    * @return A new {@link Builder} object.
6155    */
6156   public static Builder create() {
6157      return new Builder();
6158   }
6159
6160   protected final boolean detectLeaks;
6161   protected final boolean ignoreErrors;
6162   protected final boolean keepHttpClientOpen;
6163   protected final boolean skipEmptyFormData;
6164   protected final boolean skipEmptyHeaderData;
6165   protected final boolean skipEmptyQueryData;
6166   protected final BiPredicate<RestRequest,RestResponse> logRequestsPredicate;
6167   protected final CloseableHttpClient httpClient;
6168   protected final DetailLevel logRequests;
6169   protected final HeaderList headerData;
6170   protected final HttpPartParser partParser;
6171   protected final HttpPartSerializer partSerializer;
6172   protected final Level logRequestsLevel;
6173   protected final PartList formData;
6174   protected final PartList pathData;
6175   protected final PartList queryData;
6176   protected final ParserSet parsers;
6177   protected final RestCallInterceptor[] interceptors;
6178   protected final SerializerSet serializers;
6179   protected final UrlEncodingSerializer urlEncodingSerializer;  // Used for form posts only.
6180   Predicate<Integer> errorCodes;
6181   private final BeanStore beanStore;
6182   private final HttpClientConnectionManager connectionManager;
6183   private final Logger logger;
6184   private final Map<Class<?>,HttpPartParser> partParsers = new ConcurrentHashMap<>();
6185   private final Map<Class<?>,HttpPartSerializer> partSerializers = new ConcurrentHashMap<>();
6186   private final Pattern absUrlPattern = Pattern.compile("^\\w+\\:\\/\\/.*");
6187   private final PrintStream console;
6188   private final RestCallHandler callHandler;
6189   private StackTraceElement[] closedStack;
6190   private final StackTraceElement[] creationStack;
6191   private final String rootUrl;
6192   private final boolean executorServiceShutdownOnClose;
6193   private final boolean logToConsole;
6194   private final AtomicBoolean isClosed = new AtomicBoolean(false);
6195   private final AtomicReference<ExecutorService> executorService = new AtomicReference<>();
6196
6197   /**
6198    * Constructor.
6199    *
6200    * @param builder The builder for this client.
6201    */
6202   public RestClient(Builder builder) {
6203      super(builder);
6204
6205      beanStore = builder.beanStore.addBean(RestClient.class, this);
6206
6207      callHandler = builder.callHandler().run();
6208      connectionManager = builder.connectionManager;
6209      console = nn(builder.console) ? builder.console : System.err;
6210      creationStack = isDebug() ? Thread.currentThread().getStackTrace() : null;
6211      detectLeaks = builder.detectLeaks;
6212      errorCodes = builder.errorCodes;
6213      formData = builder.formData().copy();
6214      headerData = builder.headers().copy();
6215      httpClient = builder.getHttpClient();
6216      ignoreErrors = builder.ignoreErrors;
6217      interceptors = nn(builder.interceptors) ? builder.interceptors.toArray(EMPTY_REST_CALL_INTERCEPTORS) : EMPTY_REST_CALL_INTERCEPTORS;
6218      keepHttpClientOpen = builder.keepHttpClientOpen;
6219      logger = nn(builder.logger) ? builder.logger : Logger.getLogger(cn(RestClient.class));
6220      logRequests = nn(builder.logRequests) ? builder.logRequests : isDebug() ? DetailLevel.FULL : DetailLevel.NONE;
6221      logRequestsLevel = nn(builder.logRequestsLevel) ? builder.logRequestsLevel : isDebug() ? Level.WARNING : Level.OFF;
6222      logRequestsPredicate = nn(builder.logRequestsPredicate) ? builder.logRequestsPredicate : LOG_REQUESTS_PREDICATE_DEFAULT;
6223      logToConsole = builder.logToConsole || isDebug();
6224      parsers = builder.parsers().build();
6225      partParser = builder.partParser().create();
6226      partSerializer = builder.partSerializer().create();
6227      pathData = builder.pathData().copy();
6228      queryData = builder.queryData().copy();
6229      rootUrl = builder.rootUrl;
6230      serializers = builder.serializers().build();
6231      skipEmptyFormData = builder.skipEmptyFormData;
6232      skipEmptyHeaderData = builder.skipEmptyHeaderData;
6233      skipEmptyQueryData = builder.skipEmptyQueryData;
6234      urlEncodingSerializer = builder.urlEncodingSerializer().build();
6235      if (builder.executorService != null)
6236         executorService.set(builder.executorService);
6237      executorServiceShutdownOnClose = builder.executorServiceShutdownOnClose;
6238
6239      init();
6240   }
6241
6242   /**
6243    * Performs a REST call where the entire call is specified in a simple string.
6244    *
6245    * <p>
6246    * This method is useful for performing callbacks when the target of a callback is passed in
6247    * on an initial request, for example to signal when a long-running process has completed.
6248    *
6249    * <p>
6250    * The call string can be any of the following formats:
6251    * <ul class='spaced-list'>
6252    *    <li>
6253    *       <js>"[method] [uri]"</js> - e.g. <js>"GET http://localhost/callback"</js>
6254    *    <li>
6255    *       <js>"[method] [uri] [payload]"</js> - e.g. <js>"POST http://localhost/callback some text payload"</js>
6256    *    <li>
6257    *       <js>"[method] [headers] [uri] [payload]"</js> - e.g. <js>"POST {'Content-Type':'text/json'} http://localhost/callback {'some':'json'}"</js>
6258    * </ul>
6259    * <p>
6260    * The payload will always be sent using a simple {@link StringEntity}.
6261    *
6262    * @param callString The call string.
6263    *    <br>Can be <jk>null</jk> or empty (treated as empty string, will result in an invalid request).
6264    * @return
6265    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
6266    *    as a parsed object.
6267    * @throws RestCallException REST call failed.
6268    */
6269   public RestRequest callback(String callString) throws RestCallException {
6270      callString = emptyIfNull(callString);
6271
6272      // S1 - Looking for end of method.
6273      // S2 - Found end of method, looking for beginning of URI or headers.
6274      // S3 - Found beginning of headers, looking for end of headers.
6275      // S4 - Found end of headers, looking for beginning of URI.
6276      // S5 - Found beginning of URI, looking for end of URI.
6277
6278      var state = S1;
6279
6280      var mark = 0;
6281      var method = (String)null;
6282      var headers = (String)null;
6283      var uri = (String)null;
6284      var content = (String)null;
6285      for (var i = 0; i < callString.length(); i++) {
6286         var c = callString.charAt(i);
6287         if (state == S1) {
6288            if (isWhitespace(c)) {
6289               method = callString.substring(mark, i);
6290               state = S2;
6291            }
6292         } else if (state == S2) {
6293            if (! isWhitespace(c)) {
6294               mark = i;
6295               if (c == '{')
6296                  state = S3;
6297               else
6298                  state = S5;
6299            }
6300         } else if (state == S3) {
6301            if (c == '}') {
6302               headers = callString.substring(mark, i + 1);
6303               state = S4;
6304            }
6305         } else if (state == S4) {
6306            if (! isWhitespace(c)) {
6307               mark = i;
6308               state = S5;
6309            }
6310         } else /* (state == S5) */ {
6311            if (isWhitespace(c)) {
6312               uri = callString.substring(mark, i);
6313               content = callString.substring(i).trim();
6314               break;
6315            }
6316         }
6317      }
6318
6319      if (state != S5)
6320         throw new RestCallException(null, null, "Invalid format for call string.  State={0}", state);
6321
6322      try {
6323         var req = request(method, uri, ne(content));
6324         if (nn(headers))
6325            JsonMap.ofJson(headers).forEach((k, v) -> req.header(stringHeader(k, s(v))));
6326         if (ne(content))
6327            req.contentString(content);
6328         return req;
6329      } catch (ParseException e) {
6330         throw new RestCallException(null, e, "Invalid format for call string.");
6331      }
6332   }
6333
6334   /**
6335    * Calls {@link CloseableHttpClient#close()} on the underlying {@link CloseableHttpClient}.
6336    *
6337    * <p>
6338    * It's good practice to call this method after the client is no longer used.
6339    *
6340    * @throws IOException Thrown by underlying stream.
6341    */
6342   @Override
6343   public void close() throws IOException {
6344      isClosed.set(true);
6345      ExecutorService es = executorService.get();
6346      if (! keepHttpClientOpen)
6347         httpClient.close();
6348      if (nn(es) && executorServiceShutdownOnClose)
6349         es.shutdown();
6350      if (nn(creationStack))
6351         closedStack = Thread.currentThread().getStackTrace();
6352   }
6353
6354   /**
6355    * Same as {@link #close()}, but ignores any exceptions.
6356    */
6357   public void closeQuietly() {
6358      isClosed.set(true);
6359      try {
6360         if (! keepHttpClientOpen)
6361            httpClient.close();
6362         ExecutorService es = executorService.get();
6363         if (nn(es) && executorServiceShutdownOnClose)
6364            es.shutdown();
6365      } catch (@SuppressWarnings("unused") Throwable t) {}
6366      if (nn(creationStack))
6367         closedStack = Thread.currentThread().getStackTrace();
6368   }
6369
6370   @Override /* Overridden from Context */
6371   public Builder copy() {
6372      throw new NoSuchMethodError("Not implemented.");
6373   }
6374
6375   /**
6376    * Creates a mutable copy of the form data defined on this client.
6377    *
6378    * <p>
6379    * Used during the construction of {@link RestRequest} objects.
6380    *
6381    * <p>
6382    * Subclasses can override this method to provide their own builder.
6383    *
6384    * @return A new builder.
6385    */
6386   public PartList createFormData() {
6387      return formData.copy();
6388   }
6389
6390   /**
6391    * Creates a mutable copy of the header data defined on this client.
6392    *
6393    * <p>
6394    * Used during the construction of {@link RestRequest} objects.
6395    *
6396    * <p>
6397    * Subclasses can override this method to provide their own builder.
6398    *
6399    * @return A new builder.
6400    */
6401   public HeaderList createHeaderData() {
6402      return headerData.copy();
6403   }
6404
6405   /**
6406    * Creates a mutable copy of the path data defined on this client.
6407    *
6408    * <p>
6409    * Used during the construction of {@link RestRequest} objects.
6410    *
6411    * <p>
6412    * Subclasses can override this method to provide their own builder.
6413    *
6414    * @return A new builder.
6415    */
6416   public PartList createPathData() {
6417      return pathData.copy();
6418   }
6419
6420   /**
6421    * Creates a mutable copy of the query data defined on this client.
6422    *
6423    * <p>
6424    * Used during the construction of {@link RestRequest} objects.
6425    *
6426    * <p>
6427    * Subclasses can override this method to provide their own builder.
6428    *
6429    * @return A new builder.
6430    */
6431   public PartList createQueryData() {
6432      return queryData.copy();
6433   }
6434
6435   /**
6436    * Perform a <c>DELETE</c> request against the specified URI.
6437    *
6438    * @param uri
6439    *    The URI of the remote REST resource.
6440    *    <br>Can be any of the following types:
6441    *    <ul>
6442    *       <li>{@link URIBuilder}
6443    *       <li>{@link URI}
6444    *       <li>{@link URL}
6445    *       <li>{@link String}
6446    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
6447    *    </ul>
6448    * @return
6449    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
6450    *    as a parsed object.
6451    * @throws RestCallException If any authentication errors occurred.
6452    */
6453   public RestRequest delete(Object uri) throws RestCallException {
6454      return request(op("DELETE", uri, NO_BODY));
6455   }
6456
6457   /**
6458    * Executes HTTP request using the default context.
6459    *
6460    * <h5 class='section'>Notes:</h5><ul>
6461    *    <li class='note'>This method gets passed on directly to the underlying {@link HttpClient} class.
6462    * </ul>
6463    *
6464    * @param target The target host for the request.
6465    *    <br>Implementations may accept <jk>null</jk> if they can still determine a route, for example to a default
6466    *       target or by inspecting the request.
6467    * @param request The request to execute.
6468    * @return The response to the request.
6469    *    <br>This is always a final response, never an intermediate response with an 1xx status code.
6470    *    <br>Whether redirects or authentication challenges will be returned or handled automatically depends on the
6471    *       implementation and configuration of this client.
6472    * @throws IOException In case of a problem or the connection was aborted.
6473    * @throws ClientProtocolException In case of an http protocol error.
6474    */
6475   @Override /* Overridden from HttpClient */
6476   public HttpResponse execute(HttpHost target, HttpRequest request) throws IOException, ClientProtocolException {
6477      return httpClient.execute(target, request);
6478   }
6479
6480   /**
6481    * Executes HTTP request using the given context.
6482    *
6483    * <h5 class='section'>Notes:</h5><ul>
6484    *    <li class='note'>This method gets passed on directly to the underlying {@link HttpClient} class.
6485    *    <li class='note'>The {@link #run(HttpHost,HttpRequest,HttpContext)} method has been provided as a wrapper around this method.
6486    *       Subclasses can override these methods for handling requests with and without bodies separately.
6487    *    <li class='note'>The {@link RestCallHandler} interface can also be implemented to intercept this method.
6488    * </ul>
6489    *
6490    * @param target The target host for the request.
6491    *    <br>Implementations may accept <jk>null</jk> if they can still determine a route, for example to a default
6492    *       target or by inspecting the request.
6493    * @param request The request to execute.
6494    * @param context The context to use for the execution, or <jk>null</jk> to use the default context.
6495    * @return
6496    *    The response to the request.
6497    *    <br>This is always a final response, never an intermediate response with an 1xx status code.
6498    *    <br>Whether redirects or authentication challenges will be returned or handled automatically depends on the
6499    *       implementation and configuration of this client.
6500    * @throws IOException In case of a problem or the connection was aborted.
6501    * @throws ClientProtocolException In case of an http protocol error.
6502    */
6503   @Override /* Overridden from HttpClient */
6504   public HttpResponse execute(HttpHost target, HttpRequest request, HttpContext context) throws IOException, ClientProtocolException {
6505      return httpClient.execute(target, request, context);
6506   }
6507
6508   /**
6509    * Executes HTTP request to the target using the default context and processes the response using the given response handler.
6510    *
6511    * <p>
6512    * The content entity associated with the response is fully consumed and the underlying connection is released back
6513    * to the connection manager automatically in all cases relieving individual {@link ResponseHandler ResponseHandlers}
6514    * from having to manage resource deallocation internally.
6515    *
6516    * <h5 class='section'>Notes:</h5><ul>
6517    *    <li class='note'>This method gets passed on directly to the underlying {@link HttpClient} class.
6518    * </ul>
6519    *
6520    * @param target
6521    *    The target host for the request.
6522    *    <br>Implementations may accept <jk>null</jk> if they can still determine a route, for example to a default target or by inspecting the request.
6523    * @param request The request to execute.
6524    * @param responseHandler The response handler.
6525    * @return The response object as generated by the response handler.
6526    * @throws IOException In case of a problem or the connection was aborted.
6527    * @throws ClientProtocolException In case of an http protocol error.
6528    */
6529   @Override /* Overridden from HttpClient */
6530   public <T> T execute(HttpHost target, HttpRequest request, ResponseHandler<? extends T> responseHandler) throws IOException, ClientProtocolException {
6531      return httpClient.execute(target, request, responseHandler);
6532   }
6533
6534   /**
6535    * Executes a request using the default context and processes the response using the given response handler.
6536    *
6537    * <p>
6538    * The content entity associated with the response is fully consumed and the underlying connection is released back
6539    * to the connection manager automatically in all cases relieving individual {@link ResponseHandler ResponseHandlers}
6540    * from having to manage resource deallocation internally.
6541    *
6542    * <h5 class='section'>Notes:</h5><ul>
6543    *    <li class='note'>This method gets passed on directly to the underlying {@link HttpClient} class.
6544    * </ul>
6545    *
6546    * @param target
6547    *    The target host for the request.
6548    *    <br>Implementations may accept <jk>null</jk> if they can still determine a route, for example to a default target or by inspecting the request.
6549    * @param request The request to execute.
6550    * @param responseHandler The response handler.
6551    * @param context The context to use for the execution, or <jk>null</jk> to use the default context.
6552    * @return The response object as generated by the response handler.
6553    * @throws IOException In case of a problem or the connection was aborted.
6554    * @throws ClientProtocolException In case of an http protocol error.
6555    */
6556   @Override /* Overridden from HttpClient */
6557   public <T> T execute(HttpHost target, HttpRequest request, ResponseHandler<? extends T> responseHandler, HttpContext context) throws IOException, ClientProtocolException {
6558      return httpClient.execute(target, request, responseHandler, context);
6559   }
6560
6561   /**
6562    * Executes HTTP request using the default context.
6563    *
6564    * <h5 class='section'>Notes:</h5><ul>
6565    *    <li class='note'>This method gets passed on directly to the underlying {@link HttpClient} class.
6566    * </ul>
6567    *
6568    * @param request The request to execute.
6569    * @return
6570    *    The response to the request.
6571    *    <br>This is always a final response, never an intermediate response with an 1xx status code.
6572    *    <br>Whether redirects or authentication challenges will be returned or handled automatically depends on the
6573    *       implementation and configuration of this client.
6574    * @throws IOException In case of a problem or the connection was aborted.
6575    * @throws ClientProtocolException In case of an http protocol error.
6576    */
6577   @Override /* Overridden from HttpClient */
6578   public HttpResponse execute(HttpUriRequest request) throws IOException, ClientProtocolException {
6579      return httpClient.execute(request);
6580   }
6581
6582   /**
6583    * Executes HTTP request using the given context.
6584    *
6585    * <h5 class='section'>Notes:</h5><ul>
6586    *    <li class='note'>This method gets passed on directly to the underlying {@link HttpClient} class.
6587    * </ul>
6588    *
6589    * @param request The request to execute.
6590    * @param context The context to use for the execution, or <jk>null</jk> to use the default context.
6591    * @return
6592    *    The response to the request.
6593    *    <br>This is always a final response, never an intermediate response with an 1xx status code.
6594    *    <br>Whether redirects or authentication challenges will be returned or handled automatically depends on the
6595    *       implementation and configuration of this client.
6596    * @throws IOException In case of a problem or the connection was aborted.
6597    * @throws ClientProtocolException In case of an http protocol error.
6598    */
6599   @Override /* Overridden from HttpClient */
6600   public HttpResponse execute(HttpUriRequest request, HttpContext context) throws IOException, ClientProtocolException {
6601      return httpClient.execute(request, context);
6602   }
6603
6604   /**
6605    * Executes HTTP request using the default context and processes the response using the given response handler.
6606    *
6607    * <p>
6608    * The content entity associated with the response is fully consumed and the underlying connection is released back
6609    * to the connection manager automatically in all cases relieving individual {@link ResponseHandler ResponseHandlers}
6610    * from having to manage resource deallocation internally.
6611    *
6612    * <h5 class='section'>Notes:</h5><ul>
6613    *    <li class='note'>This method gets passed on directly to the underlying {@link HttpClient} class.
6614    * </ul>
6615    *
6616    * @param request The request to execute.
6617    * @param responseHandler The response handler.
6618    * @return Object returned by response handler.
6619    * @throws IOException In case of a problem or the connection was aborted.
6620    * @throws ClientProtocolException In case of an http protocol error.
6621    */
6622   @Override /* Overridden from HttpClient */
6623   public <T> T execute(HttpUriRequest request, ResponseHandler<? extends T> responseHandler) throws IOException, ClientProtocolException {
6624      return httpClient.execute(request, responseHandler);
6625   }
6626
6627   /**
6628    * Executes HTTP request using the given context and processes the response using the given response handler.
6629    *
6630    * <p>
6631    * The content entity associated with the response is fully consumed and the underlying connection is released back
6632    * to the connection manager automatically in all cases relieving individual {@link ResponseHandler ResponseHandlers}
6633    * from having to manage resource deallocation internally.
6634    *
6635    * <h5 class='section'>Notes:</h5><ul>
6636    *    <li class='note'>This method gets passed on directly to the underlying {@link HttpClient} class.
6637    * </ul>
6638    *
6639    * @param request The request to execute.
6640    * @param responseHandler The response handler.
6641    * @param context The context to use for the execution, or <jk>null</jk> to use the default context.
6642    * @return The response object as generated by the response handler.
6643    * @throws IOException In case of a problem or the connection was aborted.
6644    * @throws ClientProtocolException In case of an http protocol error.
6645    */
6646   @Override /* Overridden from HttpClient */
6647   public <T> T execute(HttpUriRequest request, ResponseHandler<? extends T> responseHandler, HttpContext context) throws IOException, ClientProtocolException {
6648      return httpClient.execute(request, responseHandler, context);
6649   }
6650
6651   /**
6652    * Same as {@link #formPost(Object, Object)} but doesn't specify the input yet.
6653    *
6654    * @param uri
6655    *    The URI of the remote REST resource.
6656    *    <br>Can be any of the following types:
6657    *    <ul>
6658    *       <li>{@link URIBuilder}
6659    *       <li>{@link URI}
6660    *       <li>{@link URL}
6661    *       <li>{@link String}
6662    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
6663    *    </ul>
6664    * @return
6665    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
6666    *    as a parsed object.
6667    * @throws RestCallException If any authentication errors occurred.
6668    */
6669   public RestRequest formPost(Object uri) throws RestCallException {
6670      return request(op("POST", uri, NO_BODY));
6671   }
6672
6673   /**
6674    * Perform a <c>POST</c> request with a content type of <c>application/x-www-form-urlencoded</c>
6675    * against the specified URI.
6676    *
6677    * @param uri
6678    *    The URI of the remote REST resource.
6679    *    <br>Can be any of the following types:
6680    *    <ul>
6681    *       <li>{@link URIBuilder}
6682    *       <li>{@link URI}
6683    *       <li>{@link URL}
6684    *       <li>{@link String}
6685    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
6686    *    </ul>
6687    * @param body
6688    *    The object to serialize and transmit to the URI as the body of the request.
6689    *    <ul class='spaced-list'>
6690    *       <li>{@link NameValuePair} - URL-encoded as a single name-value pair.
6691    *       <li>{@link NameValuePair} array - URL-encoded as name value pairs.
6692    *       <li>{@link PartList} - URL-encoded as name value pairs.
6693    *       <li>{@link Reader}/{@link InputStream}- Streamed directly and <l>Content-Type</l> set to <js>"application/x-www-form-urlencoded"</js>
6694    *       <li>{@link HttpResource} - Raw contents will be serialized to remote resource.  Additional headers and media type will be set on request.
6695    *       <li>{@link HttpEntity} - Bypass Juneau serialization and pass HttpEntity directly to HttpClient.
6696    *       <li>{@link Object} - Converted to a {@link SerializedEntity} using {@link UrlEncodingSerializer} to serialize.
6697    *       <li>{@link Supplier} - A supplier of anything on this list.
6698    *    </ul>
6699    * @return
6700    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
6701    *    as a parsed object.
6702    * @throws RestCallException If any authentication errors occurred.
6703    */
6704   public RestRequest formPost(Object uri, Object body) throws RestCallException {
6705      var req = request(op("POST", uri, NO_BODY));
6706      try {
6707         if (body instanceof Supplier body2)
6708            body = body2.get();
6709         if (body instanceof NameValuePair body2)
6710            return req.content(new UrlEncodedFormEntity(l(body2)));
6711         if (body instanceof NameValuePair[])
6712            return req.content(new UrlEncodedFormEntity(l((NameValuePair[])body)));
6713         if (body instanceof PartList body2)
6714            return req.content(new UrlEncodedFormEntity(body2));
6715         if (body instanceof HttpResource body2)
6716            body2.getHeaders().forEach(x -> req.header(x));
6717         if (body instanceof HttpEntity body3) {
6718            if (body3.getContentType() == null)
6719               req.header(ContentType.APPLICATION_FORM_URLENCODED);
6720            return req.content(body3);
6721         }
6722         if (body instanceof Reader || body instanceof InputStream)
6723            return req.header(ContentType.APPLICATION_FORM_URLENCODED).content(body);
6724         return req.content(serializedEntity(body, urlEncodingSerializer, null));
6725      } catch (IOException e) {
6726         throw new RestCallException(null, e, "Could not read form post body.");
6727      }
6728   }
6729
6730   /**
6731    * Perform a <c>POST</c> request with a content type of <c>application/x-www-form-urlencoded</c>
6732    * against the specified URI.
6733    *
6734    * @param uri
6735    *    The URI of the remote REST resource.
6736    *    <br>Can be any of the following types:
6737    *    <ul>
6738    *       <li>{@link URIBuilder}
6739    *       <li>{@link URI}
6740    *       <li>{@link URL}
6741    *       <li>{@link String}
6742    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
6743    *    </ul>
6744    * @param parameters
6745    *    The parameters of the form post.
6746    *    <br>The parameters represent name/value pairs and must be an even number of arguments.
6747    *    <br>Parameters are converted to {@link BasicPart} objects.
6748    * @return
6749    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
6750    *    as a parsed object.
6751    * @throws RestCallException If any authentication errors occurred.
6752    */
6753   public RestRequest formPostPairs(Object uri, String...parameters) throws RestCallException {
6754      return formPost(uri, partList(parameters));
6755   }
6756
6757   /**
6758    * Perform a <c>GET</c> request against the root URI.
6759    *
6760    * @return
6761    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
6762    *    as a parsed object.
6763    * @throws RestCallException If any authentication errors occurred.
6764    */
6765   public RestRequest get() throws RestCallException {
6766      return request(op("GET", null, NO_BODY));
6767   }
6768
6769   /**
6770    * Perform a <c>GET</c> request against the specified URI.
6771    *
6772    * @param uri
6773    *    The URI of the remote REST resource.
6774    *    <br>Can be any of the following types:
6775    *    <ul>
6776    *       <li>{@link URIBuilder}
6777    *       <li>{@link URI}
6778    *       <li>{@link URL}
6779    *       <li>{@link String}
6780    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
6781    *    </ul>
6782    * @return
6783    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
6784    *    as a parsed object.
6785    * @throws RestCallException If any authentication errors occurred.
6786    */
6787   public RestRequest get(Object uri) throws RestCallException {
6788      return request(op("GET", uri, NO_BODY));
6789   }
6790
6791   /**
6792    * Obtains the connection manager used by this client.
6793    *
6794    * @return The connection manager.
6795    * @deprecated Use {@link HttpClientBuilder}.
6796    */
6797   @Deprecated
6798   @Override /* Overridden from HttpClient */
6799   public ClientConnectionManager getConnectionManager() { return httpClient.getConnectionManager(); }
6800
6801   /**
6802    * Returns the connection manager if one was specified in the client builder.
6803    *
6804    * @return The connection manager.  May be <jk>null</jk>.
6805    */
6806   public HttpClientConnectionManager getHttpClientConnectionManager() { return connectionManager; }
6807
6808   /**
6809    * Obtains the parameters for this client.
6810    *
6811    * These parameters will become defaults for all requests being executed with this client, and for the parameters of dependent objects in this client.
6812    *
6813    * @return The default parameters.
6814    * @deprecated Use {@link RequestConfig}.
6815    */
6816   @Deprecated
6817   @Override /* Overridden from HttpClient */
6818   public HttpParams getParams() { return httpClient.getParams(); }
6819
6820   /**
6821    * Create a new proxy interface against a 3rd-party REST interface.
6822    *
6823    * <p>
6824    * The URI to the REST interface is based on the following values:
6825    * <ul>
6826    *    <li>The {@link Remote#path() @Remote(path)} annotation on the interface (<c>remote-path</c>).
6827    *    <li>The {@link Builder#rootUrl(Object) rootUrl} on the client (<c>root-url</c>).
6828    *    <li>The fully-qualified class name of the interface (<c>class-name</c>).
6829    * </ul>
6830    *
6831    * <p>
6832    * The URI calculation is as follows:
6833    * <ul>
6834    *    <li><c>remote-path</c> - If remote path is absolute.
6835    *    <li><c>root-uri/remote-path</c> - If remote path is relative and root-uri has been specified.
6836    *    <li><c>root-uri/class-name</c> - If remote path is not specified.
6837    * </ul>
6838    *
6839    * <p>
6840    * If the information is not available to resolve to an absolute URI, a {@link RemoteMetadataException} is thrown.
6841    *
6842    * <h5 class='section'>Examples:</h5>
6843    * <p class='bjava'>
6844    *    <jk>package</jk> org.apache.foo;
6845    *
6846    *    <ja>@RemoteResource</ja>(path=<js>"http://hostname/resturi/myinterface1"</js>)
6847    *    <jk>public interface</jk> MyInterface1 { ... }
6848    *
6849    *    <ja>@RemoteResource</ja>(path=<js>"/myinterface2"</js>)
6850    *    <jk>public interface</jk> MyInterface2 { ... }
6851    *
6852    *    <jk>public interface</jk> MyInterface3 { ... }
6853    *
6854    *    <jc>// Resolves to "http://localhost/resturi/myinterface1"</jc>
6855    *    MyInterface1 <jv>interface1</jv> = RestClient
6856    *       .<jsm>create</jsm>()
6857    *       .build()
6858    *       .getRemote(MyInterface1.<jk>class</jk>);
6859    *
6860    *    <jc>// Resolves to "http://hostname/resturi/myinterface2"</jc>
6861    *    MyInterface2 <jv>interface2</jv> = RestClient
6862    *       .<jsm>create</jsm>()
6863    *       .rootUrl(<js>"http://hostname/resturi"</js>)
6864    *       .build()
6865    *       .getRemote(MyInterface2.<jk>class</jk>);
6866    *
6867    *    <jc>// Resolves to "http://hostname/resturi/org.apache.foo.MyInterface3"</jc>
6868    *    MyInterface3 <jv>interface3</jv> = RestClient
6869    *       .<jsm>create</jsm>()
6870    *       .rootUrl(<js>"http://hostname/resturi"</js>)
6871    *       .build()
6872    *       .getRemote(MyInterface3.<jk>class</jk>);
6873    * </p>
6874    *
6875    * <h5 class='section'>Notes:</h5><ul>
6876    *    <li class='note'>
6877    *       If you plan on using your proxy in a multi-threaded environment, you'll want to use an underlying
6878    *       pooling client connection manager.
6879    * </ul>
6880    *
6881    * <h5 class='section'>See Also:</h5><ul>
6882    *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/RestProxyBasics">REST Proxy Basics</a>
6883    * </ul>
6884    *
6885    * @param <T> The interface to create a proxy for.
6886    * @param interfaceClass The interface to create a proxy for.
6887    *    <br>Cannot be <jk>null</jk>.
6888    * @return The new proxy interface.
6889    * @throws RemoteMetadataException If the REST URI cannot be determined based on the information given.
6890    */
6891   public <T> T getRemote(Class<T> interfaceClass) {
6892      return getRemote(interfaceClass, null);
6893   }
6894
6895   /**
6896    * Same as {@link #getRemote(Class)} except explicitly specifies the URI of the REST interface.
6897    *
6898    * <h5 class='section'>See Also:</h5><ul>
6899    *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/RestProxyBasics">REST Proxy Basics</a>
6900    * </ul>
6901    *
6902    * @param <T> The interface to create a proxy for.
6903    * @param interfaceClass The interface to create a proxy for.
6904    *    <br>Cannot be <jk>null</jk>.
6905    * @param rootUrl The URI of the REST interface.
6906    *    <br>Can be <jk>null</jk> (will use the root URL from the client builder if set).
6907    * @return The new proxy interface.
6908    */
6909   public <T> T getRemote(Class<T> interfaceClass, Object rootUrl) {
6910      return getRemote(interfaceClass, rootUrl, null, null);
6911   }
6912
6913   /**
6914    * Same as {@link #getRemote(Class, Object)} but allows you to override the serializer and parser used.
6915    *
6916    * <h5 class='section'>See Also:</h5><ul>
6917    *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/RestProxyBasics">REST Proxy Basics</a>
6918    * </ul>
6919
6920    * @param <T> The interface to create a proxy for.
6921    * @param interfaceClass The interface to create a proxy for.
6922    *    <br>Cannot be <jk>null</jk>.
6923    * @param rootUrl The URI of the REST interface.
6924    *    <br>Can be <jk>null</jk> (will use the root URL from the client builder if set).
6925    * @param serializer The serializer used to serialize POJOs to the body of the HTTP request.
6926    *    <br>Can be <jk>null</jk> (will use the default serializer from the client).
6927    * @param parser The parser used to parse POJOs from the body of the HTTP response.
6928    *    <br>Can be <jk>null</jk> (will use the default parser from the client).
6929    * @return The new proxy interface.
6930    */
6931   @SuppressWarnings({ "unchecked" })
6932   public <T> T getRemote(Class<T> interfaceClass, Object rootUrl, Serializer serializer, Parser parser) {
6933
6934      if (rootUrl == null)
6935         rootUrl = this.rootUrl;
6936
6937      final String restUrl2 = trimSlashes(emptyIfNull(rootUrl));
6938
6939      return (T)Proxy.newProxyInstance(interfaceClass.getClassLoader(), a(interfaceClass), new InvocationHandler() {
6940
6941         final RemoteMeta rm = new RemoteMeta(interfaceClass);
6942
6943         @Override /* Overridden from InvocationHandler */
6944         public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
6945            var rom = rm.getOperationMeta(method);
6946
6947            var uri = rom.getFullPath();
6948            if (uri.indexOf("://") == -1)
6949               uri = restUrl2 + '/' + uri;
6950            if (uri.indexOf("://") == -1)
6951               throw new RemoteMetadataException(interfaceClass, "Root URI has not been specified.  Cannot construct absolute path to remote resource.");
6952
6953            var httpMethod = rom.getHttpMethod();
6954            var rc = request(httpMethod, uri, hasContent(httpMethod));
6955
6956            if (serializer != null) rc.serializer(serializer);
6957            if (parser != null) rc.parser(parser);
6958
6959            rm.getHeaders().forEach(x -> rc.header(x));
6960
6961            // Apply method-level defaults if parameter values are not provided (9.2.0)
6962            rom.forEachPathArg(a -> {
6963               var val = args[a.getIndex()];
6964               if (val == null) {
6965                  // Check parameter-level default first (9.2.0)
6966                  var def = a.getSchema().getDefault();
6967                  // Fall back to method-level default if parameter-level not set
6968                  if (def == null)
6969                     def = rom.getPathDefault(a.getName());
6970                  if (nn(def))
6971                     val = def;
6972               }
6973               rc.pathArg(a.getName(), val, a.getSchema(), a.getSerializer().orElse(partSerializer));
6974            });
6975            rom.forEachQueryArg(a -> {
6976               var val = args[a.getIndex()];
6977               if (val == null) {
6978                  // Check parameter-level default first (9.2.0)
6979                  var def = a.getSchema().getDefault();
6980                  // Fall back to method-level default if parameter-level not set
6981                  if (def == null)
6982                     def = rom.getQueryDefault(a.getName());
6983                  if (nn(def))
6984                     val = def;
6985               }
6986               rc.queryArg(a.getName(), val, a.getSchema(), a.getSerializer().orElse(partSerializer), a.isSkipIfEmpty());
6987            });
6988            rom.forEachFormDataArg(a -> {
6989               var val = args[a.getIndex()];
6990               if (val == null) {
6991                  // Check parameter-level default first (9.2.0)
6992                  var def = a.getSchema().getDefault();
6993                  // Fall back to method-level default if parameter-level not set
6994                  if (def == null)
6995                     def = rom.getFormDataDefault(a.getName());
6996                  if (nn(def))
6997                     val = def;
6998               }
6999               rc.formDataArg(a.getName(), val, a.getSchema(), a.getSerializer().orElse(partSerializer), a.isSkipIfEmpty());
7000            });
7001            rom.forEachHeaderArg(a -> {
7002               var val = args[a.getIndex()];
7003               if (val == null) {
7004                  // Check parameter-level default first (9.2.0)
7005                  var def = a.getSchema().getDefault();
7006                  // Fall back to method-level default if parameter-level not set
7007                  if (def == null)
7008                     def = rom.getHeaderDefault(a.getName());
7009                  if (nn(def))
7010                     val = def;
7011               }
7012               rc.headerArg(a.getName(), val, a.getSchema(), a.getSerializer().orElse(partSerializer), a.isSkipIfEmpty());
7013            });
7014
7015            var ba = rom.getContentArg();
7016            if (nn(ba)) {
7017               var val = args[ba.getIndex()];
7018               if (val == null) {
7019                  // Check parameter-level default first (9.2.0)
7020                  var def = ba.getSchema().getDefault();
7021                  // Fall back to method-level default if parameter-level not set
7022                  if (def == null)
7023                     def = rom.getContentDefault();
7024                  if (nn(def))
7025                     val = def;
7026               }
7027               rc.content(val, ba.getSchema());
7028            } else {
7029               // Apply Content default if no parameter is present
7030               var contentDef = rom.getContentDefault();
7031               if (nn(contentDef))
7032                  rc.content(contentDef);
7033            }
7034
7035            rom.forEachRequestArg(rmba -> {
7036               var rbm = rmba.getMeta();
7037               var bean = args[rmba.getIndex()];
7038               if (nn(bean)) {
7039                  for (var p : rbm.getProperties()) {
7040                     var val = safeSupplier(() -> p.getGetter().invoke(bean));
7041                     var pt = p.getPartType();
7042                     var pn = p.getPartName();
7043                     var schema = p.getSchema();
7044                     if (pt == PATH)
7045                        rc.pathArg(pn, val, schema, p.getSerializer().orElse(partSerializer));
7046                     else if (nn(val)) {
7047                        if (pt == QUERY)
7048                           rc.queryArg(pn, val, schema, p.getSerializer().orElse(partSerializer), schema.isSkipIfEmpty());
7049                        else if (pt == FORMDATA)
7050                           rc.formDataArg(pn, val, schema, p.getSerializer().orElse(partSerializer), schema.isSkipIfEmpty());
7051                        else if (pt == HEADER)
7052                           rc.headerArg(pn, val, schema, p.getSerializer().orElse(partSerializer), schema.isSkipIfEmpty());
7053                        else /* (pt == HttpPartType.BODY) */
7054                           rc.content(val, schema);
7055                     }
7056                  }
7057               }
7058            });
7059
7060            var ror = rom.getReturns();
7061            if (ror.isFuture()) {
7062               return getExecutorService().submit(() -> {
7063                  try {
7064                     return executeRemote(interfaceClass, rc, method, rom);
7065                  } catch (Exception e) {
7066                     throw e;
7067                  } catch (Throwable e) {
7068                     throw toRex(e);
7069                  }
7070               });
7071            } else if (ror.isCompletableFuture()) {
7072               var cf = new CompletableFuture<>();
7073               getExecutorService().submit(() -> {
7074                  try {
7075                     cf.complete(executeRemote(interfaceClass, rc, method, rom));
7076                  } catch (Throwable e) {
7077                     cf.completeExceptionally(e);
7078                  }
7079                  return null;
7080               });
7081               return cf;
7082            }
7083
7084            return executeRemote(interfaceClass, rc, method, rom);
7085         }
7086      });
7087   }
7088
7089   /**
7090    * Create a new proxy interface against an RRPC-style service.
7091    *
7092    * <p>
7093    * Remote interfaces are interfaces exposed on the server side using either the <c>RrpcServlet</c>
7094    * or <c>RRPC</c> REST methods.
7095    *
7096    * <p>
7097    * The URI to the REST interface is based on the following values:
7098    * <ul>
7099    *    <li>The {@link Remote#path() @Remote(path)} annotation on the interface (<c>remote-path</c>).
7100    *    <li>The {@link Builder#rootUrl(Object) rootUrl} on the client (<c>root-url</c>).
7101    *    <li>The fully-qualified class name of the interface (<c>class-name</c>).
7102    * </ul>
7103    *
7104    * <p>
7105    * The URI calculation is as follows:
7106    * <ul>
7107    *    <li><c>remote-path</c> - If remote path is absolute.
7108    *    <li><c>root-url/remote-path</c> - If remote path is relative and root-url has been specified.
7109    *    <li><c>root-url/class-name</c> - If remote path is not specified.
7110    * </ul>
7111    *
7112    * <p>
7113    * If the information is not available to resolve to an absolute URI, a {@link RemoteMetadataException} is thrown.
7114    *
7115    * <h5 class='section'>Notes:</h5><ul>
7116    *    <li class='note'>
7117    *       If you plan on using your proxy in a multi-threaded environment, you'll want to use an underlying
7118    *       pooling client connection manager.
7119    * </ul>
7120    *
7121    * <h5 class='section'>See Also:</h5><ul>
7122    *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/RestRpc">REST/RPC</a>
7123    * </ul>
7124    *
7125    * @param <T> The interface to create a proxy for.
7126    * @param interfaceClass The interface to create a proxy for.
7127    *    <br>Cannot be <jk>null</jk>.
7128    * @return The new proxy interface.
7129    * @throws RemoteMetadataException If the REST URI cannot be determined based on the information given.
7130    */
7131   public <T> T getRrpcInterface(Class<T> interfaceClass) {
7132      return getRrpcInterface(interfaceClass, null);
7133   }
7134
7135   /**
7136    * Same as {@link #getRrpcInterface(Class)} except explicitly specifies the URI of the REST interface.
7137    *
7138    * <h5 class='section'>See Also:</h5><ul>
7139    *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/RestRpc">REST/RPC</a>
7140    * </ul>
7141    *
7142    * @param <T> The interface to create a proxy for.
7143    * @param interfaceClass The interface to create a proxy for.
7144    *    <br>Cannot be <jk>null</jk>.
7145    * @param uri The URI of the REST interface.
7146    *    <br>Can be <jk>null</jk> (will use the root URL from the client builder if set).
7147    * @return The new proxy interface.
7148    */
7149   public <T> T getRrpcInterface(Class<T> interfaceClass, Object uri) {
7150      return getRrpcInterface(interfaceClass, uri, null, null);
7151   }
7152
7153   /**
7154    * Same as {@link #getRrpcInterface(Class, Object)} but allows you to override the serializer and parser used.
7155    *
7156    * <h5 class='section'>See Also:</h5><ul>
7157    *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/RestRpc">REST/RPC</a>
7158    * </ul>
7159    *
7160    * @param <T> The interface to create a proxy for.
7161    * @param interfaceClass The interface to create a proxy for.
7162    *    <br>Cannot be <jk>null</jk>.
7163    * @param uri The URI of the REST interface.
7164    *    <br>Can be <jk>null</jk> (will use the root URL from the client builder if set).
7165    * @param serializer The serializer used to serialize POJOs to the body of the HTTP request.
7166    *    <br>Can be <jk>null</jk> (will use the default serializer from the client).
7167    * @param parser The parser used to parse POJOs from the body of the HTTP response.
7168    *    <br>Can be <jk>null</jk> (will use the default parser from the client).
7169    * @return The new proxy interface.
7170    */
7171   @SuppressWarnings({ "unchecked" })
7172   public <T> T getRrpcInterface(Class<T> interfaceClass, Object uri, Serializer serializer, Parser parser) {
7173
7174      if (uri == null) {
7175         var rm = new RrpcInterfaceMeta(interfaceClass, "");
7176         var path = rm.getPath();
7177         if (path.indexOf("://") == -1) {
7178            if (isEmpty(rootUrl))
7179               throw new RemoteMetadataException(interfaceClass, "Root URI has not been specified.  Cannot construct absolute path to remote interface.");
7180            path = trimSlashes(rootUrl) + '/' + path;
7181         }
7182         uri = path;
7183      }
7184
7185      final String restUrl2 = s(uri);
7186
7187      return (T)Proxy.newProxyInstance(interfaceClass.getClassLoader(), a(interfaceClass), new InvocationHandler() {
7188
7189         final RrpcInterfaceMeta rm = new RrpcInterfaceMeta(interfaceClass, restUrl2);
7190
7191         @Override /* Overridden from InvocationHandler */
7192         public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
7193            var rim = rm.getMethodMeta(method);
7194
7195            var uri = rim.getUri();
7196            var res = (RestResponse)null;
7197
7198            try {
7199               // @formatter:off
7200               RestRequest rc = request("POST", uri, true)
7201                  .serializer(serializer)
7202                  .content(args)
7203                  .rethrow(RuntimeException.class)
7204                  .rethrow(method.getExceptionTypes());
7205               // @formatter:on
7206
7207               res = rc.run();
7208
7209               var v = res.getContent().as(method.getGenericReturnType());
7210               if (v == null && method.getReturnType().isPrimitive())
7211                  v = ClassInfo.of(method.getReturnType()).getPrimitiveDefault();
7212               return v;
7213
7214            } catch (Throwable e) {
7215               if (e instanceof RestCallException e2) {
7216                  var t = e2.getCause();
7217                  if (nn(t))
7218                     e = t;
7219               }
7220               if (e instanceof RuntimeException e2)
7221                  throw e2;
7222               for (var t2 : method.getExceptionTypes())
7223                  if (t2.isInstance(e))
7224                     throw e;
7225               throw toRex(e);
7226            }
7227         }
7228      });
7229   }
7230
7231   /**
7232    * Perform a <c>HEAD</c> request against the specified URI.
7233    *
7234    * @param uri
7235    *    The URI of the remote REST resource.
7236    *    <br>Can be any of the following types:
7237    *    <ul>
7238    *       <li>{@link URIBuilder}
7239    *       <li>{@link URI}
7240    *       <li>{@link URL}
7241    *       <li>{@link String}
7242    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
7243    *    </ul>
7244    * @return
7245    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
7246    *    as a parsed object.
7247    * @throws RestCallException If any authentication errors occurred.
7248    */
7249   public RestRequest head(Object uri) throws RestCallException {
7250      return request(op("HEAD", uri, NO_BODY));
7251   }
7252
7253   /**
7254    * Perform an <c>OPTIONS</c> request against the specified URI.
7255    *
7256    * @param uri
7257    *    The URI of the remote REST resource.
7258    *    <br>Can be any of the following types:
7259    *    <ul>
7260    *       <li>{@link URIBuilder}
7261    *       <li>{@link URI}
7262    *       <li>{@link URL}
7263    *       <li>{@link String}
7264    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
7265    *    </ul>
7266    * @return
7267    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
7268    *    as a parsed object.
7269    * @throws RestCallException If any authentication errors occurred.
7270    */
7271   public RestRequest options(Object uri) throws RestCallException {
7272      return request(op("OPTIONS", uri, NO_BODY));
7273   }
7274
7275   /**
7276    * Same as {@link #patch(Object, Object)} but don't specify the input yet.
7277    *
7278    * <p>
7279    * You must call {@link RestRequest#content(Object)} to set the contents on the result object.
7280    *
7281    * @param uri
7282    *    The URI of the remote REST resource.
7283    *    <br>Can be any of the following types:
7284    *    <ul>
7285    *       <li>{@link URIBuilder}
7286    *       <li>{@link URI}
7287    *       <li>{@link URL}
7288    *       <li>{@link String}
7289    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
7290    *    </ul>
7291    * @return
7292    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
7293    *    as a parsed object.
7294    * @throws RestCallException REST call failed.
7295    */
7296   public RestRequest patch(Object uri) throws RestCallException {
7297      return request(op("PATCH", uri, NO_BODY));
7298   }
7299
7300   /**
7301    * Perform a <c>PATCH</c> request against the specified URI.
7302    *
7303    * @param uri
7304    *    The URI of the remote REST resource.
7305    *    <br>Can be any of the following types:
7306    *    <ul>
7307    *       <li>{@link URIBuilder}
7308    *       <li>{@link URI}
7309    *       <li>{@link URL}
7310    *       <li>{@link String}
7311    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
7312    *    </ul>
7313    * @param body
7314    *    The object to serialize and transmit to the URI as the body of the request.
7315    *    Can be of the following types:
7316    *    <ul class='spaced-list'>
7317    *       <li>
7318    *          {@link Reader} - Raw contents of {@code Reader} will be serialized to remote resource.
7319    *       <li>
7320    *          {@link InputStream} - Raw contents of {@code InputStream} will be serialized to remote resource.
7321    *       <li>
7322    *          {@link HttpResource} - Raw contents will be serialized to remote resource.  Additional headers and media type will be set on request.
7323    *       <li>
7324    *          {@link HttpEntity} - Bypass Juneau serialization and pass HttpEntity directly to HttpClient.
7325    *       <li>
7326    *          {@link Object} - POJO to be converted to text using the {@link Serializer} registered with the
7327    *          {@link RestClient}.
7328    *       <li>
7329    *          {@link PartList} - Converted to a URL-encoded FORM post.
7330    *       <li>
7331    *          {@link Supplier} - A supplier of anything on this list.
7332    *    </ul>
7333    * @return
7334    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
7335    *    as a parsed object.
7336    * @throws RestCallException If any authentication errors occurred.
7337    */
7338   public RestRequest patch(Object uri, Object body) throws RestCallException {
7339      return request(op("PATCH", uri, body));
7340   }
7341
7342   /**
7343    * Perform a <c>PATCH</c> request against the specified URI as a plain text body bypassing the serializer.
7344    *
7345    * @param uri
7346    *    The URI of the remote REST resource.
7347    *    <br>Can be any of the following types:
7348    *    <ul>
7349    *       <li>{@link URIBuilder}
7350    *       <li>{@link URI}
7351    *       <li>{@link URL}
7352    *       <li>{@link String}
7353    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
7354    *    </ul>
7355    * @param body
7356    *    The object to serialize and transmit to the URI as the body of the request bypassing the serializer.
7357    * @param contentType
7358    *    The content type of the request.
7359    * @return
7360    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
7361    *    as a parsed object.
7362    * @throws RestCallException If any authentication errors occurred.
7363    */
7364   public RestRequest patch(Object uri, String body, ContentType contentType) throws RestCallException {
7365      return request(op("PATCH", uri, stringBody(body))).header(contentType);
7366   }
7367
7368   /**
7369    * Same as {@link #post(Object, Object)} but don't specify the input yet.
7370    *
7371    * <p>
7372    * You must call either {@link RestRequest#content(Object)} or {@link RestRequest#formData(String, Object)} to set the
7373    * contents on the result object.
7374    *
7375    * <h5 class='section'>Notes:</h5><ul>
7376    *    <li class='note'>Use {@link #formPost(Object, Object)} for <c>application/x-www-form-urlencoded</c> form posts.
7377    * </ul>
7378    *
7379    * @param uri
7380    *    The URI of the remote REST resource.
7381    *    <br>Can be any of the following types:
7382    *    <ul>
7383    *       <li>{@link URIBuilder}
7384    *       <li>{@link URI}
7385    *       <li>{@link URL}
7386    *       <li>{@link String}
7387    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
7388    *    </ul>
7389    * @return
7390    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
7391    *    as a parsed object.
7392    * @throws RestCallException REST call failed.
7393    */
7394   public RestRequest post(Object uri) throws RestCallException {
7395      return request(op("POST", uri, NO_BODY));
7396   }
7397
7398   /**
7399    * Perform a <c>POST</c> request against the specified URI.
7400    *
7401    * <h5 class='section'>Notes:</h5><ul>
7402    *    <li class='note'>Use {@link #formPost(Object, Object)} for <c>application/x-www-form-urlencoded</c> form posts.
7403    * </ul>
7404    *
7405    * @param uri
7406    *    The URI of the remote REST resource.
7407    *    <br>Can be any of the following types:
7408    *    <ul>
7409    *       <li>{@link URIBuilder}
7410    *       <li>{@link URI}
7411    *       <li>{@link URL}
7412    *       <li>{@link String}
7413    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
7414    *    </ul>
7415    * @param body
7416    *    The object to serialize and transmit to the URI as the body of the request.
7417    *    Can be of the following types:
7418    *    <ul class='spaced-list'>
7419    *       <li>
7420    *          {@link Reader} - Raw contents of {@code Reader} will be serialized to remote resource.
7421    *       <li>
7422    *          {@link InputStream} - Raw contents of {@code InputStream} will be serialized to remote resource.
7423    *       <li>
7424    *          {@link Object} - POJO to be converted to text using the {@link Serializer} registered with the
7425    *          {@link RestClient}.
7426    *       <li>
7427    *          {@link HttpEntity} / {@link HttpResource} - Bypass Juneau serialization and pass HttpEntity directly to HttpClient.
7428    *       <li>
7429    *          {@link PartList} - Converted to a URL-encoded FORM post.
7430    *       <li>
7431    *          {@link Supplier} - A supplier of anything on this list.
7432    *    </ul>
7433    * @return
7434    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
7435    *    as a parsed object.
7436    * @throws RestCallException If any authentication errors occurred.
7437    */
7438   public RestRequest post(Object uri, Object body) throws RestCallException {
7439      return request(op("POST", uri, body));
7440   }
7441
7442   /**
7443    * Perform a <c>POST</c> request against the specified URI as a plain text body bypassing the serializer.
7444    *
7445    * @param uri
7446    *    The URI of the remote REST resource.
7447    *    <br>Can be any of the following types:
7448    *    <ul>
7449    *       <li>{@link URIBuilder}
7450    *       <li>{@link URI}
7451    *       <li>{@link URL}
7452    *       <li>{@link String}
7453    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
7454    *    </ul>
7455    * @param body
7456    *    The object to serialize and transmit to the URI as the body of the request bypassing the serializer.
7457    * @param contentType
7458    *    The content type of the request.
7459    * @return
7460    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
7461    *    as a parsed object.
7462    * @throws RestCallException If any authentication errors occurred.
7463    */
7464   public RestRequest post(Object uri, String body, ContentType contentType) throws RestCallException {
7465      return request(op("POST", uri, stringBody(body))).header(contentType);
7466   }
7467
7468   /**
7469    * Same as {@link #put(Object, Object)} but don't specify the input yet.
7470    *
7471    * <p>
7472    * You must call either {@link RestRequest#content(Object)} or {@link RestRequest#formData(String, Object)}
7473    * to set the contents on the result object.
7474    *
7475    * @param uri
7476    *    The URI of the remote REST resource.
7477    *    <br>Can be any of the following types:
7478    *    <ul>
7479    *       <li>{@link URIBuilder}
7480    *       <li>{@link URI}
7481    *       <li>{@link URL}
7482    *       <li>{@link String}
7483    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
7484    *    </ul>
7485    * @return
7486    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
7487    *    as a parsed object.
7488    * @throws RestCallException REST call failed.
7489    */
7490   public RestRequest put(Object uri) throws RestCallException {
7491      return request(op("PUT", uri, NO_BODY));
7492   }
7493
7494   /**
7495    * Perform a <c>PUT</c> request against the specified URI.
7496    *
7497    * @param uri
7498    *    The URI of the remote REST resource.
7499    *    <br>Can be any of the following types:
7500    *    <ul>
7501    *       <li>{@link URIBuilder}
7502    *       <li>{@link URI}
7503    *       <li>{@link URL}
7504    *       <li>{@link String}
7505    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
7506    *    </ul>
7507    * @param body
7508    *    The object to serialize and transmit to the URI as the body of the request.
7509    *    Can be of the following types:
7510    *    <ul class='spaced-list'>
7511    *       <li>
7512    *          {@link Reader} - Raw contents of {@code Reader} will be serialized to remote resource.
7513    *       <li>
7514    *          {@link InputStream} - Raw contents of {@code InputStream} will be serialized to remote resource.
7515    *       <li>
7516    *          {@link Object} - POJO to be converted to text using the {@link Serializer} registered with the
7517    *          {@link RestClient}.
7518    *       <li>
7519    *          {@link HttpEntity} / {@link HttpResource} - Bypass Juneau serialization and pass HttpEntity directly to HttpClient.
7520    *       <li>
7521    *          {@link PartList} - Converted to a URL-encoded FORM post.
7522    *       <li>
7523    *          {@link Supplier} - A supplier of anything on this list.
7524    *    </ul>
7525    * @return
7526    *    A {@link RestRequest} object that can be further tailored before executing the request
7527    *    and getting the response as a parsed object.
7528    * @throws RestCallException If any authentication errors occurred.
7529    */
7530   public RestRequest put(Object uri, Object body) throws RestCallException {
7531      return request(op("PUT", uri, body));
7532   }
7533
7534   /**
7535    * Perform a <c>PUT</c> request against the specified URI using a plain text body bypassing the serializer.
7536    *
7537    * @param uri
7538    *    The URI of the remote REST resource.
7539    *    <br>Can be any of the following types:
7540    *    <ul>
7541    *       <li>{@link URIBuilder}
7542    *       <li>{@link URI}
7543    *       <li>{@link URL}
7544    *       <li>{@link String}
7545    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
7546    *    </ul>
7547    * @param body
7548    *    The object to serialize and transmit to the URI as the body of the request bypassing the serializer.
7549    * @param contentType The content type of the request.
7550    * @return
7551    *    A {@link RestRequest} object that can be further tailored before executing the request
7552    *    and getting the response as a parsed object.
7553    * @throws RestCallException If any authentication errors occurred.
7554    */
7555   public RestRequest put(Object uri, String body, ContentType contentType) throws RestCallException {
7556      return request(op("PUT", uri, stringBody(body))).header(contentType);
7557   }
7558
7559   /**
7560    * Perform a generic REST call.
7561    *
7562    * @param method The HTTP method.
7563    *    <br>Cannot be <jk>null</jk>.
7564    * @param uri
7565    *    The URI of the remote REST resource.
7566    *    <br>Can be any of the following types:
7567    *    <ul>
7568    *       <li>{@link URIBuilder}
7569    *       <li>{@link URI}
7570    *       <li>{@link URL}
7571    *       <li>{@link String}
7572    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
7573    *    </ul>
7574    *    <br>Can be <jk>null</jk> (will result in an invalid request).
7575    * @return
7576    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
7577    *    as a parsed object.
7578    * @throws RestCallException If any authentication errors occurred.
7579    */
7580   public RestRequest request(String method, Object uri) throws RestCallException {
7581      return request(op(method, uri, NO_BODY));
7582   }
7583
7584   /**
7585    * Perform a generic REST call.
7586    *
7587    * <p>
7588    * Typically you're going to use {@link #request(String, Object)} or {@link #request(String, Object, Object)},
7589    * but this method is provided to allow you to perform non-standard HTTP methods (e.g. HTTP FOO).
7590    *
7591    * @param method The method name (e.g. <js>"GET"</js>, <js>"OPTIONS"</js>).
7592    *    <br>Cannot be <jk>null</jk>.
7593    * @param uri
7594    *    The URI of the remote REST resource.
7595    *    <br>Can be any of the following types:
7596    *    <ul>
7597    *       <li>{@link URIBuilder}
7598    *       <li>{@link URI}
7599    *       <li>{@link URL}
7600    *       <li>{@link String}
7601    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
7602    *    </ul>
7603    *    <br>Can be <jk>null</jk> (will result in an invalid request).
7604    * @param hasBody Boolean flag indicating if the specified request has content associated with it.
7605    * @return
7606    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
7607    *    as a parsed object.
7608    * @throws RestCallException If any authentication errors occurred.
7609    */
7610   public RestRequest request(String method, Object uri, boolean hasBody) throws RestCallException {
7611      return request(op(method, uri, NO_BODY).hasContent(hasBody));
7612   }
7613
7614   /**
7615    * Perform a generic REST call.
7616    *
7617    * @param method The HTTP method.
7618    *    <br>Cannot be <jk>null</jk>.
7619    * @param uri
7620    *    The URI of the remote REST resource.
7621    *    <br>Can be any of the following types:
7622    *    <ul>
7623    *       <li>{@link URIBuilder}
7624    *       <li>{@link URI}
7625    *       <li>{@link URL}
7626    *       <li>{@link String}
7627    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
7628    *    </ul>
7629    *    <br>Can be <jk>null</jk> (will result in an invalid request).
7630    * @param body
7631    *    The HTTP body content.
7632    *    Can be of the following types:
7633    *    <ul class='spaced-list'>
7634    *       <li>
7635    *          {@link Reader} - Raw contents of {@code Reader} will be serialized to remote resource.
7636    *       <li>
7637    *          {@link InputStream} - Raw contents of {@code InputStream} will be serialized to remote resource.
7638    *       <li>
7639    *          {@link HttpResource} - Raw contents will be serialized to remote resource.  Additional headers and media type will be set on request.
7640    *       <li>
7641    *          {@link HttpEntity} - Bypass Juneau serialization and pass HttpEntity directly to HttpClient.
7642    *       <li>
7643    *          {@link Object} - POJO to be converted to text using the {@link Serializer} registered with the
7644    *          {@link RestClient}.
7645    *       <li>
7646    *          {@link PartList} - Converted to a URL-encoded FORM post.
7647    *       <li>
7648    *          {@link Supplier} - A supplier of anything on this list.
7649    *    </ul>
7650    *    This parameter is IGNORED if the method type normally does not have content.
7651    * @return
7652    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
7653    *    as a parsed object.
7654    * @throws RestCallException If any authentication errors occurred.
7655    */
7656   public RestRequest request(String method, Object uri, Object body) throws RestCallException {
7657      return request(op(method, uri, body));
7658   }
7659
7660   private static RestOperation op(String method, Object url, Object body) {
7661      return RestOperation.of(method, url, body);
7662   }
7663
7664   private static Reader stringBody(String body) {
7665      return body == null ? null : new StringReader(s(body));
7666   }
7667
7668   /**
7669    * Creates a {@link RestRequest} object from the specified {@link HttpRequest} object.
7670    *
7671    * <p>
7672    * Subclasses can override this method to provide their own specialized {@link RestRequest} objects.
7673    *
7674    * @param uri The target.
7675    * @param method The HTTP method (uppercase).
7676    * @param hasBody Whether this method has a request entity.
7677    * @return A new {@link RestRequest} object.
7678    * @throws RestCallException If an exception or non-200 response code occurred during the connection attempt.
7679    */
7680   protected RestRequest createRequest(URI uri, String method, boolean hasBody) throws RestCallException {
7681      return new RestRequest(this, uri, method, hasBody);
7682   }
7683
7684   /**
7685    * Creates a {@link RestResponse} object from the specified {@link HttpResponse} object.
7686    *
7687    * <p>
7688    * Subclasses can override this method to provide their own specialized {@link RestResponse} objects.
7689    *
7690    * @param request The request creating this response.
7691    * @param httpResponse The response object to wrap.
7692    * @param parser The parser to use to parse the response.
7693    *
7694    * @return A new {@link RestResponse} object.
7695    * @throws RestCallException If an exception or non-200 response code occurred during the connection attempt.
7696    */
7697   protected RestResponse createResponse(RestRequest request, HttpResponse httpResponse, Parser parser) throws RestCallException {
7698      return new RestResponse(this, request, httpResponse, parser);
7699   }
7700
7701   @Override
7702   protected void finalize() throws Throwable {
7703      if (detectLeaks && ! isClosed.get() && ! keepHttpClientOpen) {
7704         var sb = new StringBuilder("WARNING:  RestClient garbage collected before it was finalized.");  // NOT DEBUG
7705         if (nn(creationStack)) {
7706            sb.append("\nCreation Stack:");  // NOT DEBUG
7707            for (var e : creationStack)
7708               sb.append("\n\t" + e);  // NOT DEBUG
7709         }
7710         log(WARNING, sb.toString());
7711      }
7712   }
7713
7714   /**
7715    * Returns the part parser associated with this client.
7716    *
7717    * @return The part parser associated with this client.
7718    */
7719   protected HttpPartParser getPartParser() { return partParser; }
7720
7721   /**
7722    * Returns the part parser instance of the specified type.
7723    *
7724    * @param c The part parser class.
7725    * @return The part parser.
7726    */
7727   protected HttpPartParser getPartParser(Class<? extends HttpPartParser> c) {
7728      var x = partParsers.get(c);
7729      if (x == null) {
7730         try {
7731            x = beanStore.createBean(c).run();
7732         } catch (ExecutableException e) {
7733            throw toRex(e);
7734         }
7735         partParsers.put(c, x);
7736      }
7737      return x;
7738   }
7739
7740   /**
7741    * Returns the part serializer associated with this client.
7742    *
7743    * @return The part serializer associated with this client.
7744    */
7745   protected HttpPartSerializer getPartSerializer() { return partSerializer; }
7746
7747   /**
7748    * Returns the part serializer instance of the specified type.
7749    *
7750    * @param c The part serializer class.
7751    * @return The part serializer.
7752    */
7753   protected HttpPartSerializer getPartSerializer(Class<? extends HttpPartSerializer> c) {
7754      var x = partSerializers.get(c);
7755      if (x == null) {
7756         try {
7757            x = beanStore.createBean(c).run();
7758         } catch (ExecutableException e) {
7759            throw toRex(e);
7760         }
7761         partSerializers.put(c, x);
7762      }
7763      return x;
7764   }
7765
7766   /**
7767    * Gets called add the end of the constructor call to perform any post-initialization.
7768    */
7769   protected void init() {}
7770
7771   /**
7772    * Returns <jk>true</jk> if empty request form-data parameter values should be ignored.
7773    *
7774    * @return <jk>true</jk> if empty request form-data parameter values should be ignored.
7775    */
7776   protected boolean isSkipEmptyFormData() { return skipEmptyFormData; }
7777
7778   /**
7779    * Returns <jk>true</jk> if empty request header values should be ignored.
7780    *
7781    * @return <jk>true</jk> if empty request header values should be ignored.
7782    */
7783   protected boolean isSkipEmptyHeaderData() { return skipEmptyHeaderData; }
7784
7785   /**
7786    * Returns <jk>true</jk> if empty request query parameter values should be ignored.
7787    *
7788    * @return <jk>true</jk> if empty request query parameter values should be ignored.
7789    */
7790   protected boolean isSkipEmptyQueryData() { return skipEmptyQueryData; }
7791
7792   /**
7793    * Logs a message.
7794    *
7795    * @param level The log level.
7796    * @param msg The message with {@link MessageFormat}-style arguments.
7797    * @param args The arguments.
7798    */
7799   protected void log(Level level, String msg, Object...args) {
7800      logger.log(level, f(msg, args));
7801      if (logToConsole)
7802         console.println(f(msg, args));
7803   }
7804
7805   /**
7806    * Logs a message.
7807    *
7808    * @param level The log level.
7809    * @param t Thrown exception.
7810    *    <br>Can be <jk>null</jk> (no exception stack trace will be logged).
7811    * @param msg The message.
7812    * @param args Optional message arguments.
7813    */
7814   protected void log(Level level, Throwable t, String msg, Object...args) {
7815      logger.log(level, t, fs(msg, args));
7816      if (logToConsole) {
7817         console.println(f(msg, args));
7818         if (nn(t))
7819            t.printStackTrace(console);
7820      }
7821   }
7822
7823   /**
7824    * Interceptor method called immediately after the RestRequest object is created and all headers/query/form-data has been set on the request from the client.
7825    *
7826    * <p>
7827    * Subclasses can override this method to handle any cleanup operations.
7828    *
7829    * <h5 class='section'>See Also:</h5><ul>
7830    *    <li class='jm'>{@link Builder#interceptors(Object...)}
7831    * </ul>
7832    *
7833    * @param req The HTTP request.
7834    * @param res The HTTP response.
7835    * @throws RestCallException If any of the interceptors threw an exception.
7836    */
7837   protected void onCallClose(RestRequest req, RestResponse res) throws RestCallException {
7838      try {
7839         for (var rci : interceptors)
7840            rci.onClose(req, res);
7841      } catch (RuntimeException | RestCallException e) {
7842         throw e;
7843      } catch (Exception e) {
7844         throw new RestCallException(res, e, "Interceptor threw an exception on close.");
7845      }
7846   }
7847
7848   /**
7849    * Interceptor method called immediately after an HTTP response has been received.
7850    *
7851    * <p>
7852    * Subclasses can override this method to intercept the response and perform special modifications.
7853    *
7854    * <h5 class='section'>See Also:</h5><ul>
7855    *    <li class='jm'>{@link Builder#interceptors(Object...)}
7856    * </ul>
7857    *
7858    * @param req The HTTP request.
7859    * @param res The HTTP response.
7860    * @throws RestCallException If any of the interceptors threw an exception.
7861    */
7862   protected void onCallConnect(RestRequest req, RestResponse res) throws RestCallException {
7863      try {
7864         for (var rci : interceptors)
7865            rci.onConnect(req, res);
7866      } catch (RuntimeException | RestCallException e) {
7867         throw e;
7868      } catch (Exception e) {
7869         throw new RestCallException(res, e, "Interceptor threw an exception on connect.");
7870      }
7871   }
7872
7873   /**
7874    * Interceptor method called immediately after the RestRequest object is created and all headers/query/form-data has been copied from the client.
7875    *
7876    * <p>
7877    * Subclasses can override this method to intercept the request and perform special modifications.
7878    *
7879    * <h5 class='section'>See Also:</h5><ul>
7880    *    <li class='jm'>{@link Builder#interceptors(Object...)}
7881    * </ul>
7882    *
7883    * @param req The HTTP request.
7884    * @throws RestCallException If any of the interceptors threw an exception.
7885    */
7886   protected void onCallInit(RestRequest req) throws RestCallException {
7887      try {
7888         for (var rci : interceptors)
7889            rci.onInit(req);
7890      } catch (RuntimeException | RestCallException e) {
7891         throw e;
7892      } catch (Exception e) {
7893         throw new RestCallException(null, e, "Interceptor threw an exception on init.");
7894      }
7895   }
7896
7897   @Override /* Overridden from BeanContextable */
7898   protected FluentMap<String,Object> properties() {
7899      return super.properties()
7900         .a("errorCodes", errorCodes)
7901         .a("executorService", executorService.get())
7902         .a("executorServiceShutdownOnClose", executorServiceShutdownOnClose)
7903         .a("headerData", headerData)
7904         .a("interceptors", interceptors)
7905         .a("keepHttpClientOpen", keepHttpClientOpen)
7906         .a("partParser", partParser)
7907         .a("partSerializer", partSerializer)
7908         .a("queryData", queryData)
7909         .a("rootUrl", rootUrl);
7910   }
7911
7912   /**
7913    * Perform an arbitrary request against the specified URI.
7914    *
7915    * <p>
7916    * All requests feed through this method so it can be used to intercept request creations and make modifications
7917    * (such as add headers).
7918    *
7919    * @param op The operation that identifies the HTTP method, URL, and optional payload.
7920    * @return
7921    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
7922    *    as a parsed object.
7923    * @throws RestCallException If any authentication errors occurred.
7924    */
7925   protected RestRequest request(RestOperation op) throws RestCallException {
7926      if (isClosed.get()) {
7927         var e2 = (Exception)null;
7928         if (nn(closedStack)) {
7929            e2 = new Exception("Creation stack:");
7930            e2.setStackTrace(closedStack);
7931            throw new RestCallException(null, e2, "RestClient.close() has already been called.  This client cannot be reused.");
7932         }
7933         throw new RestCallException(null, null,
7934            "RestClient.close() has already been called.  This client cannot be reused.  Closed location stack trace can be displayed by setting the system property 'org.apache.juneau.rest.client2.RestClient.trackCreation' to true.");
7935      }
7936
7937      var req = createRequest(toUri(op.getUri(), rootUrl), op.getMethod(), op.hasContent());
7938
7939      onCallInit(req);
7940
7941      req.content(op.getContent());
7942
7943      return req;
7944   }
7945
7946   /**
7947    * Entrypoint for executing all requests and returning a response.
7948    *
7949    * <p>
7950    * Subclasses can override this method to provide specialized handling.
7951    *
7952    * <p>
7953    * The behavior of this method can also be modified by specifying a different {@link RestCallHandler}.
7954    *
7955    * <h5 class='section'>See Also:</h5><ul>
7956    *    <li class='jm'>{@link Builder#callHandler()}
7957    * </ul>
7958    *
7959    * @param target The target host for the request.
7960    *    <br>Implementations may accept <jk>null</jk> if they can still determine a route, for example to a default
7961    *       target or by inspecting the request.
7962    * @param request The request to execute.
7963    * @param context The context to use for the execution, or <jk>null</jk> to use the default context.
7964    * @return
7965    *    The response to the request.
7966    *    <br>This is always a final response, never an intermediate response with an 1xx status code.
7967    *    <br>Whether redirects or authentication challenges will be returned or handled automatically depends on the
7968    *       implementation and configuration of this client.
7969    * @throws IOException In case of a problem or the connection was aborted.
7970    * @throws ClientProtocolException In case of an http protocol error.
7971    */
7972   protected HttpResponse run(HttpHost target, HttpRequest request, HttpContext context) throws ClientProtocolException, IOException {
7973      return callHandler.run(target, request, context);
7974   }
7975
7976   Object executeRemote(Class<?> interfaceClass, RestRequest rc, Method method, RemoteOperationMeta rom) throws Throwable {
7977      RemoteOperationReturn ror = rom.getReturns();
7978
7979      try {
7980         var ret = (Object)null;
7981         var res = (RestResponse)null;
7982         rc.rethrow(RuntimeException.class);
7983         rom.forEachException(x -> rc.rethrow(x));
7984         if (ror.getReturnValue() == RemoteReturn.NONE) {
7985            res = rc.complete();
7986         } else if (ror.getReturnValue() == RemoteReturn.STATUS) {
7987            res = rc.complete();
7988            int returnCode = res.getStatusCode();
7989            var rt = method.getReturnType();
7990            if (rt == Integer.class || rt == int.class)
7991               ret = returnCode;
7992            else if (rt == Boolean.class || rt == boolean.class)
7993               ret = returnCode < 400;
7994            else
7995               throw new RestCallException(res, null, "Invalid return type on method annotated with @RemoteOp(returns=RemoteReturn.STATUS).  Only integer and booleans types are valid.");
7996         } else if (ror.getReturnValue() == RemoteReturn.BEAN) {
7997            rc.ignoreErrors();
7998            res = rc.run();
7999            ret = res.as(ror.getResponseBeanMeta());
8000         } else {
8001            var rt = method.getReturnType();
8002            if (Throwable.class.isAssignableFrom(rt))
8003               rc.ignoreErrors();
8004            res = rc.run();
8005            Object v = res.getContent().as(ror.getReturnType());
8006            if (v == null && rt.isPrimitive())
8007               v = ClassInfo.of(rt).getPrimitiveDefault();
8008            ret = v;
8009         }
8010         return ret;
8011      } catch (RestCallException e) {
8012         Throwable t = e.getCause();
8013         if (t instanceof RuntimeException t2)
8014            throw t2;
8015         for (var t3 : method.getExceptionTypes())
8016            if (t3.isInstance(t))
8017               throw t;
8018         throw toRex(e);
8019      }
8020   }
8021
8022   ExecutorService getExecutorService() {
8023      ExecutorService result = executorService.get();
8024      if (nn(result))
8025         return result;
8026      synchronized (this) {
8027         result = executorService.get();
8028         if (nn(result))
8029            return result;
8030         result = new ThreadPoolExecutor(1, 1, 30, TimeUnit.SECONDS, new ArrayBlockingQueue<>(10));
8031         executorService.set(result);
8032         return result;
8033      }
8034   }
8035
8036   @SuppressWarnings("unchecked")
8037   <T extends Context> T getInstance(Class<T> c) {
8038      var o = requestContexts.get(c);
8039      if (o == null) {
8040         if (Serializer.class.isAssignableFrom(c)) {
8041            o = Serializer.createSerializerBuilder((Class<? extends Serializer>)c).beanContext(getBeanContext()).build();
8042         } else if (Parser.class.isAssignableFrom(c)) {
8043            o = Parser.createParserBuilder((Class<? extends Parser>)c).beanContext(getBeanContext()).build();
8044         }
8045         requestContexts.put(c, o);
8046      }
8047      return (T)o;
8048   }
8049
8050   /*
8051    * Returns the parser that best matches the specified content type.
8052    * If no match found or the content type is null, returns the parser in the list if it's a list of one.
8053    * Returns null if no parsers are defined.
8054    */
8055   Parser getMatchingParser(String mediaType) {
8056      if (parsers.isEmpty())
8057         return null;
8058      if (nn(mediaType)) {
8059         var p = parsers.getParser(mediaType);
8060         if (nn(p))
8061            return p;
8062      }
8063      var l = parsers.getParsers();
8064      return (l.size() == 1 ? l.get(0) : null);
8065   }
8066
8067   /*
8068    * Returns the serializer that best matches the specified content type.
8069    * If no match found or the content type is null, returns the serializer in the list if it's a list of one.
8070    * Returns null if no serializers are defined.
8071    */
8072   Serializer getMatchingSerializer(String mediaType) {
8073      if (serializers.isEmpty())
8074         return null;
8075      if (nn(mediaType)) {
8076         var s = serializers.getSerializer(mediaType);
8077         if (nn(s))
8078            return s;
8079      }
8080      var l = serializers.getSerializers();
8081      return (l.size() == 1 ? l.get(0) : null);
8082   }
8083
8084   boolean hasParsers() {
8085      return ! parsers.getParsers().isEmpty();
8086   }
8087
8088   boolean hasSerializers() {
8089      return ! serializers.getSerializers().isEmpty();
8090   }
8091
8092   URI toUri(Object x, String rootUrl) throws RestCallException {
8093      try {
8094         if (x instanceof URI x2)
8095            return x2;
8096         if (x instanceof URL x3)
8097            return x3.toURI();
8098         if (x instanceof URIBuilder x4)
8099            return x4.build();
8100         var s = x == null ? "" : x.toString();
8101         if (nn(rootUrl) && ! absUrlPattern.matcher(s).matches()) {
8102            if (s.isEmpty())
8103               s = rootUrl;
8104            else {
8105               var sb = new StringBuilder(rootUrl);
8106               if (! s.startsWith("/"))
8107                  sb.append('/');
8108               sb.append(s);
8109               s = sb.toString();
8110            }
8111         }
8112         s = fixUrl(s);
8113         return new URI(s);
8114      } catch (URISyntaxException e) {
8115         throw new RestCallException(null, e, "Invalid URI encountered:  {0}", x);  // Shouldn't happen.
8116      }
8117   }
8118}