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