001// ***************************************************************************************************************************
002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
003// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
005// * with the License.  You may obtain a copy of the License at                                                              *
006// *                                                                                                                         *
007// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
008// *                                                                                                                         *
009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
011// * specific language governing permissions and limitations under the License.                                              *
012// ***************************************************************************************************************************
013package org.apache.juneau.rest.client2;
014
015import static org.apache.juneau.internal.StringUtils.*;
016import static org.apache.juneau.AddFlag.*;
017import static org.apache.juneau.httppart.HttpPartType.*;
018import static org.apache.juneau.http.HttpMethod.*;
019import static java.util.logging.Level.*;
020import static org.apache.juneau.internal.StateMachineState.*;
021import static java.lang.Character.*;
022
023import java.io.*;
024import java.lang.reflect.*;
025import java.lang.reflect.Proxy;
026import java.net.*;
027import java.net.URI;
028import java.nio.charset.*;
029import java.text.*;
030import java.util.*;
031import java.util.concurrent.*;
032import java.util.function.*;
033import java.util.logging.*;
034import java.util.regex.*;
035
036import org.apache.http.*;
037import org.apache.http.client.*;
038import org.apache.http.client.config.*;
039import org.apache.http.client.entity.*;
040import org.apache.http.client.methods.*;
041import org.apache.http.client.utils.*;
042import org.apache.http.conn.*;
043import org.apache.http.entity.*;
044import org.apache.http.entity.BasicHttpEntity;
045import org.apache.http.impl.client.*;
046import org.apache.http.params.*;
047import org.apache.http.protocol.*;
048import org.apache.juneau.*;
049import org.apache.juneau.annotation.*;
050import org.apache.juneau.assertions.*;
051import org.apache.juneau.collections.*;
052import org.apache.juneau.http.remote.RemoteReturn;
053import org.apache.juneau.http.*;
054import org.apache.juneau.http.header.*;
055import org.apache.juneau.http.remote.*;
056import org.apache.juneau.httppart.*;
057import org.apache.juneau.httppart.bean.*;
058import org.apache.juneau.internal.*;
059import org.apache.juneau.marshall.*;
060import org.apache.juneau.oapi.*;
061import org.apache.juneau.parser.*;
062import org.apache.juneau.parser.ParseException;
063import org.apache.juneau.reflect.*;
064import org.apache.juneau.rest.client.remote.*;
065import org.apache.juneau.serializer.*;
066import org.apache.juneau.urlencoding.*;
067import org.apache.juneau.utils.*;
068
069/**
070 * Utility class for interfacing with remote REST interfaces.
071 *
072 * <p class='w900'>
073 * Built upon the feature-rich Apache HttpClient library, the Juneau RestClient API adds support for fluent-style
074 * REST calls and the ability to perform marshalling of POJOs to and from HTTP parts.
075 *
076 * <h5 class='figure'>Example:</h5>
077 * <p class='bcode w800'>
078 *    <jc>// Create a basic REST client with JSON support and download a bean.</jc>
079 *    MyBean <jv>bean</jv> = RestClient.<jsm>create</jsm>()
080 *       .simpleJson()
081 *       .build()
082 *       .get(<jsf>URI</jsf>)
083 *       .run()
084 *       .assertStatus().code().is(200)
085 *       .assertHeader(<js>"Content-Type"</js>).matchesSimple(<js>"application/json*"</js>)
086 *       .getBody().as(MyBean.<jk>class</jk>);
087 * </p>
088 *
089 * <p class='w900'>
090 * Breaking apart the fluent call, we can see the classes being used:
091 * <p class='bcode w800'>
092 *    RestClientBuilder <jv>builder</jv> = RestClient.<jsm>create</jsm>().simpleJson();
093 *    RestClient <jv>client</jv> = <jv>builder</jv>.build();
094 *    RestRequest <jv>req</jv> = <jv>client</jv>.get(<jsf>URI</jsf>);
095 *    RestResponse <jv>res</jv> = <jv>req</jv>.run();
096 *    RestResponseStatusLineAssertion <jv>statusLineAssertion</jv> = <jv>res</jv>.assertStatus();
097 *    FluentIntegerAssertion&lt;RestResponse&gt; <jv>codeAssertion</jv> = <jv>statusLineAssertion</jv>.code();
098 *    <jv>res</jv> = <jv>codeAssertion</jv>.is(200);
099 *    FluentStringAssertion&lt;RestResponse&gt; <jv>headerAssertion</jv> = <jv>res</jv>.assertHeader(<js>"Content-Type"</js>);
100 *    <jv>res</jv> = <jv>headerAssertion</jv>.matchesSimple(<js>"application/json*"</js>);
101 *    RestResponseBody <jv>body</jv> = <jv>res</jv>.getBody();
102 *    MyBean <jv>bean</jv> = <jv>body</jv>.as(MyBean.<jk>class</jk>);
103 * </p>
104 *
105 * <p class='w900'>
106 * It additionally provides support for creating remote proxy interfaces using REST as the transport medium.
107 *
108 * <h5 class='figure'>Example:</h5>
109 * <p class='bcode w800'>
110 *    <jc>// Define a Remote proxy for interacting with a REST interface.</jc>
111 *    <ja>@Remote</ja>(path=<js>"/petstore"</js>)
112 *    <jk>public interface</jk> PetStore {
113 *
114 *       <ja>@RemoteMethod</ja>(httpMethod=<jsf>POST</jsf>, path=<js>"/pets"</js>)
115 *       Pet addPet(
116 *          <ja>@Body</ja> CreatePet <jv>pet</jv>,
117 *          <ja>@Header</ja>(<js>"E-Tag"</js>) UUID <jv>etag</jv>,
118 *          <ja>@Query</ja>(<js>"debug"</js>) <jk>boolean</jk> <jv>debug</jv>
119 *       );
120 *    }
121 *
122 *    <jc>// Use a RestClient with default Simple JSON support.</jc>
123 *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().simpleJson().build();
124 *
125 *    PetStore <jv>store</jv> = <jv>client</jv>.getRemote(PetStore.<jk>class</jk>, <js>"http://localhost:10000"</js>);
126 *    CreatePet <jv>createPet</jv> = <jk>new</jk> CreatePet(<js>"Fluffy"</js>, 9.99);
127 *    Pet <jv>pet</jv> = <jv>store</jv>.addPet(<jv>createPet</jv>, UUID.<jsm>randomUUID</jsm>(), <jk>true</jk>);
128 * </p>
129 *
130 * <p class='w900'>
131 * The classes are closely tied to Apache HttpClient, yet provide lots of additional functionality:
132 * <ul class='javatree'>
133 *    <li class='jc'>{@link RestClient} <jk>extends</jk> {@link HttpClient}, creates {@link RestRequest} objects.
134 *    <li class='jc'>{@link RestRequest} <jk>extends</jk> {@link HttpUriRequest}, creates {@link RestResponse} objects.
135 *    <li class='jc'>{@link RestResponse} <jk>extends</jk> {@link HttpResponse}, creates {@link RestResponseBody} and {@link RestResponseHeader} objects.
136 *    <li class='jc'>{@link RestResponseBody} <jk>extends</jk> {@link HttpEntity}
137 *    <li class='jc'>{@link RestResponseHeader} <jk>extends</jk> {@link Header}
138 * </ul>
139 *
140 *
141 * <p class='w900'>
142 * Instances of this class are built using the {@link RestClientBuilder} class which can be constructed using
143 * the {@link #create() RestClient.create()} method as shown above.
144 *
145 * <p class='w900'>
146 * Clients are typically created with a root URI so that relative URIs can be used when making requests.
147 * This is done using the {@link RestClientBuilder#rootUri(Object)} method.
148 *
149 * <h5 class='figure'>Example:</h5>
150 * <p class='bcode w800'>
151 *    <jc>// Create a client where all URIs are relative to localhost.</jc>
152 *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().json().rootUri(<js>"http://localhost:5000"</js>).build();
153 *
154 *    <jc>// Use relative paths.</jc>
155 *    String <jv>body</jv> = <jv>client</jv>.get(<js>"/subpath"</js>).run().getBody().asString();
156 * </p>
157 *
158 * <p class='w900'>
159 * The {@link RestClient} class creates {@link RestRequest} objects using the following methods:
160 *
161 * <ul class='javatree'>
162 *    <li class='jc'>{@link RestClient}
163 *    <ul>
164 *       <li class='jm'>{@link RestClient#get(Object) get(uri)} / {@link RestClient#get() get()}
165 *       <li class='jm'>{@link RestClient#put(Object,Object) put(uri,body)} / {@link RestClient#put(Object) put(uri)}
166 *       <li class='jm'>{@link RestClient#post(Object) post(uri,body)} / {@link RestClient#post(Object) post(uri)}
167 *       <li class='jm'>{@link RestClient#patch(Object,Object) patch(uri,body)} / {@link RestClient#patch(Object) patch(uri)}
168 *       <li class='jm'>{@link RestClient#delete(Object) delete(uri)}
169 *       <li class='jm'>{@link RestClient#head(Object) head(uri)}
170 *       <li class='jm'>{@link RestClient#options(Object) options(uri)}
171 *       <li class='jm'>{@link RestClient#formPost(Object,Object) formPost(uri,body)} / {@link RestClient#formPost(Object) formPost(uri)}
172 *       <li class='jm'>{@link RestClient#formPostPairs(Object,Object...) formPostPairs(uri,parameters...)}
173 *       <li class='jm'>{@link RestClient#request(String,Object,Object) request(method,uri,body)}
174 *    </ul>
175 * </ul>
176 *
177 * <p class='w900'>
178 * The {@link RestRequest} class creates {@link RestResponse} objects using the following methods:
179 *
180 * <ul class='javatree'>
181 *    <li class='jc'>{@link RestRequest}
182 *    <ul>
183 *       <li class='jm'>{@link RestRequest#run() run()}
184 *       <li class='jm'>{@link RestRequest#complete() complete()}
185 *    </ul>
186 * </ul>
187 *
188 * <p class='w900'>
189 * The distinction between the two methods is that {@link RestRequest#complete() complete()} automatically consumes the response body and
190 * {@link RestRequest#run() run()} does not.  Note that you must consume response bodies in order for HTTP connections to be freed up
191 * for reuse!  The {@link InputStream InputStreams} returned by the {@link RestResponseBody} object are auto-closing once
192 * they are exhausted, so it is often not necessary to explicitly close them.
193 *
194 * <p class='w900'>
195 * The following examples show the distinction between the two calls:
196 *
197 * <p class='bcode w800'>
198 *    <jc>// Consuming the response, so use run().</jc>
199 *    String <jv>body</jv> = <jv>client</jv>.get(<jsf>URI</jsf>).run().getBody().asString();
200 *
201 *    <jc>// Only interested in response status code, so use complete().</jc>
202 *   <jk>int</jk> <jv>status</jv> = <jv>client</jv>.get(<jsf>URI</jsf>).complete().getStatusCode();
203 * </p>
204 *
205 *
206 * <h4 class='topic'>POJO Marshalling</h4>
207 *
208 * <p class='w900'>
209 * By default, JSON support is provided for HTTP request and response bodies.
210 * Other languages can be specified using any of the following builder methods:
211 * <ul class='javatree'>
212 *    <li class='jc'>{@link RestClientBuilder}
213 *    <ul>
214 *       <li class='jm'>{@link RestClientBuilder#json() json()}
215 *       <li class='jm'>{@link RestClientBuilder#simpleJson() simpleJson()}
216 *       <li class='jm'>{@link RestClientBuilder#xml() xml()}
217 *       <li class='jm'>{@link RestClientBuilder#html() html()}
218 *       <li class='jm'>{@link RestClientBuilder#plainText() plainText()}
219 *       <li class='jm'>{@link RestClientBuilder#msgPack() msgPack()}
220 *       <li class='jm'>{@link RestClientBuilder#uon() uon()}
221 *       <li class='jm'>{@link RestClientBuilder#urlEnc() urlEnc()}
222 *       <li class='jm'>{@link RestClientBuilder#openApi() openApi()}
223 *    </ul>
224 * </ul>
225 *
226 * <h5 class='figure'>Example:</h5>
227 * <p class='bcode w800'>
228 *    <jc>// Create a basic REST client with Simplified-JSON support.</jc>
229 *    <jc>// Typically easier to use when performing unit tests.</jc>
230 *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().simpleJson().build();
231 * </p>
232 *
233 * <p>
234 * Clients can also support multiple languages:
235 *
236 * <h5 class='figure'>Example:</h5>
237 * <p class='bcode w800'>
238 *    <jc>// Create a REST client with support for multiple languages.</jc>
239 *    RestClient <jv>client1</jv> = RestClient.<jsm>create</jsm>().json().xml().openApi().build();
240 *
241 *    <jc>// Create a REST client with support for all supported languages.</jc>
242 *    RestClient <jv>client2</jv> = RestClient.<jsm>create</jsm>().universal().build();
243 * </p>
244 *
245 * <p class='w900'>
246 * When using clients with multiple language support, you must specify the <c>Content-Type</c> header on requests
247 * with bodies to specify which serializer should be selected.
248 *
249 * <p class='bcode w800'>
250 *    <jc>// Create a REST client with support for multiple languages.</jc>
251 *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().universal().build();
252 *
253 *    <jv>client</jv>
254 *       .post(<jsf>URI</jsf>, <jv>myBean</jv>)
255 *       .contentType(<js>"application/json"</js>)
256 *       .complete()
257 *       .assertStatus().is(200);
258 * </p>
259 *
260 * <p>
261 * Languages can also be specified per-request.
262 *
263 * <p class='bcode w800'>
264 *    <jc>// Create a REST client with no default languages supported.</jc>
265 *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().build();
266 *
267 *    <jc>// Use JSON for this request.</jc>
268 *    <jv>client</jv>
269 *       .post(<jsf>URI</jsf>, <jv>myBean</jv>)
270 *       .json()
271 *       .complete()
272 *       .assertStatus().is(200);
273 * </p>
274 *
275 *
276 * <p class='w900'>
277 * The {@link RestClientBuilder} class provides convenience methods for setting common serializer and parser
278 * settings.
279 *
280 * <h5 class='figure'>Example:</h5>
281 * <p class='bcode w800'>
282 *    <jc>// Create a basic REST client with JSON support.</jc>
283 *    <jc>// Use single-quotes and whitespace.</jc>
284 *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().json().sq().ws().build();
285 *
286 *    <jc>// Same, but using properties.</jc>
287 *    RestClient <jv>client2</jv> = RestClient
288 *       .<jsm>create</jsm>()
289 *       .json()
290 *       .set(<jsf>WSERIALIZER_quoteChar</jsf>, <js>'\''</js>)
291 *       .set(<jsf>WSERIALIZER_useWhitespace</jsf>, <jk>true</jk>)
292 *       .build();
293 * </p>
294 *
295 * <p class='w900'>
296 *    Other methods are also provided for specifying the serializers and parsers used for lower-level marshalling support:
297 * <ul class='javatree'>
298 *    <li class='jc'>{@link RestClientBuilder}
299 *    <ul>
300 *       <li class='jm'>{@link RestClientBuilder#serializer(Serializer) serializer(Serializer)}
301 *       <li class='jm'>{@link RestClientBuilder#parser(Parser) parser(Parser)}
302 *       <li class='jm'>{@link RestClientBuilder#marshall(Marshall) marshall(Marshall)}
303 *    </ul>
304 * </ul>
305 *
306 * <p class='w900'>
307 * HTTP parts (headers, query parameters, form data...) are serialized and parsed using the {@link HttpPartSerializer}
308 * and {@link HttpPartParser} APIs.  By default, clients are configured to use {@link OpenApiSerializer} and
309 * {@link OpenApiParser}.  These can be overridden using the following methods:
310 * <ul class='javatree'>
311 *    <li class='jc'>{@link RestClientBuilder}
312 *    <ul>
313 *       <li class='jm'>{@link RestClientBuilder#partSerializer(Class) partSerializer(Class&lt;? extends HttpPartSerializer>)}
314 *       <li class='jm'>{@link RestClientBuilder#partParser(Class) partParser(Class&lt;? extends HttpPartParser>)}
315 *    </ul>
316 * </ul>
317 *
318 *
319 * <h4 class='topic'>Request Headers</h4>
320 * <p class='w900'>
321 * Per-client or per-request headers can be specified using the following methods:
322 * <ul class='javatree'>
323 *    <li class='jc'>{@link RestClientBuilder}
324 *    <ul>
325 *       <li class='jm'>{@link RestClientBuilder#header(String,Object) header(String,Object)}
326 *       <li class='jm'>{@link RestClientBuilder#header(String,Object,HttpPartSchema) header(String,Object,HttpPartSchema)}
327 *       <li class='jm'>{@link RestClientBuilder#header(String,Supplier) header(String,Supplier&lt;?&gt;)}
328 *       <li class='jm'>{@link RestClientBuilder#header(String,Supplier,HttpPartSchema) header(String,Supplier&lt;?&gt;,HttpPartSchema)}
329 *       <li class='jm'>{@link RestClientBuilder#header(Header) header(Header)}
330 *       <li class='jm'>{@link RestClientBuilder#headers(Object...) headers(Object...)}
331 *       <li class='jm'>{@link RestClientBuilder#headerPairs(Object...) headerPairs(Object...)}
332 *    </ul>
333 *    <li class='jc'>{@link RestRequest}
334 *    <ul>
335 *       <li class='jm'>{@link RestRequest#header(String,Object) header(String,Object)}
336 *       <li class='jm'>{@link RestRequest#header(String,Object,HttpPartSchema) header(String,Object,HttpPartSchema)}
337 *       <li class='jm'>{@link RestRequest#header(AddFlag,String,Object) header(AddFlag,String,Object)}
338 *       <li class='jm'>{@link RestRequest#header(AddFlag,String,Object,HttpPartSchema) header(AddFlag,String,Object,HttpPartSchema)}
339 *       <li class='jm'>{@link RestRequest#header(Header) header(Header)}
340 *       <li class='jm'>{@link RestRequest#headers(Object...) headers(Object...)}
341 *       <li class='jm'>{@link RestRequest#headers(AddFlag,Object...) headers(AddFlag;Object...)}
342 *       <li class='jm'>{@link RestRequest#headerPairs(Object...) headers(Object...)}
343 *    </ul>
344 * </ul>
345 *
346 * <p>
347 * Additionally, methods are provided on the client builder and per request for all standard HTTP headers
348 * such as {@link RestClientBuilder#authorization(Object) authorization(Object)}.
349 *
350 * <h5 class='figure'>Example:</h5>
351 * <p class='bcode w800'>
352 *    <jc>// Create a client that adds an Authorization header to every request.</jc>
353 *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().authorization(<js>"Foo"</js>).build();
354 *
355 *    <jc>// Or do it per-request.</jc>
356 *    String <jv>response</jv> = <jv>client</jv>.get(<jsf>URI</jsf>).authorization(<js>"Foo"</js>).run().getBody().asString();
357 *
358 *    <jc>// Or use an HttpHeader.</jc>
359 *    <jv>response</jv> = <jv>client</jv>.get(<jsf>URI</jsf>).headers(Authorization.<jsm>of</jsm>(<js>"Foo"</js>)).run().getBody().asString();
360 * </p>
361 *
362 * <p class='w900'>
363 * The supplier methods are particularly useful for header values whose values may change over time (such as <c>Authorization</c> headers
364 * which may need to change every few minutes).
365 * </p>
366 *
367 * <h5 class='figure'>Example:</h5>
368 * <p class='bcode w800'>
369 *    <jc>// Create a client that adds a dynamic Authorization header to every request.</jc>
370 *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().header(<js>"Authorization"</js>, ()-&gt;getMyAuthToken()).build();
371 * </p>
372 *
373 * <p>
374 * The {@link HttpPartSchema} API allows you to define OpenAPI schemas to POJO data structures on both requests
375 * and responses.
376 *
377 * <h5 class='figure'>Example:</h5>
378 * <p class='bcode w800'>
379 *    <jc>// Create a client that adds a header "Foo: bar|baz" to every request.</jc>
380 *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>()
381 *       .header(<js>"Foo"</js>, AList.<jsm>of</jsm>(<js>"bar"</js>,<js>"baz"</js>), <jsf>T_ARRAY_PIPES</jsf>)
382 *       .build();
383 * </p>
384 *
385 * <p>
386 * The methods with {@link AddFlag} parameters allow you to control whether new headers get appended, prepended, or
387 * replace existing headers with the same name.
388 *
389 * <ul class='notes'>
390 *    <li>Methods that pass in POJOs convert values to strings using the part serializers.  Methods that pass in <c>Header</c> or
391 *       <c>NameValuePair</c> objects use the values returned by that bean directly.
392 * </ul>
393 *
394 *
395 * <h4 class='topic'>Request Query Parameters</h4>
396 * <p>
397 * Per-client or per-request query parameters can be specified using the following methods:
398 * <ul class='javatree'>
399 *    <li class='jc'>{@link RestClientBuilder}
400 *    <ul>
401 *       <li class='jm'>{@link RestClientBuilder#query(String,Object) query(String,Object)}
402 *       <li class='jm'>{@link RestClientBuilder#query(String,Object,HttpPartSchema) query(String,Object,HttpPartSchema)}
403 *       <li class='jm'>{@link RestClientBuilder#query(String,Supplier) query(String,Supplier&lt;?&gt;)}
404 *       <li class='jm'>{@link RestClientBuilder#query(String,Supplier,HttpPartSchema) query(String,Supplier&lt;?&gt;,HttpPartSchema)}
405 *       <li class='jm'>{@link RestClientBuilder#queries(Object...) queries(Object...)}
406 *       <li class='jm'>{@link RestClientBuilder#queryPairs(Object...) queryPairs(Object...)}
407 *    </ul>
408 *    <li class='jc'>{@link RestRequest}
409 *    <ul>
410 *       <li class='jm'>{@link RestRequest#query(String,Object) query(String,Object)}
411 *       <li class='jm'>{@link RestRequest#query(AddFlag,String,Object) query(AddFlag,String,Object)}
412 *       <li class='jm'>{@link RestRequest#queries(Object...) queries(Object...)}
413 *       <li class='jm'>{@link RestRequest#queries(AddFlag,Object...) queries(AddFlag,Object...)}
414 *       <li class='jm'>{@link RestRequest#queryPairs(Object...) queryPairs(Object...)}
415 *       <li class='jm'>{@link RestRequest#queryCustom(Object) queryCustom(Object)}
416 *    </ul>
417 * </ul>
418 *
419 * <h5 class='figure'>Example:</h5>
420 * <p class='bcode w800'>
421 *    <jc>// Create a client that adds a ?foo=bar query parameter to every request.</jc>
422 *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().query(<js>"foo"</js>, <js>"bar"</js>).build();
423 *
424 *    <jc>// Or do it on every request.</jc>
425 *    String <jv>response</jv> = <jv>client</jv>.get(<jsf>URI</jsf>).query(<js>"foo"</js>, <js>"bar"</js>).run().getBody().asString();
426 * </p>
427 *
428 * <ul class='notes'>
429 *    <li>Like header values, dynamic values and OpenAPI schemas are supported.
430 *    <li>Methods that pass in POJOs convert values to strings using the part serializers.  Methods that pass in <c>NameValuePair</c>
431 *       objects use the values returned by that bean directly.
432 * </ul>
433 *
434 *
435 * <h4 class='topic'>Request Form Data</h4>
436 *
437 * <p class='w900'>
438 * Per-client or per-request form-data parameters can be specified using the following methods:
439 * <ul class='javatree'>
440 *    <li class='jc'>{@link RestClientBuilder}
441 *    <ul>
442 *       <li class='jm'>{@link RestClientBuilder#formData(String,Object) formData(String,Object)}
443 *       <li class='jm'>{@link RestClientBuilder#formData(String,Object,HttpPartSchema) formData(String,Object,HttpPartSchema)}
444 *       <li class='jm'>{@link RestClientBuilder#formData(String,Supplier) formData(String,Supplier&lt;?&gt;)}
445 *       <li class='jm'>{@link RestClientBuilder#formData(String,Supplier,HttpPartSchema) formData(String,Supplier&lt;?&gt;,HttpPartSchema)}
446 *       <li class='jm'>{@link RestClientBuilder#formDatas(Object...) formDatas(Object...)}
447 *       <li class='jm'>{@link RestClientBuilder#formDataPairs(Object...) formDataPairs(Object...)}
448 *    </ul>
449 *    <li class='jc'>{@link RestRequest}
450 *    <ul>
451 *       <li class='jm'>{@link RestRequest#formData(String,Object) formData(String,Object)}
452 *       <li class='jm'>{@link RestRequest#formData(AddFlag,String,Object) formData(AddFlag,String,Object)}
453 *       <li class='jm'>{@link RestRequest#formDatas(Object...) formDatas(Object...)}
454 *       <li class='jm'>{@link RestRequest#formDatas(AddFlag,Object...) formDatas(AddFlag,Object...)}
455 *       <li class='jm'>{@link RestRequest#formDataPairs(Object...) formDataPairs(Object...)}
456 *       <li class='jm'>{@link RestRequest#formDataCustom(Object) formDataCustom(Object)}
457 *    </ul>
458 * </ul>
459 *
460 * <ul class='notes'>
461 *    <li>Like header values, dynamic values and OpenAPI schemas are supported.
462 *    <li>Methods that pass in POJOs convert values to strings using the part serializers.  Methods that pass in <c>NameValuePair</c>
463 *       objects use the values returned by that bean directly.
464 * </ul>
465 *
466 *
467 * <h4 class='topic'>Request Body</h4>
468 *
469 * <p class='w900'>
470 * The request body can either be passed in with the client creator method (e.g. {@link RestClient#post(Object,Object) post(uri,body)}),
471 * or can be specified via the following methods:
472 *
473 * <ul class='javatree'>
474 *    <li class='jc'>{@link RestRequest}
475 *    <ul>
476 *       <li class='jm'>{@link RestRequest#body(Object) body(Object)}
477 *       <li class='jm'>{@link RestRequest#body(Object,HttpPartSchema) body(Object,HttpPartSchema)}
478 *    </ul>
479 * </ul>
480 *
481 * <p class='w900'>
482 * The request body can be any of the following types:
483 * <ul class='javatree'>
484 *       <li class='jc'>
485 *          {@link Object} - POJO to be converted to text using the {@link Serializer} defined on the client or request.
486 *       <li class='jc'>
487 *          {@link Reader} - Raw contents of {@code Reader} will be serialized to remote resource.
488 *       <li class='jc'>
489 *          {@link InputStream} - Raw contents of {@code InputStream} will be serialized to remote resource.
490 *       <li class='jc'>
491 *          {@link HttpResource}/{@link BasicHttpResource} - Raw contents will be serialized to remote resource.  Additional headers and media type will be set on request.
492 *       <li class='jc'>
493 *          {@link HttpEntity}/{@link BasicHttpEntity} - Bypass Juneau serialization and pass HttpEntity directly to HttpClient.
494 *       <li class='jc'>
495 *          {@link NameValuePairSupplier} - Converted to a URL-encoded FORM post.
496 *       <li class='jc'>
497 *          {@link Supplier} - A supplier of anything on this list.
498 *    </ul>
499 *
500 * <ul class='notes'>
501 *    <li>If the serializer on the client or request is explicitly set to <jk>null</jk>, POJOs will be converted to strings
502 *       using the registered part serializer as content type <js>"text/plain</js>.  If the part serializer is also <jk>null</jk>,
503 *       POJOs will be converted to strings using {@link ClassMeta#toString(Object)} which typically just calls {@link Object#toString()}.
504 * </ul>
505 *
506 *
507 * <h4 class='topic'>Response Status</h4>
508 *
509 * <p class='w900'>
510 * After execution using {@link RestRequest#run()} or {@link RestRequest#complete()}, the following methods can be used
511 * to get the response status:
512 *
513 * <ul class='javatree'>
514 *    <li class='jc'>{@link RestResponse}
515 *    <ul>
516 *       <li class='jm'><c>{@link RestResponse#getStatusLine() getStatusLine()} <jk>returns</jk> {@link StatusLine}</c>
517 *       <li class='jm'><c>{@link RestResponse#getStatusCode() getStatusCode()} <jk>returns</jk> <jk>int</jk></c>
518 *       <li class='jm'><c>{@link RestResponse#getReasonPhrase() getReasonPhrase()} <jk>returns</jk> String</c>
519 *       <li class='jm'><c>{@link RestResponse#assertStatus() assertStatus()} <jk>returns</jk> {@link RestResponseStatusLineAssertion}</c>
520 *    </ul>
521 * </ul>
522 *
523 * <h5 class='figure'>Example:</h5>
524 * <p class='bcode w800'>
525 *    <jc>// Only interested in status code.</jc>
526 *    <jk>int</jk> <jv>statusCode</jv> = <jv>client</jv>.get(<jsf>URI</jsf>).complete().getStatusCode();
527 * </p>
528 *
529 * <p class='w900'>
530 * Equivalent methods with mutable parameters are provided to allow access to status values without breaking fluent call chains.
531 *
532 * <h5 class='figure'>Example:</h5>
533 * <p class='bcode w800'>
534 *    <jc>// Interested in multiple values.</jc>
535 *    Mutable&lt;Integer&gt; <jv>statusCode</jv> = Mutable.<jsm>create</jsm>();
536 *    Mutable&lt;String&gt; <jv>reasonPhrase</jv> = Mutable.<jsm>create</jsm>();
537 *
538 *    <jv>client</jv>.get(<jsf>URI</jsf>).complete().getStatusCode(<jv>statusCode</jv>).getReasonPhrase(<jv>reasonPhrase</jv>);
539 *    System.<jsf>err</jsf>.println(<js>"statusCode="</js>+<jv>statusCode</jv>.get()+<js>", reasonPhrase="</js>+<jv>reasonPhrase</jv>.get());
540 * </p>
541 *
542 * <ul class='notes'>
543 *    <li>If you are only interested in the response status and not the response body, be sure to use {@link RestRequest#complete()} instead
544 *       of {@link RestRequest#run()} to make sure the response body gets automatically cleaned up.  Otherwise you must
545 *       consume the response yourself.
546 * </ul>
547 *
548 * <p class='w900'>
549 * The assertion method is provided for quickly asserting status codes in fluent calls.
550 *
551 * <h5 class='figure'>Example:</h5>
552 * <p class='bcode w800'>
553 *    <jc>// Status assertion using a static value.</jc>
554 *    String <jv>body</jv> = <jv>client</jv>.get(<jsf>URI</jsf>)
555 *       .run()
556 *       .assertStatus().code().isBetween(200,399)
557 *       .getBody().asString();
558 *
559 *    <jc>// Status assertion using a predicate.</jc>
560 *    String <jv>body</jv> = <jv>client</jv>.get(<jsf>URI</jsf>)
561 *       .run()
562 *       .assertStatus().code().passes(<jv>x</jv> -&gt; <jv>x</jv>&lt;400)
563 *       .getBody().asString();
564 * </p>
565 *
566 *
567 * <h4 class='topic'>Response Headers</h4>
568 *
569 * <p class='w900'>
570 * Response headers are accessed through the following methods:
571 *
572 * <ul class='javatree'>
573 *    <li class='jc'>{@link RestResponse}
574 *    <ul>
575 *       <li class='jm'><c>{@link RestResponse#getHeader(String) getHeader(String)} <jk>returns</jk> {@link RestResponseHeader}</c>
576 *       <li class='jm'><c>{@link RestResponse#getHeaders(String) getHeaders(String)} <jk>returns</jk> {@link RestResponseHeader}[]</c>
577 *       <li class='jm'><c>{@link RestResponse#getFirstHeader(String) getFirstHeader(String)} <jk>returns</jk> {@link RestResponseHeader}</c>
578 *       <li class='jm'><c>{@link RestResponse#getLastHeader(String) getLastHeader(String)} <jk>returns</jk> {@link RestResponseHeader}</c>
579 *       <li class='jm'><c>{@link RestResponse#getAllHeaders() getAllHeaders()} <jk>returns</jk> {@link RestResponseHeader}[]</c>
580 *       <li class='jm'><c>{@link RestResponse#getStringHeader(String) getStringHeader(String)} <jk>returns</jk> String</c>
581 *       <li class='jm'><c>{@link RestResponse#containsHeader(String) containsHeader(String)} <jk>returns</jk> <jk>boolean</jk></c>
582 *    </ul>
583 * </ul>
584 *
585 * <p class='w900'>
586 * Unlike {@link RestResponse#getFirstHeader(String)} and {@link RestResponse#getLastHeader(String)}, the {@link RestResponse#getHeader(String)}
587 * method returns an empty {@link RestResponseHeader} object instead of returning <jk>null</jk>.
588 * This allows it to be used more easily in fluent calls.
589 *
590 * <h5 class='figure'>Example:</h5>
591 * <p class='bcode w800'>
592 *    <jc>// See if response contains Location header.</jc>
593 *    <jk>boolean</jk> <jv>hasLocationHeader</jv> = client.get(<jsf>URI</jsf>).complete().getHeader(<js>"Location"</js>).exists();
594 * </p>
595 *
596 * <p class='w900'>
597 * The {@link RestResponseHeader} class extends from the HttpClient {@link Header} class and provides several convenience
598 * methods:
599 *
600 * <ul class='javatree'>
601 *    <li class='jc'>{@link RestResponseHeader}
602 *    <ul>
603 *       <li class='jm'><c>{@link RestResponseHeader#exists() exists()} <jk>returns</jk> <jk>boolean</jk></c>
604 *       <li class='jm'><c>{@link RestResponseHeader#asString() asString()} <jk>returns</jk> String</c>
605 *       <li class='jm'><c>{@link RestResponseHeader#asOptionalString() asOptionalString()} <jk>returns</jk> Optional&lt;String&gt;</c>
606 *       <li class='jm'><c>{@link RestResponseHeader#asStringOrElse(String) asStringOrElse(String)} <jk>returns</jk> String</c>
607 *       <li class='jm'><c>{@link RestResponseHeader#as(Type,Type...) as(Type,Type...)} <jk>returns</jk> T</c>
608 *       <li class='jm'><c>{@link RestResponseHeader#as(Class) as(Class&lt;T&gt;)} <jk>returns</jk> T</c>
609 *       <li class='jm'><c>{@link RestResponseHeader#asOptional(Type,Type...) asOptional(Type,Type...)} <jk>returns</jk> Optional&lt;T&gt;</c>
610 *       <li class='jm'><c>{@link RestResponseHeader#asOptional(Class) asOptional(Class&lt;T&gt;)} <jk>returns</jk> Optional&lt;T&gt;</c>
611 *       <li class='jm'><c>{@link RestResponseHeader#asMatcher(Pattern) asMatcher(Pattern)} <jk>returns</jk> {@link Matcher}</c>
612 *       <li class='jm'><c>{@link RestResponseHeader#asMatcher(String) asMatcher(String)} <jk>returns</jk> {@link Matcher}</c>
613 *       <li class='jm'><c>{@link RestResponseHeader#asHeader(Class) asHeader(Class&lt;T <jk>extends</jk> BasicHeader&gt; c)} <jk>returns</jk> {@link BasicHeader}</c>
614 *       <li class='jm'><c>{@link RestResponseHeader#asStringHeader() asStringHeader()} <jk>returns</jk> {@link BasicIntegerHeader}</c>
615 *       <li class='jm'><c>{@link RestResponseHeader#asIntegerHeader() asIntegerHeader()} <jk>returns</jk> {@link BasicStringHeader}</c>
616 *       <li class='jm'><c>{@link RestResponseHeader#asLongHeader() asLongHeader()} <jk>returns</jk> {@link BasicLongHeader}</c>
617 *       <li class='jm'><c>{@link RestResponseHeader#asDateHeader() asDateHeader()} <jk>returns</jk> {@link BasicDateHeader}</c>
618 *       <li class='jm'><c>{@link RestResponseHeader#asCsvArrayHeader() asCsvArrayHeader()} <jk>returns</jk> {@link BasicCsvArrayHeader}</c>
619 *       <li class='jm'><c>{@link RestResponseHeader#asEntityTagArrayHeader() asEntityValidatorArrayHeader()} <jk>returns</jk> {@link BasicEntityTagArrayHeader}</c>
620 *       <li class='jm'><c>{@link RestResponseHeader#asStringRangeArrayHeader() asRangeArrayHeader()} <jk>returns</jk> {@link BasicStringRangeArrayHeader}</c>
621 *       <li class='jm'><c>{@link RestResponseHeader#asUriHeader() asUriHeader()} <jk>returns</jk> {@link BasicUriHeader}</c>
622 *    </ul>
623 * </ul>
624 *
625 * <p>
626 * The {@link RestResponseHeader#schema(HttpPartSchema)} method allows you to perform parsing of OpenAPI formats for
627 * header parts.
628 *
629 * <h5 class='figure'>Example:</h5>
630 * <p class='bcode w800'>
631 *    <jc>// Parse the header "Foo: bar|baz".</jc>
632 *    List&lt;String&gt; <jv>fooHeader</jv> = <jv>client</jv>
633 *       .get(<jsf>URI</jsf>)
634 *       .complete()
635 *       .getHeader(<js>"Foo"</js>).schema(<jsf>T_ARRAY_PIPES</jsf>).as(List.<jk>class</jk>, String.<jk>class</jk>);
636 * </p>
637 *
638 * <p>
639 * Assertion methods are also provided for fluent-style calls:
640 *
641 * <ul class='javatree'>
642 *    <li class='jc'>{@link RestResponseHeader}
643 *    <ul>
644 *       <li class='jm'><c>{@link RestResponseHeader#assertString() assertString()} <jk>returns</jk> {@link FluentStringAssertion}</c>
645 *       <li class='jm'><c>{@link RestResponseHeader#assertInteger() assertInteger()} <jk>returns</jk> {@link FluentIntegerAssertion}</c>
646 *       <li class='jm'><c>{@link RestResponseHeader#assertLong() assertLong()} <jk>returns</jk> {@link FluentLongAssertion}</c>
647 *       <li class='jm'><c>{@link RestResponseHeader#assertDate() assertDate()} <jk>returns</jk> {@link FluentDateAssertion}</c>
648 *    </ul>
649 * </ul>
650 *
651 * <p>
652 * Note how in the following example, the fluent assertion returns control to the {@link RestResponse} object after
653 * the assertion has been completed:
654 *
655 * <h5 class='figure'>Example:</h5>
656 * <p class='bcode w800'>
657 *    <jc>// Assert the response content type is any sort of JSON.</jc>
658 *    String <jv>body</jv> = <jv>client</jv>.get(<jsf>URI</jsf>)
659 *       .run()
660 *       .getHeader(<js>"Content-Type"</js>).assertString().matchesSimple(<js>"application/json*"</js>)
661 *       .getBody().asString();
662 * </p>
663 *
664 *
665 * <h4 class='topic'>Response Body</h4>
666 *
667 * <p class='w900'>
668 * The response body is accessed through the following method:
669 *
670 * <ul class='javatree'>
671 *    <li class='jc'>{@link RestResponse}
672 *    <ul>
673 *       <li class='jm'><c>{@link RestResponse#getBody() getBody()} <jk>returns</jk> {@link RestResponseBody}</c>
674 *    </ul>
675 * </ul>
676 *
677 * <p class='w900'>
678 * The {@link RestResponseBody} class extends from the HttpClient {@link HttpEntity} class and provides several convenience
679 * methods:
680 *
681 * <ul class='javatree'>
682 *    <li class='jc'>{@link RestResponseBody}
683 *    <ul>
684 *       <li class='jm'><c>{@link RestResponseBody#asInputStream() asInputStream()} <jk>returns</jk> InputStream</c>
685 *       <li class='jm'><c>{@link RestResponseBody#asReader() asReader()} <jk>returns</jk> Reader</c>
686 *       <li class='jm'><c>{@link RestResponseBody#asReader(Charset) asReader(Charset)} <jk>returns</jk> Reader</c>
687 *       <li class='jm'><c>{@link RestResponseBody#pipeTo(OutputStream) pipeTo(OutputStream)} <jk>returns</jk> {@link RestResponse}</c>
688 *       <li class='jm'><c>{@link RestResponseBody#pipeTo(Writer) pipeTo(Writer)} <jk>returns</jk> {@link RestResponse}</c>
689 *       <li class='jm'><c>{@link RestResponseBody#as(Type,Type...) as(Type,Type...)} <jk>returns</jk> T</c>
690 *       <li class='jm'><c>{@link RestResponseBody#as(Class) as(Class&lt;T&gt;)} <jk>returns</jk> T</c>
691 *       <li class='jm'><c>{@link RestResponseBody#asFuture(Class) asFuture(Class&lt;T&gt;)} <jk>returns</jk> Future&lt;T&gt;</c>
692 *       <li class='jm'><c>{@link RestResponseBody#asFuture(Type,Type...) asFuture(Type,Type...)} <jk>returns</jk> Future&lt;T&gt;</c>
693 *       <li class='jm'><c>{@link RestResponseBody#asString() asString()} <jk>returns</jk> String</c>
694 *       <li class='jm'><c>{@link RestResponseBody#asStringFuture() asStringFuture()} <jk>returns</jk> Future&lt;String&gt;</c>
695 *       <li class='jm'><c>{@link RestResponseBody#asAbbreviatedString(int) asAbbreviatedString(int)} <jk>returns</jk> String</c>
696 *       <li class='jm'><c>{@link RestResponseBody#asPojoRest(Class) asPojoRest(Class&lt;?&gt;)} <jk>returns</jk> {@link PojoRest}</c>
697 *       <li class='jm'><c>{@link RestResponseBody#asPojoRest() asPojoRest()} <jk>returns</jk> {@link PojoRest}</c>
698 *       <li class='jm'><c>{@link RestResponseBody#asMatcher(Pattern) asMatcher(Pattern)} <jk>returns</jk> {@link Matcher}</c>
699 *       <li class='jm'><c>{@link RestResponseBody#asMatcher(String) asMatcher(String)} <jk>returns</jk> {@link Matcher}</c>
700 *    </ul>
701 * </ul>
702 *
703 * <br>
704 *
705 * <h5 class='figure'>Examples:</h5>
706 * <p class='bcode w800'>
707 *    <jc>// Parse into a linked-list of strings.</jc>
708 *    List&lt;String&gt; <jv>l1</jv> = <jv>client</jv>
709 *       .get(<jsf>URI</jsf>)
710 *       .run()
711 *       .getBody().as(LinkedList.<jk>class</jk>, String.<jk>class</jk>);
712 *
713 *    <jc>// Parse into a linked-list of beans.</jc>
714 *    List&lt;MyBean&gt; <jv>l2</jv> = <jv>client</jv>
715 *       .get(<jsf>URI</jsf>)
716 *       .run()
717 *       .getBody().as(LinkedList.<jk>class</jk>, MyBean.<jk>class</jk>);
718 *
719 *    <jc>// Parse into a linked-list of linked-lists of strings.</jc>
720 *    List&lt;List&lt;String&gt;&gt; <jv>l3</jv> = <jv>client</jv>
721 *       .get(<jsf>URI</jsf>)
722 *       .run()
723 *       .getBody().as(LinkedList.<jk>class</jk>, LinkedList.<jk>class</jk>, String.<jk>class</jk>);
724 *
725 *    <jc>// Parse into a map of string keys/values.</jc>
726 *    Map&lt;String,String&gt; <jv>m1</jv> = <jv>client</jv>
727 *       .get(<jsf>URI</jsf>)
728 *       .run()
729 *       .getBody().as(TreeMap.<jk>class</jk>, String.<jk>class</jk>, String.<jk>class</jk>);
730 *
731 *    <jc>// Parse into a map containing string keys and values of lists containing beans.</jc>
732 *    Map&lt;String,List&lt;MyBean&gt;&gt; <jv>m2<jv> = <jv>client</jv>
733 *       .get(<jsf>URI</jsf>)
734 *       .run()
735 *       .getBody().as(TreeMap.<jk>class</jk>, String.<jk>class</jk>, List.<jk>class</jk>, MyBean.<jk>class</jk>);
736 * </p>
737 *
738 * <p class='w900'>
739 * The response body can only be consumed once unless it has been cached into memory.  In many cases, the body is
740 * automatically cached when using the assertions methods or methods such as {@link RestResponseBody#asString()}.
741 * However, methods that involve reading directly from the input stream cannot be called twice.
742 * In these cases, the {@link RestResponse#cacheBody()} and {@link RestResponseBody#cache()} methods are provided
743 * to cache the response body in memory so that you can perform several operations against it.
744 *
745 * <p class='bcode w800'>
746 *    <jc>// Cache the response body so we can access it twice.</jc>
747 *    InputStream <jv>inputStream</jv> = <jv>client</jv>
748 *       .get(<jsf>URI</jsf>)
749 *       .run()
750 *       .cacheBody()
751 *       .getBody().pipeTo(<jv>someOtherStream</jv>)
752 *       .getBody().asInputStream();
753 * </p>
754 *
755 * <p>
756 * Assertion methods are also provided for fluent-style calls:
757 *
758 * <ul class='javatree'>
759 *    <li class='jc'>{@link RestResponseBody}
760 *    <ul>
761 *       <li class='jm'><c>{@link RestResponseBody#assertString() assertString()} <jk>returns</jk> {@link FluentStringAssertion}</c>
762 *       <li class='jm'><c>{@link RestResponseBody#assertObject(Class) assertObject(Class&lt;?&gt;)} <jk>returns</jk> {@link FluentObjectAssertion}</c>
763 *       <li class='jm'><c>{@link RestResponseBody#assertBytes() assertBytes()} <jk>returns</jk> {@link FluentByteArrayAssertion}</c>
764 *    </ul>
765 * </ul>
766 *
767 * <br>
768 *
769 * <h5 class='figure'>Example:</h5>
770 * <p class='bcode w800'>
771 *    <jc>// Assert that the body contains the string "Success".</jc>
772 *    String <jv>body</jv> = <jv>client</jv>
773 *       .get(<jsf>URI</jsf>)
774 *       .run()
775 *       .getBody().assertString().contains(<js>"Success"</js>)
776 *       .getBody().asString();
777 * </p>
778 *
779 * <p>
780 * Object assertions allow you to parse the response body into a POJO and then perform various tests on that resulting
781 * POJO.
782 *
783 * <h5 class='figure'>Example:</h5>
784 * <p class='bcode w800'>
785 *    <jc>// Parse bean into POJO and then validate that it was parsed correctly.</jc>
786 *    MyBean <jv>bean</jv> = <jv>client</jv>.get(<jsf>URI</jsf>)
787 *       .run()
788 *       .getBody().assertObject(MyBean.<jk>class</jk>).json().is(<js>"{foo:'bar'}"</js>)
789 *       .getBody().as(MyBean.<jk>class</jk>);
790 * </p>
791 *
792 *
793 * <h4 class='topic'>Custom Call Handlers</h4>
794 *
795 * <p class='w900'>
796 * The {@link RestCallHandler} interface provides the ability to provide custom handling of requests.
797 *
798 * <ul class='javatree'>
799 *    <li class='jc'>{@link RestClientBuilder}
800 *    <ul>
801 *       <li class='jm'>{@link RestClientBuilder#callHandler(Class) callHandler(Class&lt;? extends RestCallHandler&gt;)}
802 *       <li class='jm'>{@link RestClientBuilder#callHandler(RestCallHandler) callHandler(RestCallHandler)}
803 *    </ul>
804 *    <li class='jic'>{@link RestCallHandler}
805 *    <ul>
806 *       <li class='jm'><c>{@link RestCallHandler#run(HttpHost,HttpRequest,HttpContext) run(HttpHost,HttpRequest,HttpContext)} <jk>returns</jk> HttpResponse</c>
807 *    </ul>
808 * </ul>
809 *
810 * <p class='w900'>
811 * Note that there are other ways of accomplishing this such as extending the {@link RestClient} class and overriding
812 * the {@link #run(HttpHost,HttpRequest,HttpContext)} method
813 * or by defining your own {@link HttpRequestExecutor}.  Using this interface is often simpler though.
814 *
815 *
816 * <h4 class='topic'>Interceptors</h4>
817 *
818 * <p class='w900'>
819 * The {@link RestCallInterceptor} API provides a quick way of intercepting and manipulating requests and responses beyond
820 * the existing {@link HttpRequestInterceptor} and {@link HttpResponseInterceptor} APIs.
821 *
822 * <ul class='javatree'>
823 *    <li class='jc'>{@link RestClientBuilder}
824 *    <ul>
825 *       <li class='jm'>{@link RestClientBuilder#interceptors(Object...) interceptors(Object...)}
826 *    </ul>
827 *    <li class='jc'>{@link RestRequest}
828 *    <ul>
829 *       <li class='jm'>{@link RestRequest#interceptors(RestCallInterceptor...) interceptors(RestCallInterceptor...)}
830 *    </ul>
831 *    <li class='jic'>{@link RestCallInterceptor}
832 *    <ul>
833 *       <li class='jm'>{@link RestCallInterceptor#onInit(RestRequest) onInit(RestRequest)}
834 *       <li class='jm'>{@link RestCallInterceptor#onConnect(RestRequest,RestResponse) onConnect(RestRequest,RestResponse)}
835 *       <li class='jm'>{@link RestCallInterceptor#onClose(RestRequest,RestResponse) onClose(RestRequest,RestResponse)}
836 *    </ul>
837 * </ul>
838 *
839 *
840 * <h4 class='topic'>Logging / Debugging</h4>
841 *
842 * <p class='w900'>
843 * The following methods provide logging of requests and responses:
844 *
845 * <ul class='javatree'>
846 *    <li class='jc'>{@link RestClientBuilder}
847 *    <ul>
848 *       <li class='jm'>{@link RestClientBuilder#logger(Logger) logger(Logger)}
849 *       <li class='jm'>{@link RestClientBuilder#logToConsole() logToConsole()}
850 *       <li class='jm'>{@link RestClientBuilder#logRequests(DetailLevel,Level,BiPredicate) logRequests(DetailLevel,Level,BiPredicate)}
851 *    </ul>
852 * </ul>
853 *
854 * <p>
855 * The following example shows the results of logging all requests that end with <c>/bean</c>.
856 *
857 * <h5 class='figure'>Examples:</h5>
858 * <p class='bcode w800'>
859 *    MyBean <jv>bean</jv> = RestClient
860 *       .<jsm>create</jsm>()
861 *       .simpleJson()
862 *       .logRequests(DetailLevel.<jsf>FULL</jsf>, Level.<jsf>SEVERE</jsf>, (<jv>req</jv>,<jv>res</jv>)-&gt;<jv>req</jv>.getUri().endsWith(<js>"/bean"</js>))
863 *       .logToConsole()
864 *       .build()
865 *       .post(<js>"http://localhost/bean"</js>, <jv>anotherBean</jv>)
866 *       .run()
867 *       .getBody().as(MyBean.<jk>class</jk>);
868 * </p>
869 *
870 * <p>
871 * This produces the following console output:
872 *
873 * <p class='bcode w800 console'>
874 *    === HTTP Call (outgoing) ======================================================
875 *    === REQUEST ===
876 *    POST http://localhost/bean
877 *    ---request headers---
878 *       Accept: application/json+simple
879 *    ---request entity---
880 *    Content-Type: application/json+simple
881 *    ---request content---
882 *    {f:1}
883 *    === RESPONSE ===
884 *    HTTP/1.1 200
885 *    ---response headers---
886 *       Content-Type: application/json
887 *    ---response content---
888 *    {f:1}
889 *    === END =======================================================================",
890 * </p>
891 *
892 *
893 * <p class='notes w900'>
894 * 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
895 * a performance penalty.
896 *
897 * <p class='w900'>
898 * Additionally, the following method is also provided for enabling debug mode:
899 *
900 * <ul class='javatree'>
901 *    <li class='jc'>{@link RestClientBuilder}
902 *    <ul>
903 *       <li class='jm'>{@link RestClientBuilder#debug() debug()}
904 *    </ul>
905 * </ul>
906 *
907 * <p class='w900'>
908 * Enabling debug mode has the following effects:
909 * <ul>
910 *    <li>{@link Context#CONTEXT_debug} is enabled.
911 *    <li>{@link #RESTCLIENT_leakDetection} is enabled.
912 *    <li>{@link RestClientBuilder#logToConsole()} is called.
913 * </ul>
914 *
915 *
916 * <h4 class='topic'>REST Proxies</h4>
917 *
918 * <p class='w900'>
919 * One of the more powerful features of the REST client class is the ability to produce Java interface proxies against
920 * arbitrary remote REST resources.
921 *
922 * <h5 class='figure'>Example:</h5>
923 * <p class='bcode w800'>
924 *    <jc>// Define a Remote proxy for interacting with a REST interface.</jc>
925 *    <ja>@Remote</ja>(path=<js>"/petstore"</js>)
926 *    <jk>public interface</jk> PetStore {
927 *
928 *       <ja>@RemoteMethod</ja>(httpMethod=<jsf>POST</jsf>, path=<js>"/pets"</js>)
929 *       Pet addPet(
930 *          <ja>@Body</ja> CreatePet <jv>pet</jv>,
931 *          <ja>@Header</ja>(<js>"E-Tag"</js>) UUID <jv>etag</jv>,
932 *          <ja>@Query</ja>(<js>"debug"</js>) <jk>boolean</jk> <jv>debug</jv>
933 *       );
934 *    }
935 *
936 *    <jc>// Use a RestClient with default Simple JSON support.</jc>
937 *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().simpleJson().build())
938 *
939 *    PetStore <jv>store</jv> = <jv>client</jv>.getRemote(PetStore.<jk>class</jk>, <js>"http://localhost:10000"</js>);
940 *    CreatePet <jv>createPet</jv> = <jk>new</jk> CreatePet(<js>"Fluffy"</js>, 9.99);
941 *    Pet <jv>pet</jv> = <jv>store</jv>.addPet(<jv>createPet</jv>, UUID.<jsm>randomUUID</jsm>(), <jk>true</jk>);
942 * </p>
943 *
944 * <p class='w900'>
945 * The methods to retrieve remote interfaces are:
946 *
947 * <ul class='javatree'>
948 *    <li class='jc'>{@link RestClient}
949 *    <ul>
950 *       <li class='jm'><c>{@link RestClient#getRemote(Class) getRemote(Class&lt;T&gt;)} <jk>returns</jk> T</c>
951 *       <li class='jm'><c>{@link RestClient#getRemote(Class,Object) getRemote(Class&lt;T&gt;,Object)} <jk>returns</jk> T</c>
952 *       <li class='jm'><c>{@link RestClient#getRemote(Class,Object,Serializer,Parser) getRemote(Class&lt;T&gt;,Object,Serializer,Parser)} <jk>returns</jk> T</c>
953 *       <li class='jm'><c>{@link RestClient#getRrpcInterface(Class) getRrpcInterface(Class&lt;T&gt;)} <jk>returns</jk> T</c>
954 *       <li class='jm'><c>{@link RestClient#getRrpcInterface(Class,Object) getRrpcInterface(Class&lt;T&gt;,Object)} <jk>returns</jk> T</c>
955 *       <li class='jm'><c>{@link RestClient#getRrpcInterface(Class,Object,Serializer,Parser) getRrpcInterface(Class&lt;T&gt;,Object,Serializer,Parser)} <jk>returns</jk> T</c>
956 *    </ul>
957 * </ul>
958 *
959 * <p class='w900'>
960 * Two basic types of remote interfaces are provided:
961 *
962 * <ul class='spaced-list'>
963 *    <li>{@link Remote @Remote}-annotated interfaces.  These can be defined against arbitrary external REST resources.
964 *    <li>RPC-over-REST interfaces.  These are Java interfaces that allow you to make method calls on server-side POJOs.
965 * </ul>
966 *
967 * <p class='w900'>
968 * Refer to the following documentation on both flavors:
969 *
970 * <ul class='doctree'>
971 *    <li class='link'>{@doc RestcProxies}
972 *    <li class='link'>{@doc RestRpc}
973 * </ul>
974 *
975 * <br>
976 * <hr class='w900'>
977 * <h4 class='topic'>Customizing Apache HttpClient</h4>
978 *
979 * <p class='w900'>
980 * Several methods are provided for customizing the underlying HTTP client and client builder classes:
981 * <ul class='javatree'>
982 *    <li class='jc'>{@link RestClientBuilder}
983 *    <ul>
984 *       <li class='jm'>{@link RestClientBuilder#httpClientBuilder(HttpClientBuilder) httpClientBuilder(HttpClientBuilder)} - Set the client builder yourself.
985 *       <li class='jm'>{@link RestClientBuilder#createHttpClientBuilder() createHttpClientBuilder()} - Override to create the client builder.
986 *       <li class='jm'>{@link RestClientBuilder#createHttpClient() createHttpClient()} - Override to create the client.
987 *       <li class='jm'>{@link RestClientBuilder#createConnectionManager() createConnectionManager()} - Override to create the connection management.
988 *    </ul>
989 * </ul>
990 *
991 * <p class='w900'>
992 * Additionally, all methods on the <c>HttpClientBuilder</c> class have been extended with fluent setters.
993 *
994 * <h5 class='figure'>Example:</h5>
995 * <p class='bcode w800'>
996 *    <jc>// Create a client with customized HttpClient settings.</jc>
997 *    MyBean <jv>bean</jv> = RestClient
998 *       .<jsm>create</jsm>()
999 *       .disableRedirectHandling()
1000 *       .connectionManager(<jv>myConnectionManager</jv>)
1001 *       .addInterceptorFirst(<jv>myHttpRequestInterceptor</jv>)
1002 *       .build();
1003 * </p>
1004 *
1005 * <p>
1006 * Refer to the {@link HttpClientBuilder HTTP Client Builder API} for more information.
1007 *
1008 *
1009 * <h4 class='topic'>Extending RestClient</h4>
1010 *
1011 * <p class='w900'>
1012 * The <c>RestClient</c> API has been designed to allow for the ability to be easily extended.
1013 * The following example that overrides the primary run method shows how this can be done.
1014 *
1015 * <h5 class='figure'>Example:</h5>
1016 * <p class='bcode w800'>
1017 *    <jk>public class</jk> MyRestClient <jk>extends</jk> RestClient {
1018 *
1019 *       <jc>// Must provide this constructor!</jc>
1020 *       <jk>public</jk> MyRestClient(PropertyStore <jv>ps</jv>) {
1021 *          <jk>super</jk>(<jv>ps</jv>);
1022 *       }
1023 *
1024 *       <ja>@Override</ja>
1025 *       <jk>public</jk> HttpResponse run(HttpHost <jv>target</jv>, HttpRequest <jv>request</jv>, HttpContext <jv>context</jv>) <jk>throws</jk> IOException {
1026 *          <jc>// Perform special handling of requests.</jc>
1027 *       }
1028 *    }
1029 *
1030 *    <jc>// Instantiate your client.</jc>
1031 *    MyRestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().json().build(MyRestClient.<jk>class</jk>);
1032 * </p>
1033 *
1034 * <p class='w900'>
1035 * The {@link RestRequest} and {@link RestResponse} objects can also be extended and integrated by overriding the
1036 * {@link RestClient#createRequest(URI, String, boolean)} and {@link RestClient#createResponse(RestRequest, HttpResponse, Parser)} methods.
1037 *
1038 *
1039 * <ul class='seealso'>
1040 *    <li class='link'>{@doc juneau-rest-client}
1041 * </ul>
1042 */
1043@ConfigurableContext(nocache=true)
1044public class RestClient extends BeanContext implements HttpClient, Closeable, RestCallHandler, RestCallInterceptor {
1045
1046   //-------------------------------------------------------------------------------------------------------------------
1047   // Configurable properties
1048   //-------------------------------------------------------------------------------------------------------------------
1049
1050   private static final String PREFIX = "RestClient.";
1051
1052   /**
1053    * Configuration property:  REST call handler.
1054    *
1055    * <h5 class='section'>Property:</h5>
1056    * <ul class='spaced-list'>
1057    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.client2.RestClient#RESTCLIENT_callHandler RESTCLIENT_callHandler}
1058    *    <li><b>Name:</b>  <js>"RestClient.callHandler.o"</js>
1059    *    <li><b>Data type:</b>
1060    *       <ul>
1061    *          <li><c>Class&lt;? <jk>extends</jk> {@link org.apache.juneau.rest.client2.RestCallHandler}&gt;</c>
1062    *          <li>{@link org.apache.juneau.rest.client2.RestCallHandler}
1063    *       </ul>
1064    *    <li><b>Default:</b>  <c><jk>null</jk></c>
1065    *    <li><b>Methods:</b>
1066    *       <ul>
1067    *          <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#callHandler(Class)}
1068    *          <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#callHandler(RestCallHandler)}
1069    *       </ul>
1070    * </ul>
1071    *
1072    * <h5 class='section'>Description:</h5>
1073    *
1074    * <p>
1075    * Allows you to provide a custom handler for making HTTP calls.
1076    *
1077    * <h5 class='section'>Example:</h5>
1078    * <p class='bcode w800'>
1079    *    <jc>// Create a client that handles processing of requests using a custom handler.</jc>
1080    *    RestClient <jv>client</jv> = RestClient
1081    *       .<jsm>create</jsm>()
1082    *       .callHandler(
1083    *          <jk>new</jk> RestCallHandler() {
1084    *             <ja>@Override</ja>
1085    *             <jk>public</jk> HttpResponse run(HttpHost <jv>target</jv>, HttpRequest <jv>request</jv>, HttpContext <jv>context</jv>) <jk>throws</jk> IOException {
1086    *                <jc>// Custom handle requests.</jc>
1087    *             }
1088    *          }
1089    *       )
1090    *       .build();
1091    * </p>
1092    */
1093   public static final String RESTCLIENT_callHandler = PREFIX + "callHandler.o";
1094
1095   /**
1096    * Configuration property:  Console print stream.
1097    *
1098    * <h5 class='section'>Property:</h5>
1099    * <ul class='spaced-list'>
1100    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.client2.RestClient#RESTCLIENT_console RESTCLIENT_console}
1101    *    <li><b>Name:</b>  <js>"RestClient.console.o"</js>
1102    *    <li><b>System property:</b>  <c>RestClient.console</c>
1103    *    <li><b>Data type:</b>
1104    *    <ul>
1105    *       <li><b>Data type:</b>  <c>Class&lt;? <jk>extends</jk> {@link java.io.PrintStream}&gt; | {@link java.io.PrintStream}</c>
1106    *    </ul>
1107    *    <li><b>Default:</b>  <c>System.<jsf>out</jsf></c>
1108    *    <li><b>Methods:</b>
1109    *       <ul>
1110    *          <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#console(PrintStream)}
1111    *          <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#console(Class)}
1112    *       </ul>
1113    * </ul>
1114    *
1115    * <h5 class='section'>Description:</h5>
1116    * <p>
1117    * Allows you to redirect the console output to a different print stream.
1118    */
1119   public static final String RESTCLIENT_console = PREFIX + "console.o";
1120
1121   /**
1122    * Configuration property:  Error codes predicate.
1123    *
1124    * <h5 class='section'>Property:</h5>
1125    * <ul class='spaced-list'>
1126    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.client2.RestClient#RESTCLIENT_errorCodes RESTCLIENT_errorCodes}
1127    *    <li><b>Name:</b>  <js>"RestClient.errorCodes.o"</js>
1128    *    <li><b>Data type:</b>  {@link java.util.function.Predicate}&lt;{@link java.lang.Integer}&gt;
1129    *    <li><b>Default:</b>  <code>x -&gt; x&gt;=400</code>
1130    *    <li><b>Methods:</b>
1131    *       <ul>
1132    *          <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#errorCodes(Predicate)}
1133    *          <li class='jm'>{@link org.apache.juneau.rest.client2.RestRequest#errorCodes(Predicate)}
1134    *       </ul>
1135    * </ul>
1136    *
1137    * <h5 class='section'>Description:</h5>
1138    *
1139    * <p>
1140    * Defines a predicate to test for error codes.
1141    *
1142    * <h5 class='section'>Example:</h5>
1143    * <p class='bcode w800'>
1144    *    <jc>// Create a client that considers any 300+ responses to be errors.</jc>
1145    *    RestClient <jv>client</jv> = RestClient
1146    *       .<jsm>create</jsm>()
1147    *       .errorCodes(<jv>x</jv> -&gt; <jv>x</jv> &gt;= 300)
1148    *       .build();
1149    * </p>
1150    */
1151   public static final String RESTCLIENT_errorCodes = PREFIX + "errorCodes.o";
1152
1153   /**
1154    * Configuration property:  Executor service.
1155    *
1156    * <h5 class='section'>Property:</h5>
1157    * <ul class='spaced-list'>
1158    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.client2.RestClient#RESTCLIENT_executorService RESTCLIENT_executorService}
1159    *    <li><b>Name:</b>  <js>"RestClient.executorService.o"</js>
1160    *    <li><b>Data type:</b>
1161    *       <ul>
1162    *          <li><c>Class&lt;? <jk>extends</jk> {@link java.util.concurrent.ExecutorService}&gt;</c>
1163    *          <li>{@link java.util.concurrent.ExecutorService}
1164    *       </ul>
1165    *    <li><b>Default:</b>  <jk>null</jk>.
1166    *    <li><b>Methods:</b>
1167    *       <ul>
1168    *          <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#executorService(ExecutorService, boolean)}
1169    *       </ul>
1170    * </ul>
1171    *
1172    * <h5 class='section'>Description:</h5>
1173    * <p>
1174    * Defines the executor service to use when calling future methods on the {@link RestRequest} class.
1175    *
1176    * <p>
1177    * This executor service is used to create {@link Future} objects on the following methods:
1178    * <ul>
1179    *    <li class='jm'>{@link RestRequest#runFuture()}
1180    *    <li class='jm'>{@link RestRequest#completeFuture()}
1181    *    <li class='jm'>{@link RestResponseBody#asFuture(Class)} (and similar methods)
1182    * </ul>
1183    *
1184    * <p>
1185    * The default executor service is a single-threaded {@link ThreadPoolExecutor} with a 30 second timeout
1186    * and a queue size of 10.
1187    *
1188    * <h5 class='section'>Example:</h5>
1189    * <p class='bcode w800'>
1190    *    <jc>// Create a client with a customized executor service.</jc>
1191    *    RestClient <jv>client</jv> = RestClient
1192    *       .<jsm>create</jsm>()
1193    *       .executorService(<jk>new</jk> ThreadPoolExecutor(1, 1, 30, TimeUnit.<jsf>SECONDS</jsf>, <jk>new</jk> ArrayBlockingQueue&lt;Runnable&gt;(10)), <jk>true</jk>)
1194    *       .build();
1195    *
1196    *    <jc>// Use it to asynchronously run a request.</jc>
1197    *    Future&lt;RestResponse&gt; <jv>responseFuture</jv> = <jv>client</jv>.get(<jsf>URI</jsf>).runFuture();
1198    *
1199    *    <jc>// Do some other stuff.</jc>
1200    *
1201    *    <jc>// Now read the response.</jc>
1202    *    String <jv>body</jv> = <jv>responseFuture</jv>.get().getBody().asString();
1203    *
1204    *    <jc>// Use it to asynchronously retrieve a response.</jc>
1205    *    Future&lt;MyBean&gt; <jv>myBeanFuture</jv> = <jv>client</jv>
1206    *       .get(<jsf>URI</jsf>)
1207    *       .run()
1208    *       .getBody().asFuture(MyBean.<jk>class</jk>);
1209    *
1210    *    <jc>// Do some other stuff.</jc>
1211    *
1212    *    <jc>// Now read the response.</jc>
1213    *    MyBean <jv>bean</jv> = <jv>myBeanFuture</jv>.get();
1214    * </p>
1215    */
1216   public static final String RESTCLIENT_executorService = PREFIX + "executorService.o";
1217
1218   /**
1219    * Configuration property:  Shut down executor service on close.
1220    *
1221    * <h5 class='section'>Property:</h5>
1222    * <ul class='spaced-list'>
1223    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.client2.RestClient#RESTCLIENT_executorServiceShutdownOnClose RESTCLIENT_executorServiceShutdownOnClose}
1224    *    <li><b>Name:</b>  <js>"RestClient.executorServiceShutdownOnClose.b"</js>
1225    *    <li><b>Data type:</b>  <jk>boolean</jk>
1226    *    <li><b>System property:</b>  <c>RestClient.executorServiceShutdownOnClose</c>
1227    *    <li><b>Environment variable:</b>  <c>RESTCLIENT_EXECUTORSERVICESHUTDOWNONCLOSE</c>
1228    *    <li><b>Default:</b>  <jk>false</jk>
1229    *    <li><b>Methods:</b>
1230    *       <ul>
1231    *          <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#executorService(ExecutorService, boolean)}
1232    *       </ul>
1233    * </ul>
1234    *
1235    * <h5 class='section'>Description:</h5>
1236    * <p>
1237    * Call {@link ExecutorService#shutdown()} when {@link RestClient#close()} is called.
1238    */
1239   public static final String RESTCLIENT_executorServiceShutdownOnClose = PREFIX + "executorServiceShutdownOnClose.b";
1240
1241   /**
1242    * Configuration property:  Request form-data parameters.
1243    *
1244    * <h5 class='section'>Property:</h5>
1245    * <ul class='spaced-list'>
1246    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.client2.RestClient#RESTCLIENT_formData RESTCLIENT_formData}
1247    *    <li><b>Name:</b>  <js>"RestClient.formData.lo"</js>
1248    *    <li><b>Data type:</b>  <c>List&lt;{@link org.apache.http.NameValuePair}&gt;</c>
1249    *    <li><b>Default:</b>  empty map
1250    *    <li><b>Methods:</b>
1251    *       <ul>
1252    *          <li class='jc'>{@link org.apache.juneau.rest.client2.RestClientBuilder}
1253    *          <ul>
1254    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#formData(String,Object) formData(String,Object)}
1255    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#formData(String,Object,HttpPartSchema,HttpPartSerializer) formData(String,Object,HttpPartSerializer,HttpPartSchema)}
1256    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#formDatas(Object...) formDatas(Object...)}
1257    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#formDataPairs(Object...) formDataPairs(Map<String, Object>)}
1258    *          </ul>
1259    *          <li class='jc'>{@link org.apache.juneau.rest.client2.RestRequest}
1260    *          <ul>
1261    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestRequest#formData(String,Object) formData(String,Object)}
1262    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestRequest#formData(AddFlag,String,Object) formData(EnumSet&lt;AddFlag&gt;,String,Object)}
1263    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestRequest#formDatas(Object...) formDatas(Object...)}
1264    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestRequest#formDatas(AddFlag,Object...) formDatas(EnumSet&lt;AddFlag&gt;Object...)}
1265    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestRequest#formDataPairs(Object...) formDataPairs(Object...)}
1266    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestRequest#formDataCustom(Object) formDataCustom(Object)}
1267    *          </ul>
1268    *       </ul>
1269    * </ul>
1270    *
1271    * <h5 class='section'>Description:</h5>
1272    * <p>
1273    * Query parameters to add to every request.
1274    */
1275   public static final String RESTCLIENT_formData = PREFIX + "formData.lo";
1276
1277   /**
1278    * Configuration property:  Request headers.
1279    *
1280    * <h5 class='section'>Property:</h5>
1281    * <ul class='spaced-list'>
1282    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.client2.RestClient#RESTCLIENT_headers RESTCLIENT_headers}
1283    *    <li><b>Name:</b>  <js>"RestClient.headers.lo"</js>
1284    *    <li><b>Data type:</b>  <c>List&lt;{@link org.apache.http.Header} | {@link org.apache.http.NameValuePair}&gt;</c>
1285    *    <li><b>Default:</b>  empty map
1286    *    <li><b>Methods:</b>
1287    *       <ul>
1288    *          <li class='jc'>{@link org.apache.juneau.rest.client2.RestClientBuilder}
1289    *          <ul>
1290    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#header(String,Object) header(String,Object)}
1291    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#header(String,Object,HttpPartSchema,HttpPartSerializer) header(String,Object,HttpPartSerializer,HttpPartSchema)}
1292    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#header(Header) header(Header)}
1293    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#headers(Object...) headers(Object...)}
1294    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#headerPairs(Object...) headerPairs(Object...)}
1295    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#accept(Object) accept(Object)}
1296    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#acceptCharset(Object) acceptCharset(Object)}
1297    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#acceptEncoding(Object) acceptEncoding(Object)}
1298    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#acceptLanguage(Object) acceptLanguage(Object)}
1299    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#authorization(Object) authorization(Object)}
1300    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#cacheControl(Object) cacheControl(Object)}
1301    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#clientVersion(Object) clientVersion(Object)}
1302    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#connection(Object) connection(Object)}
1303    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#contentLength(Object) contentLength(Object)}
1304    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#contentType(Object) contentType(Object)}
1305    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#date(Object) date(Object)}
1306    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#expect(Object) expect(Object)}
1307    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#forwarded(Object) forwarded(Object)}
1308    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#from(Object) from(Object)}
1309    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#host(Object) host(Object)}
1310    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#ifMatch(Object) ifMatch(Object)}
1311    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#ifModifiedSince(Object) ifModifiedSince(Object)}
1312    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#ifNoneMatch(Object) ifNoneMatch(Object)}
1313    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#ifRange(Object) ifRange(Object)}
1314    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#ifUnmodifiedSince(Object) ifUnmodifiedSince(Object)}
1315    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#maxForwards(Object) maxForwards(Object)}
1316    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#origin(Object) origin(Object)}
1317    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#pragma(Object) pragma(Object)}
1318    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#proxyAuthorization(Object) proxyAuthorization(Object)}
1319    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#range(Object) proxyAuthorization(Object)}
1320    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#referer(Object) referer(Object)}
1321    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#te(Object) te(Object)}
1322    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#userAgent(Object) userAgent(Object)}
1323    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#upgrade(Object) upgrade(Object)}
1324    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#via(Object) via(Object)}
1325    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#warning(Object) warning(Object)}
1326    *          </ul>
1327    *          <li class='jc'>{@link org.apache.juneau.rest.client2.RestRequest}
1328    *          <ul>
1329    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestRequest#header(String,Object) header(String,Object)}
1330    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestRequest#header(AddFlag,String,Object) header(EnumSet&gt;AddFlag&gt;,String,Object)}
1331    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestRequest#header(Header) header(Header)}
1332    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestRequest#headers(Object...) headers(Object...)}
1333    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestRequest#headers(AddFlag,Object...) headers(EnumSet&gt;AddFlag&gt;,Object...)}
1334    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestRequest#headerPairs(Object...) headerPairs(Object...)}
1335    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestRequest#accept(Object) accept(Object)}
1336    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestRequest#acceptCharset(Object) acceptCharset(Object)}
1337    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestRequest#acceptEncoding(Object) acceptEncoding(Object)}
1338    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestRequest#acceptLanguage(Object) acceptLanguage(Object)}
1339    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestRequest#authorization(Object) authorization(Object)}
1340    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestRequest#cacheControl(Object) cacheControl(Object)}
1341    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestRequest#clientVersion(Object) clientVersion(Object)}
1342    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestRequest#connection(Object) connection(Object)}
1343    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestRequest#contentLength(Object) contentLength(Object)}
1344    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestRequest#contentType(Object) contentType(Object)}
1345    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestRequest#date(Object) date(Object)}
1346    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestRequest#expect(Object) expect(Object)}
1347    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestRequest#forwarded(Object) forwarded(Object)}
1348    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestRequest#from(Object) from(Object)}
1349    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestRequest#hostHeader(Object) hostHeader(Object)}
1350    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestRequest#ifMatch(Object) ifMatch(Object)}
1351    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestRequest#ifModifiedSince(Object) ifModifiedSince(Object)}
1352    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestRequest#ifNoneMatch(Object) ifNoneMatch(Object)}
1353    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestRequest#ifRange(Object) ifRange(Object)}
1354    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestRequest#ifUnmodifiedSince(Object) ifUnmodifiedSince(Object)}
1355    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestRequest#maxForwards(Object) maxForwards(Object)}
1356    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestRequest#origin(Object) origin(Object)}
1357    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestRequest#pragma(Object) pragma(Object)}
1358    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestRequest#proxyAuthorization(Object) proxyAuthorization(Object)}
1359    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestRequest#range(Object) proxyAuthorization(Object)}
1360    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestRequest#referer(Object) referer(Object)}
1361    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestRequest#te(Object) te(Object)}
1362    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestRequest#userAgent(Object) userAgent(Object)}
1363    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestRequest#upgrade(Object) upgrade(Object)}
1364    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestRequest#via(Object) via(Object)}
1365    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestRequest#warning(Object) warning(Object)}
1366    *          </ul>
1367    *       </ul>
1368    * </ul>
1369    *
1370    * <h5 class='section'>Description:</h5>
1371    * <p>
1372    * Headers to add to every request.
1373    */
1374   public static final String RESTCLIENT_headers = PREFIX + "headers.lo";
1375
1376   /**
1377    * Configuration property:  Ignore errors.
1378    *
1379    * <h5 class='section'>Property:</h5>
1380    * <ul class='spaced-list'>
1381    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.client2.RestClient#RESTCLIENT_ignoreErrors RESTCLIENT_ignoreErrors}
1382    *    <li><b>Name:</b>  <js>"RestClient.ignoreErrors.b"</js>
1383    *    <li><b>Data type:</b>  <jk>boolean</jk>
1384    *    <li><b>Default:</b>  <jk>false</jk>
1385    *    <li><b>Methods:</b>
1386    *       <ul>
1387    *          <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#ignoreErrors()}
1388    *          <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#ignoreErrors(boolean)}
1389    *          <li class='jm'>{@link org.apache.juneau.rest.client2.RestRequest#ignoreErrors()}
1390    *       </ul>
1391    * </ul>
1392    *
1393    * <h5 class='section'>Description:</h5>
1394    *
1395    * <p>
1396    * When enabled, HTTP error response codes (e.g. <l>&gt;=400</l>) will not cause a {@link RestCallException} to
1397    * be thrown.
1398    * <p>
1399    * Note that this is equivalent to <c>builder.errorCodes(x -&gt; <jk>false</jk>);</c>
1400    *
1401    * <h5 class='section'>Example:</h5>
1402    * <p class='bcode w800'>
1403    *    <jc>// Create a client that doesn't throws a RestCallException when a 500 error occurs.</jc>
1404    *    RestClient
1405    *       .<jsm>create</jsm>()
1406    *       .ignoreErrors()
1407    *       .build()
1408    *       .get(<js>"/error"</js>)  <jc>// Throws a 500 error</jc>
1409    *       .run()
1410    *       .assertStatus().is(500);
1411    * </p>
1412    */
1413   public static final String RESTCLIENT_ignoreErrors = PREFIX + "ignoreErrors.b";
1414
1415   /**
1416    * Configuration property:  Call interceptors.
1417    *
1418    * <h5 class='section'>Property:</h5>
1419    * <ul class='spaced-list'>
1420    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.client2.RestClient#RESTCLIENT_interceptors RESTCLIENT_interceptors}
1421    *    <li><b>Name:</b>  <js>"RestClient.interceptors.lo"</js>
1422    *    <li><b>Data type:</b>  <c>List&lt;Class&lt;{@link org.apache.juneau.rest.client2.RestCallInterceptor}&gt; | {@link org.apache.juneau.rest.client2.RestCallInterceptor}&gt;&gt;</c>
1423    *    <li><b>Default:</b>  empty list.
1424    *    <li><b>Methods:</b>
1425    *       <ul>
1426    *          <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#interceptors(Object...)}
1427    *       </ul>
1428    * </ul>
1429    *
1430    * <h5 class='section'>Description:</h5>
1431    * <p>
1432    * Adds an interceptor that can be called to hook into specified events in the lifecycle of a single request.
1433    *
1434    * <h5 class='section'>Example:</h5>
1435    * <p class='bcode w800'>
1436    *   <jc>// Customized interceptor (note you can also extend from BasicRestCallInterceptor as well.</jc>
1437    *    <jk>public class</jk> MyRestCallInterceptor <jk>implements</jk> RestCallInterceptor {
1438    *
1439    *       <ja>@Override</ja>
1440    *       <jk>public void</jk> onInit(RestRequest <jv>req</jv>) <jk>throws</jk> Exception {
1441    *       <jc>// Intercept immediately after RestRequest object is created and all headers/query/form-data has been
1442    *       // set on the request from the client.</jc>
1443    *    }
1444    *    <ja>@Override</ja>
1445    *    <jk>public void</jk> onConnect(RestRequest <jv>req</jv>, RestResponse <jv>res</jv>) <jk>throws</jk> Exception {
1446    *       <jc>// Intercept immediately after an HTTP response has been received.</jc>
1447    *    }
1448    *
1449    *    <ja>@Override</ja>
1450    *    <jk>public void</jk> onClose(RestRequest <jv>req</jv>, RestResponse <jv>res</jv>) <jk>throws</jk> Exception {
1451    *          <jc>// Intercept when the response body is consumed.</jc>
1452    *       }
1453    *    }
1454    *
1455    *    <jc>// Create a client with a customized interceptor.</jc>
1456    *    RestClient <jv>client</jv> = RestClient
1457    *       .<jsm>create</jsm>()
1458    *       .interceptors(MyRestCallInterceptor.<jk>class</jk>)
1459    *       .build();
1460    * </p>
1461    */
1462   public static final String RESTCLIENT_interceptors = PREFIX + "interceptors.lo";
1463
1464   /**
1465    * Add to the Call interceptors property.
1466    */
1467   public static final String RESTCLIENT_interceptors_add = PREFIX + "interceptors.so/add";
1468
1469   /**
1470    * Configuration property:  Keep HttpClient open.
1471    *
1472    * <h5 class='section'>Property:</h5>
1473    * <ul class='spaced-list'>
1474    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.client2.RestClient#RESTCLIENT_keepHttpClientOpen RESTCLIENT_keepHttpClientOpen}
1475    *    <li><b>Name:</b>  <js>"RestClient.keepHttpClientOpen.b"</js>
1476    *    <li><b>Data type:</b>  <jk>boolean</jk>
1477    *    <li><b>System property:</b>  <c>RestClient.keepHttpClientOpen</c>
1478    *    <li><b>Environment variable:</b>  <c>RESTCLIENT_KEEPHTTPCLIENTOPEN</c>
1479    *    <li><b>Default:</b>  <jk>false</jk>
1480    *    <li><b>Methods:</b>
1481    *       <ul>
1482    *          <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#keepHttpClientOpen()}
1483    *       </ul>
1484    * </ul>
1485    *
1486    * <h5 class='section'>Description:</h5>
1487    * <p>
1488    * Don't close this client when the {@link RestClient#close()} method is called.
1489    *
1490    * <h5 class='section'>Example:</h5>
1491    * <p class='bcode w800'>
1492    *    <jc>// Create a client with a customized client and don't close the client  service.</jc>
1493    *    RestClient <jv>client</jv> = RestClient
1494    *       .<jsm>create</jsm>()
1495    *       .httpClient(<jv>myHttpClient</jv>)
1496    *       .keepHttpClientOpen()
1497    *       .build();
1498    *
1499    *    <jv>client</jv>.closeQuietly();  <jc>// Customized HttpClient won't be closed.</jc>
1500    * </p>
1501    */
1502   public static final String RESTCLIENT_keepHttpClientOpen = PREFIX + "keepHttpClientOpen.b";
1503
1504   /**
1505    * Configuration property:  Enable leak detection.
1506    *
1507    * <h5 class='section'>Property:</h5>
1508    * <ul class='spaced-list'>
1509    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.client2.RestClient#RESTCLIENT_leakDetection RESTCLIENT_leakDetection}
1510    *    <li><b>Name:</b>  <js>"RestClient.leakDetection.b"</js>
1511    *    <li><b>Data type:</b>  <jk>boolean</jk>
1512    *    <li><b>System property:</b>  <c>RestClient.leakDetection</c>
1513    *    <li><b>Environment variable:</b>  <c>RESTCLIENT_LEAKDETECTION</c>
1514    *    <li><b>Default:</b>  <jk>false</jk>
1515    *    <li><b>Methods:</b>
1516    *       <ul>
1517    *          <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#leakDetection()}
1518    *       </ul>
1519    * </ul>
1520    *
1521    * <h5 class='section'>Description:</h5>
1522    * <p>
1523    * Enable client and request/response leak detection.
1524    *
1525    * <p>
1526    * Causes messages to be logged to the console if clients or request/response objects are not properly closed
1527    * when the <c>finalize</c> methods are invoked.
1528    *
1529    * <p>
1530    * Automatically enabled with {@link Context#CONTEXT_debug}.
1531    *
1532    * <h5 class='section'>Example:</h5>
1533    * <p class='bcode w800'>
1534    *    <jc>// Create a client that logs a message if </jc>
1535    *    RestClient <jv>client</jv> = RestClient
1536    *       .<jsm>create</jsm>()
1537    *       .leakDetection()
1538    *       .logToConsole()  <jc>// Also log the error message to System.err</jc>
1539    *       .build();
1540    *
1541    *    <jv>client</jv>.closeQuietly();  <jc>// Customized HttpClient won't be closed.</jc>
1542    * </p>
1543    */
1544   public static final String RESTCLIENT_leakDetection = PREFIX + "leakDetection.b";
1545
1546   /**
1547    * Configuration property:  Logger.
1548    *
1549    * <h5 class='section'>Property:</h5>
1550    * <ul class='spaced-list'>
1551    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.client2.RestClient#RESTCLIENT_logger RESTCLIENT_logger}
1552    *    <li><b>Name:</b>  <js>"RestClient.logger.o"</js>
1553    *    <li><b>Data type:</b>
1554    *       <ul>
1555    *          <li>{@link java.util.logging.Logger}
1556    *       </ul>
1557    *    <li><b>Default:</b>  <c>Logger.<jsm>getLogger</jsm>(RestClient.<jk>class</jk>.getName())</c>
1558    *    <li><b>Methods:</b>
1559    *       <ul>
1560    *          <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#logger(Logger)}
1561    *       </ul>
1562    * </ul>
1563    *
1564    * <h5 class='section'>Description:</h5>
1565    * <p>
1566    * Specifies the logger to use for logging.
1567    */
1568   public static final String RESTCLIENT_logger = PREFIX + "logger.o";
1569
1570   /**
1571    * Configuration property:  Log to console.
1572    *
1573    * <h5 class='section'>Property:</h5>
1574    * <ul class='spaced-list'>
1575    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.client2.RestClient#RESTCLIENT_logToConsole RESTCLIENT_logToConsole}
1576    *    <li><b>Name:</b>  <js>"RestClient.logToConsole.b"</js>
1577    *    <li><b>System property:</b>  <c>RestClient.logToConsole</c>
1578    *    <li><b>Environment variable:</b>  <c>RESTCLIENT_LOGTOCONSOLE</c>
1579    *    <li><b>Data type:</b>
1580    *       <ul>
1581    *          <li><jk>boolean</jk>
1582    *       </ul>
1583    *    <li><b>Default:</b>  <jk>false</jk>
1584    *    <li><b>Methods:</b>
1585    *       <ul>
1586    *          <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#logToConsole()}
1587    *       </ul>
1588    * </ul>
1589    *
1590    * <h5 class='section'>Description:</h5>
1591    * <p>
1592    * When enabled, log messages are sent to the console in addition to the existing logger.
1593    */
1594   public static final String RESTCLIENT_logToConsole = PREFIX + "logToConsole.b";
1595
1596   /**
1597    * Configuration property:  Log requests.
1598    *
1599    * <h5 class='section'>Property:</h5>
1600    * <ul class='spaced-list'>
1601    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.client2.RestClient#RESTCLIENT_logRequests RESTCLIENT_logRequests}
1602    *    <li><b>Name:</b>  <js>"RestClient.logRequests.s"</js>
1603    *    <li><b>System property:</b>  <c>RestClient.logRequests</c>
1604    *    <li><b>Environment variable:</b>  <c>RESTCLIENT_LOGREQUESTS</c>
1605    *    <li><b>Data type:</b>
1606    *       <ul>
1607    *          <li>{@link org.apache.juneau.DetailLevel}
1608    *       </ul>
1609    *    <li><b>Default:</b>  {@link org.apache.juneau.DetailLevel#NONE}
1610    *    <li><b>Methods:</b>
1611    *       <ul>
1612    *          <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#logRequests(DetailLevel,Level,BiPredicate)}
1613    *       </ul>
1614    * </ul>
1615    *
1616    * <h5 class='section'>Description:</h5>
1617    * <p>
1618    * Causes requests/responses to be logged at the specified log level at the end of the request.
1619    *
1620    * <p>
1621    * <jsf>SIMPLE</jsf> detail produces a log message like the following:
1622    * <p class='bcode w800 console'>
1623    *    POST http://localhost:10000/testUrl, HTTP/1.1 200 OK
1624    * </p>
1625    *
1626    * <p>
1627    * <jsf>FULL</jsf> detail produces a log message like the following:
1628    * <p class='bcode w800 console'>
1629    *    === HTTP Call (outgoing) =======================================================
1630    *    === REQUEST ===
1631    *    POST http://localhost:10000/testUrl
1632    *    ---request headers---
1633    *       Debug: true
1634    *       No-Trace: true
1635    *       Accept: application/json
1636    *    ---request entity---
1637    *       Content-Type: application/json
1638    *    ---request content---
1639    *    {"foo":"bar","baz":123}
1640    *    === RESPONSE ===
1641    *    HTTP/1.1 200 OK
1642    *    ---response headers---
1643    *       Content-Type: application/json;charset=utf-8
1644    *       Content-Length: 21
1645    *       Server: Jetty(8.1.0.v20120127)
1646    *    ---response content---
1647    *    {"message":"OK then"}
1648    *    === END ========================================================================
1649    * </p>
1650    *
1651    * <p>
1652    * By default, the message is logged to the default logger.  It can be logged to a different logger via the
1653    * {@link org.apache.juneau.rest.client2.RestClient#RESTCLIENT_logger} setting or logged to the console using the
1654    * {@link org.apache.juneau.rest.client2.RestClient#RESTCLIENT_logToConsole} setting.
1655    */
1656   public static final String RESTCLIENT_logRequests = PREFIX + "logRequests.s";
1657
1658   /**
1659    * Configuration property:  Log requests log level.
1660    *
1661    * <h5 class='section'>Property:</h5>
1662    * <ul class='spaced-list'>
1663    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.client2.RestClient#RESTCLIENT_logRequestsLevel RESTCLIENT_logRequestsLevel}
1664    *    <li><b>Name:</b>  <js>"RestClient.logRequestsLevel.s"</js>
1665    *    <li><b>System property:</b>  <c>RestClient.logRequestsLevel</c>
1666    *    <li><b>Environment variable:</b>  <c>RESTCLIENT_LOGREQUESTLEVEL</c>
1667    *    <li><b>Data type:</b>
1668    *       <ul>
1669    *          <li>{@link java.util.logging.Level}
1670    *       </ul>
1671    *    <li><b>Default:</b>  {@link java.util.logging.Level#INFO}
1672    *    <li><b>Methods:</b>
1673    *       <ul>
1674    *          <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#logRequests(DetailLevel,Level,BiPredicate)}
1675    *       </ul>
1676    * </ul>
1677    *
1678    * <h5 class='section'>Description:</h5>
1679    * <p>
1680    * Used in combination with {@link org.apache.juneau.rest.client2.RestClient#RESTCLIENT_logRequests} to specify the
1681    * level to log request messages to.
1682    */
1683   public static final String RESTCLIENT_logRequestsLevel = PREFIX + "logRequestsLevel.s";
1684
1685   /**
1686    * Configuration property:  Log requests predicate.
1687    *
1688    * <h5 class='section'>Property:</h5>
1689    * <ul class='spaced-list'>
1690    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.client2.RestClient#RESTCLIENT_logRequestsPredicate RESTCLIENT_logRequestsPredicate}
1691    *    <li><b>Name:</b>  <js>"RestClient.logRequestsPredicate.o"</js>
1692    *    <li><b>Data type:</b>
1693    *       <ul>
1694    *          <li>{@link java.util.function.BiPredicate}&lt;{@link org.apache.juneau.rest.client2.RestRequest},{@link org.apache.juneau.rest.client2.RestResponse}&gt;
1695    *       </ul>
1696    *    <li><b>Default:</b>  <c>(req,res) -&gt; <jk>true</jk></c>
1697    *    <li><b>Methods:</b>
1698    *       <ul>
1699    *          <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#logRequests(DetailLevel,Level,BiPredicate)}
1700    *       </ul>
1701    * </ul>
1702    *
1703    * <h5 class='section'>Description:</h5>
1704    * <p>
1705    * Used in combination with {@link org.apache.juneau.rest.client2.RestClient#RESTCLIENT_logRequests} to specify the
1706    * level to log request messages to.
1707    */
1708   public static final String RESTCLIENT_logRequestsPredicate = PREFIX + "logRequestsPredicate.o";
1709
1710   /**
1711    * Configuration property:  Parsers.
1712    *
1713    * <h5 class='section'>Property:</h5>
1714    * <ul class='spaced-list'>
1715    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.client2.RestClient#RESTCLIENT_parsers RESTCLIENT_parsers}
1716    *    <li><b>Name:</b>  <js>"RestClient.parsers.lo"</js>
1717    *    <li><b>Data type:</b>
1718    *       <ul>
1719    *          <li><c>Class&lt;? <jk>extends</jk> {@link org.apache.juneau.parser.Parser}&gt;</c>
1720    *          <li>{@link org.apache.juneau.parser.Parser}
1721    *       </ul>
1722    *    <li><b>Default:</b>  No parsers.
1723    *    <li><b>Methods:</b>
1724    *       <ul>
1725    *          <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#parser(Class)}
1726    *          <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#parser(Parser)}
1727    *          <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#parsers(Class...)}
1728    *          <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#parsers(Parser...)}
1729    *       </ul>
1730    * </ul>
1731    *
1732    * <h5 class='section'>Description:</h5>
1733    * <p>
1734    * Associates the specified {@link Parser Parsers} with the HTTP client.
1735    *
1736    * <p>
1737    * The parsers are used to parse the HTTP response body into a POJO.
1738    *
1739    * <p>
1740    * The parser that best matches the <c>Accept</c> header will be used to parse the response body.
1741    * <br>If no <c>Accept</c> header is specified, the first parser in the list will be used.
1742    *
1743    * <h5 class='section'>Example:</h5>
1744    * <p class='bcode w800'>
1745    *    <jc>// Create a client that uses JSON and XML transport for response bodies.</jc>
1746    *    RestClient <jv>client</jv> = RestClient
1747    *       .<jsm>create</jsm>()
1748    *       .parser(JsonParser.<jk>class</jk>, XmlParser.<jk>class</jk>)
1749    *       .strict()  <jc>// Enable strict mode on parsers.</jc>
1750    *       .build();
1751    * </p>
1752    */
1753   public static final String RESTCLIENT_parsers = PREFIX + "parsers.lo";
1754
1755   /**
1756    * Configuration property:  Part parser.
1757    *
1758    * <h5 class='section'>Property:</h5>
1759    * <ul class='spaced-list'>
1760    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.client2.RestClient#RESTCLIENT_partParser RESTCLIENT_partParser}
1761    *    <li><b>Name:</b>  <js>"RestClient.partParser.o"</js>
1762    *    <li><b>Data type:</b>
1763    *       <ul>
1764    *          <li><c>Class&lt;? <jk>extends</jk> {@link org.apache.juneau.httppart.HttpPartParser}&gt;</c>
1765    *          <li>{@link org.apache.juneau.httppart.HttpPartParser}
1766    *       </ul>
1767    *    <li><b>Default:</b>  {@link org.apache.juneau.oapi.OpenApiParser};
1768    *    <li><b>Methods:</b>
1769    *       <ul>
1770    *          <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#partParser(Class)}
1771    *          <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#partParser(HttpPartParser)}
1772    *       </ul>
1773    * </ul>
1774    *
1775    * <h5 class='section'>Description:</h5>
1776    * <p>
1777    * The parser to use for parsing POJOs from form data, query parameters, headers, and path variables.
1778    *
1779    * <p>
1780    * The default part parser is {@link OpenApiParser} which allows for schema-driven marshalling.
1781    *
1782    * <h5 class='section'>Example:</h5>
1783    * <p class='bcode w800'>
1784    *    <jc>// Create a client that uses UON format by default for incoming HTTP parts.</jc>
1785    *    RestClient <jv>client</jv> = RestClient
1786    *       .<jsm>create</jsm>()
1787    *       .partParser(UonParser.<jk>class</jk>)
1788    *       .build();
1789    * </p>
1790    */
1791   public static final String RESTCLIENT_partParser = PREFIX + "partParser.o";
1792
1793   /**
1794    * Configuration property:  Part serializer.
1795    *
1796    * <h5 class='section'>Property:</h5>
1797    * <ul class='spaced-list'>
1798    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.client2.RestClient#RESTCLIENT_partSerializer RESTCLIENT_partSerializer}
1799    *    <li><b>Name:</b>  <js>"RestClient.partSerializer.o"</js>
1800    *    <li><b>Data type:</b>
1801    *       <ul>
1802    *          <li><c>Class&lt;? <jk>extends</jk> {@link org.apache.juneau.httppart.HttpPartSerializer}&gt;</c>
1803    *          <li>{@link org.apache.juneau.httppart.HttpPartSerializer}
1804    *       </ul>
1805    *    <li><b>Default:</b>  {@link org.apache.juneau.oapi.OpenApiSerializer};
1806    *    <li><b>Methods:</b>
1807    *       <ul>
1808    *          <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#partSerializer(Class)}
1809    *          <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#partSerializer(HttpPartSerializer)}
1810    *       </ul>
1811    * </ul>
1812    *
1813    * <h5 class='section'>Description:</h5>
1814    * <p>
1815    * The serializer to use for serializing POJOs in form data, query parameters, headers, and path variables.
1816    *
1817    * <p>
1818    * The default part serializer is {@link OpenApiSerializer} which allows for schema-driven marshalling.
1819    *
1820    * <h5 class='section'>Example:</h5>
1821    * <p class='bcode w800'>
1822    *    <jc>// Create a client that uses UON format by default for outgoing HTTP parts.</jc>
1823    *    RestClient <jv>client</jv> = RestClient
1824    *       .<jsm>create</jsm>()
1825    *       .partSerializer(UonSerializer.<jk>class</jk>)
1826    *       .build();
1827    * </p>
1828    */
1829   public static final String RESTCLIENT_partSerializer = PREFIX + "partSerializer.o";
1830
1831   /**
1832    * Configuration property:  Request query parameters.
1833    *
1834    * <h5 class='section'>Property:</h5>
1835    * <ul class='spaced-list'>
1836    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.client2.RestClient#RESTCLIENT_query RESTCLIENT_query}
1837    *    <li><b>Name:</b>  <js>"RestClient.query.lo"</js>
1838    *    <li><b>Data type:</b>  <c>List&lt;{@link org.apache.http.NameValuePair}&gt;</c>
1839    *    <li><b>Default:</b>  empty map
1840    *    <li><b>Methods:</b>
1841    *       <ul>
1842    *          <li class='jc'>{@link org.apache.juneau.rest.client2.RestClientBuilder}
1843    *          <ul>
1844    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#queries(Object...) queries(Object...)}
1845    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#query(String,Object) query(String,Object)}
1846    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#query(String,Object,HttpPartSchema,HttpPartSerializer) query(String,Object,HttpPartSerializer,HttpPartSchema)}
1847    *          </ul>
1848    *          <li class='jc'>{@link org.apache.juneau.rest.client2.RestRequest}
1849    *          <ul>
1850    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestRequest#query(String,Object) query(String,Object)}
1851    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestRequest#query(AddFlag,String,Object) query(EnumSet&lt;AddFlag&gt;,String,Object)}
1852    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestRequest#queries(Object...) queries(Object...)}
1853    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestRequest#queries(AddFlag,Object...) queries(EnumSet&lt;AddFlag&gt;,Object...)}
1854    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestRequest#queryPairs(Object...) queryPairs(Object...)}
1855    *             <li class='jm'>{@link org.apache.juneau.rest.client2.RestRequest#queryCustom(Object) queryCustom(Object)}
1856    *          </ul>
1857    *       </ul>
1858    * </ul>
1859    *
1860    * <h5 class='section'>Description:</h5>
1861    * <p>
1862    * Query parameters to add to every request.
1863    */
1864   public static final String RESTCLIENT_query = PREFIX + "query.lo";
1865
1866   /**
1867    * Configuration property:  Root URI.
1868    *
1869    * <h5 class='section'>Property:</h5>
1870    * <ul class='spaced-list'>
1871    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.client2.RestClient#RESTCLIENT_rootUri RESTCLIENT_rootUri}
1872    *    <li><b>Name:</b>  <js>"RestClient.rootUri.s"</js>
1873    *    <li><b>Data type:</b>  <c>String</c>
1874    *    <li><b>System property:</b>  <c>RestClient.rootUri</c>
1875    *    <li><b>Environment variable:</b>  <c>RESTCLIENT_ROOTURI</c>
1876    *    <li><b>Default:</b>  <jk>false</jk>
1877    *    <li><b>Methods:</b>
1878    *       <ul>
1879    *          <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#rootUri(Object)}
1880    *       </ul>
1881    * </ul>
1882    *
1883    * <h5 class='section'>Description:</h5>
1884    * <p>
1885    * When set, relative URI strings passed in through the various rest call methods (e.g. {@link RestClient#get(Object)}
1886    * will be prefixed with the specified root.
1887    * <br>This root URI is ignored on those methods if you pass in a {@link URL}, {@link URI}, or an absolute URI string.
1888    *
1889    * <h5 class='section'>Example:</h5>
1890    * <p class='bcode w800'>
1891    *    <jc>// Create a client that uses UON format by default for HTTP parts.</jc>
1892    *    RestClient <jv>client</jv> = RestClient
1893    *       .<jsm>create</jsm>()
1894    *       .rootUri(<js>"http://localhost:10000/foo"</js>)
1895    *       .build();
1896    *
1897    *    Bar <jv>bar</jv> = <jv>client</jv>
1898    *       .get(<js>"/bar"</js>)  <jc>// Relative to http://localhost:10000/foo</jc>
1899    *       .run()
1900    *       .getBody().as(Bar.<jk>class</jk>);
1901    * </p>
1902    */
1903   public static final String RESTCLIENT_rootUri = PREFIX + "rootUri.s";
1904
1905   /**
1906    * Configuration property:  Serializers.
1907    *
1908    * <h5 class='section'>Property:</h5>
1909    * <ul class='spaced-list'>
1910    *    <li><b>ID:</b>  {@link org.apache.juneau.rest.client2.RestClient#RESTCLIENT_serializers RESTCLIENT_serializers}
1911    *    <li><b>Name:</b>  <js>"RestClient.serializers.lo"</js>
1912    *    <li><b>Data type:</b>
1913    *       <ul>
1914    *          <li><c>Class&lt;? <jk>extends</jk> {@link org.apache.juneau.serializer.Serializer}&gt;</c>
1915    *          <li>{@link org.apache.juneau.serializer.Serializer}
1916    *       </ul>
1917    *    <li><b>Default:</b>  No serializers.
1918    *    <li><b>Methods:</b>
1919    *       <ul>
1920    *          <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#serializer(Class)}
1921    *          <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#serializer(Serializer)}
1922    *          <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#serializers(Class...)}
1923    *          <li class='jm'>{@link org.apache.juneau.rest.client2.RestClientBuilder#serializers(Serializer...)}
1924    *       </ul>
1925    * </ul>
1926    *
1927    * <h5 class='section'>Description:</h5>
1928    * <p>
1929    * Associates the specified {@link Serializer Serializers} with the HTTP client.
1930    *
1931    * <p>
1932    * The serializer is used to serialize POJOs into the HTTP request body.
1933    *
1934    * <p>
1935    * The serializer that best matches the <c>Content-Type</c> header will be used to serialize the request body.
1936    * <br>If no <c>Content-Type</c> header is specified, the first serializer in the list will be used.
1937    *
1938    * <h5 class='section'>Example:</h5>
1939    * <p class='bcode w800'>
1940    *    <jc>// Create a client that uses JSON and XML transport for request bodies.</jc>
1941    *    RestClient <jv>client</jv> = RestClient
1942    *       .<jsm>create</jsm>()
1943    *       .serializers(JsonSerializer.<jk>class</jk>,XmlSerializer.<jk>class</jk>)
1944    *       .sortCollections()  <jc>// Sort any collections being serialized.</jc>
1945    *       .build();
1946    * </p>
1947    */
1948   public static final String RESTCLIENT_serializers = PREFIX + "serializers.lo";
1949
1950   static final String RESTCLIENT_httpClient = PREFIX + "httpClient.o";
1951   static final String RESTCLIENT_httpClientBuilder= PREFIX + "httpClientBuilder.o";
1952
1953   private final HeaderSupplier headers;
1954   private final NameValuePairSupplier query, formData;
1955   final CloseableHttpClient httpClient;
1956   private final boolean keepHttpClientOpen, leakDetection;
1957   private final UrlEncodingSerializer urlEncodingSerializer;  // Used for form posts only.
1958   private final HttpPartSerializer partSerializer;
1959   private final HttpPartParser partParser;
1960   private final RestCallHandler callHandler;
1961   private final String rootUri;
1962   private volatile boolean isClosed = false;
1963   private final StackTraceElement[] creationStack;
1964   private final Logger logger;
1965   final DetailLevel logRequests;
1966   final BiPredicate<RestRequest,RestResponse> logRequestsPredicate;
1967   final Level logRequestsLevel;
1968   final boolean ignoreErrors;
1969   private final boolean logToConsole;
1970   private final PrintStream console;
1971   private StackTraceElement[] closedStack;
1972   private static final ConcurrentHashMap<Class<?>,Context> requestContexts = new ConcurrentHashMap<>();
1973
1974   // These are read directly by RestCall.
1975   final SerializerGroup serializers;
1976   final ParserGroup parsers;
1977   Predicate<Integer> errorCodes;
1978
1979   final RestCallInterceptor[] interceptors;
1980
1981   // This is lazy-created.
1982   private volatile ExecutorService executorService;
1983   private final boolean executorServiceShutdownOnClose;
1984
1985   /**
1986    * Instantiates a new clean-slate {@link RestClientBuilder} object.
1987    *
1988    * @return A new {@link RestClientBuilder} object.
1989    */
1990   public static RestClientBuilder create() {
1991      return new RestClientBuilder(PropertyStore.DEFAULT);
1992   }
1993
1994   @Override /* Context */
1995   public RestClientBuilder builder() {
1996      return new RestClientBuilder(getPropertyStore());
1997   }
1998
1999   private static final
2000      Predicate<Integer> ERROR_CODES_DEFAULT = x ->  x<=0 || x>=400;
2001
2002   private static final
2003      BiPredicate<RestRequest,RestResponse> LOG_REQUESTS_PREDICATE_DEFAULT = (req,res) -> true;
2004
2005   /**
2006    * Constructor.
2007    *
2008    * @param ps The property store containing the unmodifiable configuration for this client.
2009    */
2010   @SuppressWarnings("unchecked")
2011   protected RestClient(PropertyStore ps) {
2012      super(ps);
2013      this.httpClient = getInstanceProperty(RESTCLIENT_httpClient, CloseableHttpClient.class, null);
2014      this.keepHttpClientOpen = getBooleanProperty(RESTCLIENT_keepHttpClientOpen, false);
2015      this.errorCodes = getInstanceProperty(RESTCLIENT_errorCodes, Predicate.class, ERROR_CODES_DEFAULT);
2016      this.executorServiceShutdownOnClose = getBooleanProperty(RESTCLIENT_executorServiceShutdownOnClose, false);
2017      this.rootUri = StringUtils.nullIfEmpty(getStringProperty(RESTCLIENT_rootUri, "").replaceAll("\\/$", ""));
2018      this.leakDetection = getBooleanProperty(RESTCLIENT_leakDetection, isDebug());
2019      this.ignoreErrors = getBooleanProperty(RESTCLIENT_ignoreErrors, false);
2020      this.logger = getInstanceProperty(RESTCLIENT_logger, Logger.class, Logger.getLogger(RestClient.class.getName()));
2021      this.logRequests = getInstanceProperty(RESTCLIENT_logRequests, DetailLevel.class, isDebug() ? DetailLevel.FULL : DetailLevel.NONE);
2022      this.logRequestsLevel = getInstanceProperty(RESTCLIENT_logRequestsLevel, Level.class, isDebug() ? Level.WARNING : Level.OFF);
2023      this.logToConsole = getBooleanProperty(RESTCLIENT_logToConsole, isDebug());
2024      this.console = getInstanceProperty(RESTCLIENT_console, PrintStream.class, System.err);
2025      this.logRequestsPredicate = getInstanceProperty(RESTCLIENT_logRequestsPredicate, BiPredicate.class, LOG_REQUESTS_PREDICATE_DEFAULT);
2026
2027      SerializerGroupBuilder sgb = SerializerGroup.create();
2028      for (Object o : getArrayProperty(RESTCLIENT_serializers, Object.class)) {
2029         if (o instanceof Serializer) {
2030            sgb.append((Serializer)o);  // Don't apply PropertyStore.
2031         } else if (o instanceof Class) {
2032            Class<?> c = (Class<?>)o;
2033            if (! Serializer.class.isAssignableFrom(c))
2034               throw new ConfigException("RESTCLIENT_serializers property had invalid class of type ''{0}''", c.getName());
2035            sgb.append(ContextCache.INSTANCE.create((Class<? extends Serializer>)o, ps));
2036         } else {
2037            throw new ConfigException("RESTCLIENT_serializers property had invalid object of type ''{0}''", o.getClass().getName());
2038         }
2039      }
2040      this.serializers = sgb.build();
2041
2042      ParserGroupBuilder pgb = ParserGroup.create();
2043      for (Object o : getArrayProperty(RESTCLIENT_parsers, Object.class)) {
2044         if (o instanceof Parser) {
2045            pgb.append((Parser)o);  // Don't apply PropertyStore.
2046         } else if (o instanceof Class) {
2047            Class<?> c = (Class<?>)o;
2048            if (! Parser.class.isAssignableFrom(c))
2049               throw new ConfigException("RESTCLIENT_parsers property had invalid class of type ''{0}''", c.getName());
2050            pgb.append(ContextCache.INSTANCE.create((Class<? extends Parser>)o, ps));
2051         } else {
2052            throw new ConfigException("RESTCLIENT_parsers property had invalid object of type ''{0}''", o.getClass().getName());
2053         }
2054      }
2055      this.parsers = pgb.build();
2056
2057      this.urlEncodingSerializer = new SerializerBuilder(ps).build(UrlEncodingSerializer.class);
2058      this.partSerializer = getInstanceProperty(RESTCLIENT_partSerializer, HttpPartSerializer.class, OpenApiSerializer.class, ResourceResolver.FUZZY, ps);
2059      this.partParser = getInstanceProperty(RESTCLIENT_partParser, HttpPartParser.class, OpenApiParser.class, ResourceResolver.FUZZY, ps);
2060      this.executorService = getInstanceProperty(RESTCLIENT_executorService, ExecutorService.class, null);
2061
2062      HttpPartSerializerSession partSerializerSession = partSerializer.createPartSession(null);
2063
2064      this.headers = HeaderSupplier.create();
2065      for (Object o : getListProperty(RESTCLIENT_headers, Object.class)) {
2066         o = buildBuilders(o, partSerializerSession);
2067         if (o instanceof HeaderSupplier)
2068            headers.add((HeaderSupplier)o);
2069         else
2070            headers.add(BasicHeader.cast(o));
2071      }
2072
2073      this.query = NameValuePairSupplier.create();
2074      for (Object o : getListProperty(RESTCLIENT_query, Object.class)) {
2075         o = buildBuilders(o, partSerializerSession);
2076         if (o instanceof NameValuePairSupplier)
2077            query.add((NameValuePairSupplier)o);
2078         else
2079            query.add(BasicNameValuePair.cast(o));
2080      }
2081
2082      this.formData = NameValuePairSupplier.create();
2083      for (Object o : getListProperty(RESTCLIENT_formData, Object.class)) {
2084         o = buildBuilders(o, partSerializerSession);
2085         if (o instanceof NameValuePairSupplier)
2086            formData.add((NameValuePairSupplier)o);
2087         else
2088            formData.add(BasicNameValuePair.cast(o));
2089      }
2090
2091      this.callHandler = getInstanceProperty(RESTCLIENT_callHandler, RestCallHandler.class, BasicRestCallHandler.class, ResourceResolver.FUZZY, ps, this);
2092
2093      this.interceptors = getInstanceArrayProperty(RESTCLIENT_interceptors, RestCallInterceptor.class, new RestCallInterceptor[0]);
2094
2095      creationStack = isDebug() ? Thread.currentThread().getStackTrace() : null;
2096   }
2097
2098   private static Object buildBuilders(Object o, HttpPartSerializerSession ss) {
2099      if (o instanceof SerializedHeader)
2100         return ((SerializedHeader)o).serializer(ss, false);
2101      if (o instanceof SerializedNameValuePair)
2102         return ((SerializedNameValuePair)o).serializer(ss, false);
2103      return o;
2104   }
2105
2106   /**
2107    * Calls {@link CloseableHttpClient#close()} on the underlying {@link CloseableHttpClient}.
2108    *
2109    * <p>
2110    * It's good practice to call this method after the client is no longer used.
2111    *
2112    * @throws IOException Thrown by underlying stream.
2113    */
2114   @Override
2115   public void close() throws IOException {
2116      isClosed = true;
2117      if (! keepHttpClientOpen)
2118         httpClient.close();
2119      if (executorService != null && executorServiceShutdownOnClose)
2120         executorService.shutdown();
2121      if (creationStack != null)
2122         closedStack = Thread.currentThread().getStackTrace();
2123   }
2124
2125   /**
2126    * Same as {@link #close()}, but ignores any exceptions.
2127    */
2128   public void closeQuietly() {
2129      isClosed = true;
2130      try {
2131         if (! keepHttpClientOpen)
2132            httpClient.close();
2133         if (executorService != null && executorServiceShutdownOnClose)
2134            executorService.shutdown();
2135      } catch (Throwable t) {}
2136      if (creationStack != null)
2137         closedStack = Thread.currentThread().getStackTrace();
2138   }
2139
2140   /**
2141    * Entrypoint for executing all requests and returning a response.
2142    *
2143    * <p>
2144    * Subclasses can override this method to provide specialized handling.
2145    *
2146    * <p>
2147    * The behavior of this method can also be modified by specifying a different {@link RestCallHandler}.
2148    *
2149    * <ul class='seealso'>
2150    *    <li class='jf'>{@link RestClient#RESTCLIENT_callHandler}
2151    *    <li class='jm'>{@link RestClientBuilder#callHandler(Class)}
2152    *    <li class='jm'>{@link RestClientBuilder#callHandler(RestCallHandler)}
2153    * </ul>
2154    *
2155    * @param target The target host for the request.
2156    *    <br>Implementations may accept <jk>null</jk> if they can still determine a route, for example to a default
2157    *       target or by inspecting the request.
2158    * @param request The request to execute.
2159    * @param context The context to use for the execution, or <jk>null</jk> to use the default context.
2160    * @return
2161    *    The response to the request.
2162    *    <br>This is always a final response, never an intermediate response with an 1xx status code.
2163    *    <br>Whether redirects or authentication challenges will be returned or handled automatically depends on the
2164    *       implementation and configuration of this client.
2165    * @throws IOException In case of a problem or the connection was aborted.
2166    * @throws ClientProtocolException In case of an http protocol error.
2167    */
2168   @Override /* RestCallHandler */
2169   public HttpResponse run(HttpHost target, HttpRequest request, HttpContext context) throws ClientProtocolException, IOException {
2170      return callHandler.run(target, request, context);
2171   }
2172
2173   /**
2174    * Perform a <c>GET</c> request against the specified URI.
2175    *
2176    * @param uri
2177    *    The URI of the remote REST resource.
2178    *    <br>Can be any of the following types:
2179    *    <ul>
2180    *       <li>{@link URIBuilder}
2181    *       <li>{@link URI}
2182    *       <li>{@link URL}
2183    *       <li>{@link String}
2184    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
2185    *    </ul>
2186    * @return
2187    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
2188    *    as a parsed object.
2189    * @throws RestCallException If any authentication errors occurred.
2190    */
2191   public RestRequest get(Object uri) throws RestCallException {
2192      return request("GET", uri, false);
2193   }
2194
2195   /**
2196    * Perform a <c>GET</c> request against the root URI.
2197    *
2198    * @return
2199    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
2200    *    as a parsed object.
2201    * @throws RestCallException If any authentication errors occurred.
2202    */
2203   public RestRequest get() throws RestCallException {
2204      return request("GET", null, false);
2205   }
2206
2207   /**
2208    * Perform a <c>PUT</c> request against the specified URI.
2209    *
2210    * @param uri
2211    *    The URI of the remote REST resource.
2212    *    <br>Can be any of the following types:
2213    *    <ul>
2214    *       <li>{@link URIBuilder}
2215    *       <li>{@link URI}
2216    *       <li>{@link URL}
2217    *       <li>{@link String}
2218    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
2219    *    </ul>
2220    * @param body
2221    *    The object to serialize and transmit to the URI as the body of the request.
2222    *    Can be of the following types:
2223    *    <ul class='spaced-list'>
2224    *       <li>
2225    *          {@link Reader} - Raw contents of {@code Reader} will be serialized to remote resource.
2226    *       <li>
2227    *          {@link InputStream} - Raw contents of {@code InputStream} will be serialized to remote resource.
2228    *       <li>
2229    *          {@link Object} - POJO to be converted to text using the {@link Serializer} registered with the
2230    *          {@link RestClient}.
2231    *       <li>
2232    *          {@link HttpEntity} / {@link HttpResource} - Bypass Juneau serialization and pass HttpEntity directly to HttpClient.
2233    *       <li>
2234    *          {@link NameValuePairSupplier} - Converted to a URL-encoded FORM post.
2235    *       <li>
2236    *          {@link Supplier} - A supplier of anything on this list.
2237    *    </ul>
2238    * @return
2239    *    A {@link RestRequest} object that can be further tailored before executing the request
2240    *    and getting the response as a parsed object.
2241    * @throws RestCallException If any authentication errors occurred.
2242    */
2243   public RestRequest put(Object uri, Object body) throws RestCallException {
2244      return request("PUT", uri, true).body(body);
2245   }
2246
2247   /**
2248    * Perform a <c>PUT</c> request against the specified URI using a plain text body bypassing the serializer.
2249    *
2250    * @param uri
2251    *    The URI of the remote REST resource.
2252    *    <br>Can be any of the following types:
2253    *    <ul>
2254    *       <li>{@link URIBuilder}
2255    *       <li>{@link URI}
2256    *       <li>{@link URL}
2257    *       <li>{@link String}
2258    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
2259    *    </ul>
2260    * @param body
2261    *    The object to serialize and transmit to the URI as the body of the request bypassing the serializer.
2262    * @param contentType The content type of the request.
2263    * @return
2264    *    A {@link RestRequest} object that can be further tailored before executing the request
2265    *    and getting the response as a parsed object.
2266    * @throws RestCallException If any authentication errors occurred.
2267    */
2268   public RestRequest put(Object uri, String body, String contentType) throws RestCallException {
2269      return request("PUT", uri, true).bodyString(body).contentType(contentType);
2270   }
2271
2272   /**
2273    * Same as {@link #put(Object, Object)} but don't specify the input yet.
2274    *
2275    * <p>
2276    * You must call either {@link RestRequest#body(Object)} or {@link RestRequest#formData(String, Object)}
2277    * to set the contents on the result object.
2278    *
2279    * @param uri
2280    *    The URI of the remote REST resource.
2281    *    <br>Can be any of the following types:
2282    *    <ul>
2283    *       <li>{@link URIBuilder}
2284    *       <li>{@link URI}
2285    *       <li>{@link URL}
2286    *       <li>{@link String}
2287    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
2288    *    </ul>
2289    * @return
2290    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
2291    *    as a parsed object.
2292    * @throws RestCallException REST call failed.
2293    */
2294   public RestRequest put(Object uri) throws RestCallException {
2295      return request("PUT", uri, true);
2296   }
2297
2298   /**
2299    * Perform a <c>POST</c> request against the specified URI.
2300    *
2301    * <ul class='notes'>
2302    *    <li>Use {@link #formPost(Object, Object)} for <c>application/x-www-form-urlencoded</c> form posts.
2303    * </ul>
2304    *
2305    * @param uri
2306    *    The URI of the remote REST resource.
2307    *    <br>Can be any of the following types:
2308    *    <ul>
2309    *       <li>{@link URIBuilder}
2310    *       <li>{@link URI}
2311    *       <li>{@link URL}
2312    *       <li>{@link String}
2313    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
2314    *    </ul>
2315    * @param body
2316    *    The object to serialize and transmit to the URI as the body of the request.
2317    *    Can be of the following types:
2318    *    <ul class='spaced-list'>
2319    *       <li>
2320    *          {@link Reader} - Raw contents of {@code Reader} will be serialized to remote resource.
2321    *       <li>
2322    *          {@link InputStream} - Raw contents of {@code InputStream} will be serialized to remote resource.
2323    *       <li>
2324    *          {@link Object} - POJO to be converted to text using the {@link Serializer} registered with the
2325    *          {@link RestClient}.
2326    *       <li>
2327    *          {@link HttpEntity} / {@link HttpResource} - Bypass Juneau serialization and pass HttpEntity directly to HttpClient.
2328    *       <li>
2329    *          {@link NameValuePairSupplier} - Converted to a URL-encoded FORM post.
2330    *       <li>
2331    *          {@link Supplier} - A supplier of anything on this list.
2332    *    </ul>
2333    * @return
2334    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
2335    *    as a parsed object.
2336    * @throws RestCallException If any authentication errors occurred.
2337    */
2338   public RestRequest post(Object uri, Object body) throws RestCallException {
2339      return request("POST", uri, true).body(body);
2340   }
2341
2342   /**
2343    * Perform a <c>POST</c> request against the specified URI as a plain text body bypassing the serializer.
2344    *
2345    * @param uri
2346    *    The URI of the remote REST resource.
2347    *    <br>Can be any of the following types:
2348    *    <ul>
2349    *       <li>{@link URIBuilder}
2350    *       <li>{@link URI}
2351    *       <li>{@link URL}
2352    *       <li>{@link String}
2353    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
2354    *    </ul>
2355    * @param body
2356    *    The object to serialize and transmit to the URI as the body of the request bypassing the serializer.
2357    * @param contentType
2358    *    The content type of the request.
2359    * @return
2360    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
2361    *    as a parsed object.
2362    * @throws RestCallException If any authentication errors occurred.
2363    */
2364   public RestRequest post(Object uri, String body, String contentType) throws RestCallException {
2365      return request("POST", uri, true).bodyString(body).contentType(contentType);
2366   }
2367
2368   /**
2369    * Same as {@link #post(Object, Object)} but don't specify the input yet.
2370    *
2371    * <p>
2372    * You must call either {@link RestRequest#body(Object)} or {@link RestRequest#formData(String, Object)} to set the
2373    * contents on the result object.
2374    *
2375    * <ul class='notes'>
2376    *    <li>Use {@link #formPost(Object, Object)} for <c>application/x-www-form-urlencoded</c> form posts.
2377    * </ul>
2378    *
2379    * @param uri
2380    *    The URI of the remote REST resource.
2381    *    <br>Can be any of the following types:
2382    *    <ul>
2383    *       <li>{@link URIBuilder}
2384    *       <li>{@link URI}
2385    *       <li>{@link URL}
2386    *       <li>{@link String}
2387    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
2388    *    </ul>
2389    * @return
2390    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
2391    *    as a parsed object.
2392    * @throws RestCallException REST call failed.
2393    */
2394   public RestRequest post(Object uri) throws RestCallException {
2395      return request("POST", uri, true);
2396   }
2397
2398   /**
2399    * Perform a <c>DELETE</c> request against the specified URI.
2400    *
2401    * @param uri
2402    *    The URI of the remote REST resource.
2403    *    <br>Can be any of the following types:
2404    *    <ul>
2405    *       <li>{@link URIBuilder}
2406    *       <li>{@link URI}
2407    *       <li>{@link URL}
2408    *       <li>{@link String}
2409    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
2410    *    </ul>
2411    * @return
2412    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
2413    *    as a parsed object.
2414    * @throws RestCallException If any authentication errors occurred.
2415    */
2416   public RestRequest delete(Object uri) throws RestCallException {
2417      return request("DELETE", uri, false);
2418   }
2419
2420   /**
2421    * Perform an <c>OPTIONS</c> request against the specified URI.
2422    *
2423    * @param uri
2424    *    The URI of the remote REST resource.
2425    *    <br>Can be any of the following types:
2426    *    <ul>
2427    *       <li>{@link URIBuilder}
2428    *       <li>{@link URI}
2429    *       <li>{@link URL}
2430    *       <li>{@link String}
2431    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
2432    *    </ul>
2433    * @return
2434    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
2435    *    as a parsed object.
2436    * @throws RestCallException If any authentication errors occurred.
2437    */
2438   public RestRequest options(Object uri) throws RestCallException {
2439      return request("OPTIONS", uri, true);
2440   }
2441
2442   /**
2443    * Perform a <c>HEAD</c> request against the specified URI.
2444    *
2445    * @param uri
2446    *    The URI of the remote REST resource.
2447    *    <br>Can be any of the following types:
2448    *    <ul>
2449    *       <li>{@link URIBuilder}
2450    *       <li>{@link URI}
2451    *       <li>{@link URL}
2452    *       <li>{@link String}
2453    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
2454    *    </ul>
2455    * @return
2456    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
2457    *    as a parsed object.
2458    * @throws RestCallException If any authentication errors occurred.
2459    */
2460   public RestRequest head(Object uri) throws RestCallException {
2461      return request("HEAD", uri, false);
2462   }
2463
2464   /**
2465    * Perform a <c>POST</c> request with a content type of <c>application/x-www-form-urlencoded</c>
2466    * against the specified URI.
2467    *
2468    * @param uri
2469    *    The URI of the remote REST resource.
2470    *    <br>Can be any of the following types:
2471    *    <ul>
2472    *       <li>{@link URIBuilder}
2473    *       <li>{@link URI}
2474    *       <li>{@link URL}
2475    *       <li>{@link String}
2476    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
2477    *    </ul>
2478    * @param body
2479    *    The object to serialize and transmit to the URI as the body of the request.
2480    *    <ul class='spaced-list'>
2481    *       <li>{@link NameValuePair} - URL-encoded as a single name-value pair.
2482    *       <li>{@link NameValuePair} array - URL-encoded as name value pairs.
2483    *       <li>{@link NameValuePairSupplier} - URL-encoded as name value pairs.
2484    *       <li>{@link Reader}/{@link InputStream}- Streamed directly and <l>Content-Type</l> set to <js>"application/x-www-form-urlencoded"</js>
2485    *       <li>{@link HttpResource}/{@link BasicHttpResource} - Raw contents will be serialized to remote resource.  Additional headers and media type will be set on request.
2486    *       <li>{@link HttpEntity}/{@link BasicHttpEntity} - Bypass Juneau serialization and pass HttpEntity directly to HttpClient.
2487    *       <li>{@link Object} - Converted to a {@link SerializedHttpEntity} using {@link UrlEncodingSerializer} to serialize.
2488    *       <li>{@link Supplier} - A supplier of anything on this list.
2489    *    </ul>
2490    * @return
2491    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
2492    *    as a parsed object.
2493    * @throws RestCallException If any authentication errors occurred.
2494    */
2495   public RestRequest formPost(Object uri, Object body) throws RestCallException {
2496      RestRequest req = request("POST", uri, true);
2497      try {
2498         if (body instanceof Supplier)
2499            body = ((Supplier<?>)body).get();
2500         if (body instanceof NameValuePair)
2501            return req.body(new UrlEncodedFormEntity(AList.of((NameValuePair)body)));
2502         if (body instanceof NameValuePair[])
2503            return req.body(new UrlEncodedFormEntity(Arrays.asList((NameValuePair[])body)));
2504         if (body instanceof NameValuePairSupplier)
2505            return req.body(new UrlEncodedFormEntity((NameValuePairSupplier)body));
2506         if (body instanceof HttpResource) {
2507            for (Header h : ((HttpResource)body).getHeaders())
2508               req.header(h);
2509         }
2510         if (body instanceof HttpEntity) {
2511            HttpEntity e = (HttpEntity)body;
2512            if (e.getContentType() == null)
2513               req.contentType("application/x-www-form-urlencoded");
2514            return req.body(e);
2515         }
2516         if (body instanceof Reader || body instanceof InputStream)
2517            return req.contentType("application/x-www-form-urlencoded").body(body);
2518         return req.body(SerializedHttpEntity.of(body, urlEncodingSerializer));
2519      } catch (IOException e) {
2520         throw new RestCallException(null, e, "Could not read form post body.");
2521      }
2522   }
2523
2524   /**
2525    * Same as {@link #formPost(Object, Object)} but doesn't specify the input yet.
2526    *
2527    * @param uri
2528    *    The URI of the remote REST resource.
2529    *    <br>Can be any of the following types:
2530    *    <ul>
2531    *       <li>{@link URIBuilder}
2532    *       <li>{@link URI}
2533    *       <li>{@link URL}
2534    *       <li>{@link String}
2535    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
2536    *    </ul>
2537    * @return
2538    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
2539    *    as a parsed object.
2540    * @throws RestCallException If any authentication errors occurred.
2541    */
2542   public RestRequest formPost(Object uri) throws RestCallException {
2543      return request("POST", uri, true);
2544   }
2545
2546   /**
2547    * Perform a <c>POST</c> request with a content type of <c>application/x-www-form-urlencoded</c>
2548    * against the specified URI.
2549    *
2550    * @param uri
2551    *    The URI of the remote REST resource.
2552    *    <br>Can be any of the following types:
2553    *    <ul>
2554    *       <li>{@link URIBuilder}
2555    *       <li>{@link URI}
2556    *       <li>{@link URL}
2557    *       <li>{@link String}
2558    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
2559    *    </ul>
2560    * @param parameters
2561    *    The parameters of the form post.
2562    *    <br>The parameters represent name/value pairs and must be an even number of arguments.
2563    *    <br>Parameters are converted to {@link BasicNameValuePair} objects.
2564    * @return
2565    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
2566    *    as a parsed object.
2567    * @throws RestCallException If any authentication errors occurred.
2568    */
2569   public RestRequest formPostPairs(Object uri, Object...parameters) throws RestCallException {
2570      return formPost(uri, NameValuePairSupplier.ofPairs(parameters));
2571   }
2572
2573   /**
2574    * Perform a <c>PATCH</c> request against the specified URI.
2575    *
2576    * @param uri
2577    *    The URI of the remote REST resource.
2578    *    <br>Can be any of the following types:
2579    *    <ul>
2580    *       <li>{@link URIBuilder}
2581    *       <li>{@link URI}
2582    *       <li>{@link URL}
2583    *       <li>{@link String}
2584    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
2585    *    </ul>
2586    * @param body
2587    *    The object to serialize and transmit to the URI as the body of the request.
2588    *    Can be of the following types:
2589    *    <ul class='spaced-list'>
2590    *       <li>
2591    *          {@link Reader} - Raw contents of {@code Reader} will be serialized to remote resource.
2592    *       <li>
2593    *          {@link InputStream} - Raw contents of {@code InputStream} will be serialized to remote resource.
2594    *       <li>
2595    *          {@link HttpResource}/{@link BasicHttpResource} - Raw contents will be serialized to remote resource.  Additional headers and media type will be set on request.
2596    *       <li>
2597    *          {@link HttpEntity}/{@link BasicHttpEntity} - Bypass Juneau serialization and pass HttpEntity directly to HttpClient.
2598    *       <li>
2599    *          {@link Object} - POJO to be converted to text using the {@link Serializer} registered with the
2600    *          {@link RestClient}.
2601    *       <li>
2602    *          {@link NameValuePairSupplier} - Converted to a URL-encoded FORM post.
2603    *       <li>
2604    *          {@link Supplier} - A supplier of anything on this list.
2605    *    </ul>
2606    * @return
2607    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
2608    *    as a parsed object.
2609    * @throws RestCallException If any authentication errors occurred.
2610    */
2611   public RestRequest patch(Object uri, Object body) throws RestCallException {
2612      return request("PATCH", uri, true).body(body);
2613   }
2614
2615   /**
2616    * Perform a <c>PATCH</c> request against the specified URI as a plain text body bypassing the serializer.
2617    *
2618    * @param uri
2619    *    The URI of the remote REST resource.
2620    *    <br>Can be any of the following types:
2621    *    <ul>
2622    *       <li>{@link URIBuilder}
2623    *       <li>{@link URI}
2624    *       <li>{@link URL}
2625    *       <li>{@link String}
2626    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
2627    *    </ul>
2628    * @param body
2629    *    The object to serialize and transmit to the URI as the body of the request bypassing the serializer.
2630    * @param contentType
2631    *    The content type of the request.
2632    * @return
2633    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
2634    *    as a parsed object.
2635    * @throws RestCallException If any authentication errors occurred.
2636    */
2637   public RestRequest patch(Object uri, String body, String contentType) throws RestCallException {
2638      return request("PATCH", uri, true).bodyString(body).contentType(contentType);
2639   }
2640
2641   /**
2642    * Same as {@link #patch(Object, Object)} but don't specify the input yet.
2643    *
2644    * <p>
2645    * You must call {@link RestRequest#body(Object)} to set the contents on the result object.
2646    *
2647    * @param uri
2648    *    The URI of the remote REST resource.
2649    *    <br>Can be any of the following types:
2650    *    <ul>
2651    *       <li>{@link URIBuilder}
2652    *       <li>{@link URI}
2653    *       <li>{@link URL}
2654    *       <li>{@link String}
2655    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
2656    *    </ul>
2657    * @return
2658    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
2659    *    as a parsed object.
2660    * @throws RestCallException REST call failed.
2661    */
2662   public RestRequest patch(Object uri) throws RestCallException {
2663      return request("PATCH", uri, true);
2664   }
2665
2666
2667   /**
2668    * Performs a REST call where the entire call is specified in a simple string.
2669    *
2670    * <p>
2671    * This method is useful for performing callbacks when the target of a callback is passed in
2672    * on an initial request, for example to signal when a long-running process has completed.
2673    *
2674    * <p>
2675    * The call string can be any of the following formats:
2676    * <ul class='spaced-list'>
2677    *    <li>
2678    *       <js>"[method] [uri]"</js> - e.g. <js>"GET http://localhost/callback"</js>
2679    *    <li>
2680    *       <js>"[method] [uri] [payload]"</js> - e.g. <js>"POST http://localhost/callback some text payload"</js>
2681    *    <li>
2682    *       <js>"[method] [headers] [uri] [payload]"</js> - e.g. <js>"POST {'Content-Type':'text/json'} http://localhost/callback {'some':'json'}"</js>
2683    * </ul>
2684    * <p>
2685    * The payload will always be sent using a simple {@link StringEntity}.
2686    *
2687    * @param callString The call string.
2688    * @return
2689    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
2690    *    as a parsed object.
2691    * @throws RestCallException REST call failed.
2692    */
2693   public RestRequest callback(String callString) throws RestCallException {
2694      callString = emptyIfNull(callString);
2695
2696      // S01 - Looking for end of method.
2697      // S02 - Found end of method, looking for beginning of URI or headers.
2698      // S03 - Found beginning of headers, looking for end of headers.
2699      // S04 - Found end of headers, looking for beginning of URI.
2700      // S05 - Found beginning of URI, looking for end of URI.
2701
2702      StateMachineState state = S01;
2703
2704      int mark = 0;
2705      String method = null, headers = null, uri = null, content = null;
2706      for (int i = 0; i < callString.length(); i++) {
2707         char c = callString.charAt(i);
2708         if (state == S01) {
2709            if (isWhitespace(c)) {
2710               method = callString.substring(mark, i);
2711               state = S02;
2712            }
2713         } else if (state == S02) {
2714            if (! isWhitespace(c)) {
2715               mark = i;
2716               if (c == '{')
2717                  state = S03;
2718               else
2719                  state = S05;
2720            }
2721         } else if (state == S03) {
2722            if (c == '}') {
2723               headers = callString.substring(mark, i+1);
2724               state = S04;
2725            }
2726         } else if (state == S04) {
2727            if (! isWhitespace(c)) {
2728               mark = i;
2729               state = S05;
2730            }
2731         } else /* (state == S05) */ {
2732            if (isWhitespace(c)) {
2733               uri = callString.substring(mark, i);
2734               content = callString.substring(i).trim();
2735               break;
2736            }
2737         }
2738      }
2739
2740      if (state != S05)
2741         throw new RestCallException(null, null, "Invalid format for call string.  State={0}", state);
2742
2743      try {
2744         RestRequest req = request(method, uri, isNotEmpty(content));
2745         if (headers != null)
2746            for (Map.Entry<String,Object> e : OMap.ofJson(headers).entrySet())
2747               req.header(BasicHeader.of(e.getKey(), e.getValue()));
2748         if (isNotEmpty(content))
2749            req.bodyString(content);
2750         return req;
2751      } catch (ParseException e) {
2752         throw new RestCallException(null, e, "Invalid format for call string.");
2753      }
2754   }
2755
2756   /**
2757    * Perform a generic REST call.
2758    *
2759    * @param method The HTTP method.
2760    * @param uri
2761    *    The URI of the remote REST resource.
2762    *    <br>Can be any of the following types:
2763    *    <ul>
2764    *       <li>{@link URIBuilder}
2765    *       <li>{@link URI}
2766    *       <li>{@link URL}
2767    *       <li>{@link String}
2768    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
2769    *    </ul>
2770    * @param body
2771    *    The HTTP body content.
2772    *    Can be of the following types:
2773    *    <ul class='spaced-list'>
2774    *       <li>
2775    *          {@link Reader} - Raw contents of {@code Reader} will be serialized to remote resource.
2776    *       <li>
2777    *          {@link InputStream} - Raw contents of {@code InputStream} will be serialized to remote resource.
2778    *       <li>
2779    *          {@link HttpResource}/{@link BasicHttpResource} - Raw contents will be serialized to remote resource.  Additional headers and media type will be set on request.
2780    *       <li>
2781    *          {@link HttpEntity}/{@link BasicHttpEntity} - Bypass Juneau serialization and pass HttpEntity directly to HttpClient.
2782    *       <li>
2783    *          {@link Object} - POJO to be converted to text using the {@link Serializer} registered with the
2784    *          {@link RestClient}.
2785    *       <li>
2786    *          {@link NameValuePairSupplier} - Converted to a URL-encoded FORM post.
2787    *       <li>
2788    *          {@link Supplier} - A supplier of anything on this list.
2789    *    </ul>
2790    *    This parameter is IGNORED if the method type normally does not have content.
2791    * @return
2792    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
2793    *    as a parsed object.
2794    * @throws RestCallException If any authentication errors occurred.
2795    */
2796   public RestRequest request(String method, Object uri, Object body) throws RestCallException {
2797      boolean b = hasContent(method);
2798      RestRequest rc = request(method, uri, b);
2799      if (b)
2800         rc.body(body);
2801      return rc;
2802   }
2803
2804   /**
2805    * Perform a generic REST call.
2806    *
2807    * @param method The HTTP method.
2808    * @param uri
2809    *    The URI of the remote REST resource.
2810    *    <br>Can be any of the following types:
2811    *    <ul>
2812    *       <li>{@link URIBuilder}
2813    *       <li>{@link URI}
2814    *       <li>{@link URL}
2815    *       <li>{@link String}
2816    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
2817    *    </ul>
2818    * @return
2819    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
2820    *    as a parsed object.
2821    * @throws RestCallException If any authentication errors occurred.
2822    */
2823   public RestRequest request(String method, Object uri) throws RestCallException {
2824      RestRequest rc = request(method, uri, hasContent(method));
2825      return rc;
2826   }
2827
2828   /**
2829    * Perform a generic REST call.
2830    *
2831    * <p>
2832    * Typically you're going to use {@link #request(String, Object)} or {@link #request(String, Object, Object)},
2833    * but this method is provided to allow you to perform non-standard HTTP methods (e.g. HTTP FOO).
2834    *
2835    * @param method The method name (e.g. <js>"GET"</js>, <js>"OPTIONS"</js>).
2836    * @param uri
2837    *    The URI of the remote REST resource.
2838    *    <br>Can be any of the following types:
2839    *    <ul>
2840    *       <li>{@link URIBuilder}
2841    *       <li>{@link URI}
2842    *       <li>{@link URL}
2843    *       <li>{@link String}
2844    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
2845    *    </ul>
2846    * @param hasBody Boolean flag indicating if the specified request has content associated with it.
2847    * @return
2848    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
2849    *    as a parsed object.
2850    * @throws RestCallException If any authentication errors occurred.
2851    */
2852   public RestRequest request(String method, Object uri, boolean hasBody) throws RestCallException {
2853      if (method == null)
2854         method = "GET";
2855      if (isClosed) {
2856         Exception e2 = null;
2857         if (closedStack != null) {
2858            e2 = new Exception("Creation stack:");
2859            e2.setStackTrace(closedStack);
2860            throw new RestCallException(null, e2, "RestClient.close() has already been called.  This client cannot be reused.");
2861         }
2862         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.");
2863      }
2864
2865      RestRequest req = createRequest(toURI(uri, rootUri), method.toUpperCase(Locale.ENGLISH), hasBody);
2866
2867      for (Object o : headers)
2868         req.header(BasicHeader.cast(o));
2869
2870      for (Object o : query)
2871         req.query(BasicNameValuePair.cast(o));
2872
2873      for (Object o : formData)
2874         req.formData(BasicNameValuePair.cast(o));
2875
2876      onInit(req);
2877
2878      return req;
2879   }
2880
2881   /**
2882    * Creates a {@link RestRequest} object from the specified {@link HttpRequest} object.
2883    *
2884    * <p>
2885    * Subclasses can override this method to provide their own specialized {@link RestRequest} objects.
2886    *
2887    * @param uri The target.
2888    * @param method The HTTP method (uppercase).
2889    * @param hasBody Whether this method has a request entity.
2890    * @return A new {@link RestRequest} object.
2891    * @throws RestCallException If an exception or non-200 response code occurred during the connection attempt.
2892    */
2893   protected RestRequest createRequest(URI uri, String method, boolean hasBody) throws RestCallException {
2894      return new RestRequest(this, uri, method, hasBody);
2895   }
2896
2897   /**
2898    * Creates a {@link RestResponse} object from the specified {@link HttpResponse} object.
2899    *
2900    * <p>
2901    * Subclasses can override this method to provide their own specialized {@link RestResponse} objects.
2902    *
2903    * @param request The request creating this response.
2904    * @param httpResponse The response object to wrap.
2905    * @param parser The parser to use to parse the response.
2906    *
2907    * @return A new {@link RestResponse} object.
2908    * @throws RestCallException If an exception or non-200 response code occurred during the connection attempt.
2909    */
2910   protected RestResponse createResponse(RestRequest request, HttpResponse httpResponse, Parser parser) throws RestCallException {
2911      return new RestResponse(this, request, httpResponse, parser);
2912   }
2913
2914   /**
2915    * Create a new proxy interface against a 3rd-party REST interface.
2916    *
2917    * <p>
2918    * The URI to the REST interface is based on the following values:
2919    * <ul>
2920    *    <li>The {@link Remote#path() @Remote(path)} annotation on the interface (<c>remote-path</c>).
2921    *    <li>The {@link RestClientBuilder#rootUri(Object) rootUri} on the client (<c>root-url</c>).
2922    *    <li>The fully-qualified class name of the interface (<c>class-name</c>).
2923    * </ul>
2924    *
2925    * <p>
2926    * The URI calculation is as follows:
2927    * <ul>
2928    *    <li><c>remote-path</c> - If remote path is absolute.
2929    *    <li><c>root-uri/remote-path</c> - If remote path is relative and root-uri has been specified.
2930    *    <li><c>root-uri/class-name</c> - If remote path is not specified.
2931    * </ul>
2932    *
2933    * <p>
2934    * If the information is not available to resolve to an absolute URI, a {@link RemoteMetadataException} is thrown.
2935    *
2936    * <h5 class='section'>Examples:</h5>
2937    * <p class='bcode w800'>
2938    *    <jk>package</jk> <jk>org.apache.foo</jk>;
2939    *
2940    *    <ja>@RemoteResource</ja>(path=<js>"http://hostname/resturi/myinterface1"</js>)
2941    *    <jk>public interface</jk> MyInterface1 { ... }
2942    *
2943    *    <ja>@RemoteResource</ja>(path=<js>"/myinterface2"</js>)
2944    *    <jk>public interface</jk> MyInterface2 { ... }
2945    *
2946    *    <jk>public interface</jk> MyInterface3 { ... }
2947    *
2948    *    <jc>// Resolves to "http://localhost/resturi/myinterface1"</jc>
2949    *    MyInterface1 <jv>i1</jv> = RestClient
2950    *       .<jsm>create</jsm>()
2951    *       .build()
2952    *       .getRemote(MyInterface1.<jk>class</jk>);
2953    *
2954    *    <jc>// Resolves to "http://hostname/resturi/myinterface2"</jc>
2955    *    MyInterface2 <jv>i2</jv> = RestClient
2956    *       .<jsm>create</jsm>()
2957    *       .rootUri(<js>"http://hostname/resturi"</js>)
2958    *       .build()
2959    *       .getRemote(MyInterface2.<jk>class</jk>);
2960    *
2961    *    <jc>// Resolves to "http://hostname/resturi/org.apache.foo.MyInterface3"</jc>
2962    *    MyInterface3 <jv>i3</jv> = RestClient
2963    *       .<jsm>create</jsm>()
2964    *       .rootUri(<js>"http://hostname/resturi"</js>)
2965    *       .build()
2966    *       .getRemote(MyInterface3.<jk>class</jk>);
2967    * </p>
2968    *
2969    * <ul class='notes'>
2970    *    <li>
2971    *       If you plan on using your proxy in a multi-threaded environment, you'll want to use an underlying
2972    *       pooling client connection manager.
2973    * </ul>
2974    *
2975    * <ul class='seealso'>
2976    *    <li class='link'>{@doc RestcProxies}
2977    * </ul>
2978    *
2979    * @param interfaceClass The interface to create a proxy for.
2980    * @return The new proxy interface.
2981    * @throws RemoteMetadataException If the REST URI cannot be determined based on the information given.
2982    */
2983   public <T> T getRemote(Class<T> interfaceClass) {
2984      return getRemote(interfaceClass, null);
2985   }
2986
2987   /**
2988    * Same as {@link #getRemote(Class)} except explicitly specifies the URI of the REST interface.
2989    *
2990    * <ul class='seealso'>
2991    *    <li class='link'>{@doc RestcProxies}
2992    * </ul>
2993    *
2994    * @param interfaceClass The interface to create a proxy for.
2995    * @param rootUri The URI of the REST interface.
2996    * @return The new proxy interface.
2997    */
2998   public <T> T getRemote(Class<T> interfaceClass, Object rootUri) {
2999      return getRemote(interfaceClass, rootUri, null, null);
3000   }
3001
3002   /**
3003    * Same as {@link #getRemote(Class, Object)} but allows you to override the serializer and parser used.
3004    *
3005    * <ul class='seealso'>
3006    *    <li class='link'>{@doc RestcProxies}
3007    * </ul>
3008
3009    * @param interfaceClass The interface to create a proxy for.
3010    * @param rootUri The URI of the REST interface.
3011    * @param serializer The serializer used to serialize POJOs to the body of the HTTP request.
3012    * @param parser The parser used to parse POJOs from the body of the HTTP response.
3013    * @return The new proxy interface.
3014    */
3015   @SuppressWarnings({ "unchecked" })
3016   public <T> T getRemote(final Class<T> interfaceClass, Object rootUri, final Serializer serializer, final Parser parser) {
3017
3018      if (rootUri == null)
3019         rootUri = this.rootUri;
3020
3021      final String restUrl2 = trimSlashes(emptyIfNull(rootUri));
3022
3023      return (T)Proxy.newProxyInstance(
3024         interfaceClass.getClassLoader(),
3025         new Class[] { interfaceClass },
3026         new InvocationHandler() {
3027
3028            final RemoteMeta rm = new RemoteMeta(interfaceClass);
3029
3030            @Override /* InvocationHandler */
3031            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
3032               RemoteMethodMeta rmm = rm.getMethodMeta(method);
3033
3034               String uri = rmm.getFullPath();
3035               if (uri.indexOf("://") == -1)
3036                  uri = restUrl2 + '/' + uri;
3037               if (uri.indexOf("://") == -1)
3038                  throw new RemoteMetadataException(interfaceClass, "Root URI has not been specified.  Cannot construct absolute path to remote resource.");
3039
3040               String httpMethod = rmm.getHttpMethod();
3041               HttpPartSerializerSession s = getPartSerializerSession();
3042
3043               RestRequest rc = request(httpMethod, uri, hasContent(httpMethod));
3044
3045               rc.serializer(serializer);
3046               rc.parser(parser);
3047
3048               for (Header h : rm.getHeaders())
3049                  rc.header(h);
3050
3051               for (RemoteMethodArg a : rmm.getPathArgs())
3052                  rc.pathArg(a.getName(), args[a.getIndex()], a.getSchema(), a.getSerializer(s));
3053
3054               for (RemoteMethodArg a : rmm.getQueryArgs())
3055                  rc.queryArg(a.isSkipIfEmpty() ? SKIP_IF_EMPTY_FLAGS : DEFAULT_FLAGS, a.getName(), args[a.getIndex()], a.getSchema(), a.getSerializer(s));
3056
3057               for (RemoteMethodArg a : rmm.getFormDataArgs())
3058                  rc.formDataArg(a.isSkipIfEmpty() ? SKIP_IF_EMPTY_FLAGS : DEFAULT_FLAGS, a.getName(), args[a.getIndex()], a.getSchema(), a.getSerializer(s));
3059
3060               for (RemoteMethodArg a : rmm.getHeaderArgs())
3061                  rc.headerArg(a.isSkipIfEmpty() ? SKIP_IF_EMPTY_FLAGS : DEFAULT_FLAGS, a.getName(), args[a.getIndex()], a.getSchema(), a.getSerializer(s));
3062
3063               RemoteMethodArg ba = rmm.getBodyArg();
3064               if (ba != null)
3065                  rc.body(args[ba.getIndex()], ba.getSchema());
3066
3067               if (rmm.getRequestArgs().length > 0) {
3068                  for (RemoteMethodBeanArg rmba : rmm.getRequestArgs()) {
3069                     RequestBeanMeta rbm = rmba.getMeta();
3070                     Object bean = args[rmba.getIndex()];
3071                     if (bean != null) {
3072                        for (RequestBeanPropertyMeta p : rbm.getProperties()) {
3073                           Object val = p.getGetter().invoke(bean);
3074                           HttpPartType pt = p.getPartType();
3075                           HttpPartSerializerSession ps = p.getSerializer(s);
3076                           String pn = p.getPartName();
3077                           HttpPartSchema schema = p.getSchema();
3078                           EnumSet<AddFlag> flags = schema.isSkipIfEmpty() ? SKIP_IF_EMPTY_FLAGS : DEFAULT_FLAGS;
3079                           if (pt == PATH)
3080                              rc.pathArg(pn, val, schema, p.getSerializer(s));
3081                           else if (val != null) {
3082                              if (pt == QUERY)
3083                                 rc.queryArg(flags, pn, val, schema, ps);
3084                              else if (pt == FORMDATA)
3085                                 rc.formDataArg(flags, pn, val, schema, ps);
3086                              else if (pt == HEADER)
3087                                 rc.headerArg(flags, pn, val, schema, ps);
3088                              else /* (pt == HttpPartType.BODY) */
3089                                 rc.body(val, schema);
3090                           }
3091                        }
3092                     }
3093                  }
3094               }
3095
3096               RemoteMethodReturn rmr = rmm.getReturns();
3097               if (rmr.isFuture()) {
3098                  return getExecutorService().submit(new Callable<Object>() {
3099                     @Override
3100                     public Object call() throws Exception {
3101                        try {
3102                           return executeRemote(interfaceClass, rc, method, rmm);
3103                        } catch (Exception e) {
3104                           throw e;
3105                        } catch (Throwable e) {
3106                           throw new RuntimeException(e);
3107                        }
3108                     }
3109                  });
3110               } else if (rmr.isCompletableFuture()) {
3111                  CompletableFuture<Object> cf = new CompletableFuture<>();
3112                  getExecutorService().submit(new Callable<Object>() {
3113                     @Override
3114                     public Object call() throws Exception {
3115                        try {
3116                           cf.complete(executeRemote(interfaceClass, rc, method, rmm));
3117                        } catch (Throwable e) {
3118                           cf.completeExceptionally(e);
3119                        }
3120                        return null;
3121                     }
3122                  });
3123                  return cf;
3124               }
3125
3126               return executeRemote(interfaceClass, rc, method, rmm);
3127            }
3128      });
3129   }
3130
3131   Object executeRemote(Class<?> interfaceClass, RestRequest rc, Method method, RemoteMethodMeta rmm) throws Throwable {
3132      RemoteMethodReturn rmr = rmm.getReturns();
3133
3134      try {
3135         Object ret = null;
3136         RestResponse res = null;
3137         if (rmr.getReturnValue() == RemoteReturn.NONE) {
3138            res = rc.complete();
3139         } else if (rmr.getReturnValue() == RemoteReturn.STATUS) {
3140            res = rc.complete();
3141            int returnCode = res.getStatusCode();
3142            Class<?> rt = method.getReturnType();
3143            if (rt == Integer.class || rt == int.class)
3144               ret = returnCode;
3145            else if (rt == Boolean.class || rt == boolean.class)
3146               ret = returnCode < 400;
3147            else
3148               throw new RestCallException(res, null, "Invalid return type on method annotated with @RemoteMethod(returns=RemoteReturn.STATUS).  Only integer and booleans types are valid.");
3149         } else if (rmr.getReturnValue() == RemoteReturn.BEAN) {
3150            rc.ignoreErrors();
3151            res = rc.run();
3152            ret = res.as(rmr.getResponseBeanMeta());
3153         } else {
3154            Class<?> rt = method.getReturnType();
3155            if (Throwable.class.isAssignableFrom(rt))
3156               rc.ignoreErrors();
3157            res = rc.run();
3158            Object v = res.getBody().as(rmr.getReturnType());
3159            if (v == null && rt.isPrimitive())
3160               v = ClassInfo.of(rt).getPrimitiveDefault();
3161            if (rt.getName().equals(res.getStringHeader("Exception-Name")))
3162               res.removeHeaders("Exception-Name");
3163            ret = v;
3164         }
3165
3166         ThrowableUtils.throwException(res.getStringHeader("Exception-Name"), res.getStringHeader("Exception-Message"), rmm.getExceptions());
3167         return ret;
3168      } catch (RestCallException e) {
3169         ThrowableUtils.throwException(e.getServerExceptionName(), e.getServerExceptionMessage(), rmm.getExceptions());
3170         throw new RuntimeException(e);
3171      }
3172   }
3173
3174   /**
3175    * Create a new proxy interface against an RRPC-style service.
3176    *
3177    * <p>
3178    * Remote interfaces are interfaces exposed on the server side using either the <c>RrpcServlet</c>
3179    * or <c>RRPC</c> REST methods.
3180    *
3181    * <p>
3182    * The URI to the REST interface is based on the following values:
3183    * <ul>
3184    *    <li>The {@link Remote#path() @Remote(path)} annotation on the interface (<c>remote-path</c>).
3185    *    <li>The {@link RestClientBuilder#rootUri(Object) rootUri} on the client (<c>root-url</c>).
3186    *    <li>The fully-qualified class name of the interface (<c>class-name</c>).
3187    * </ul>
3188    *
3189    * <p>
3190    * The URI calculation is as follows:
3191    * <ul>
3192    *    <li><c>remote-path</c> - If remote path is absolute.
3193    *    <li><c>root-url/remote-path</c> - If remote path is relative and root-url has been specified.
3194    *    <li><c>root-url/class-name</c> - If remote path is not specified.
3195    * </ul>
3196    *
3197    * <p>
3198    * If the information is not available to resolve to an absolute URI, a {@link RemoteMetadataException} is thrown.
3199    *
3200    * <ul class='notes'>
3201    *    <li>
3202    *       If you plan on using your proxy in a multi-threaded environment, you'll want to use an underlying
3203    *       pooling client connection manager.
3204    * </ul>
3205    *
3206    * <ul class='seealso'>
3207    *    <li class='link'>{@doc RestRpc}
3208    * </ul>
3209    *
3210    * @param interfaceClass The interface to create a proxy for.
3211    * @return The new proxy interface.
3212    * @throws RemoteMetadataException If the REST URI cannot be determined based on the information given.
3213    */
3214   public <T> T getRrpcInterface(final Class<T> interfaceClass) {
3215      return getRrpcInterface(interfaceClass, null);
3216   }
3217
3218   /**
3219    * Same as {@link #getRrpcInterface(Class)} except explicitly specifies the URI of the REST interface.
3220    *
3221    * <ul class='seealso'>
3222    *    <li class='link'>{@doc RestRpc}
3223    * </ul>
3224    *
3225    * @param interfaceClass The interface to create a proxy for.
3226    * @param uri The URI of the REST interface.
3227    * @return The new proxy interface.
3228    */
3229   public <T> T getRrpcInterface(final Class<T> interfaceClass, final Object uri) {
3230      return getRrpcInterface(interfaceClass, uri, null, null);
3231   }
3232
3233   /**
3234    * Same as {@link #getRrpcInterface(Class, Object)} but allows you to override the serializer and parser used.
3235    *
3236    * <ul class='seealso'>
3237    *    <li class='link'>{@doc RestRpc}
3238    * </ul>
3239    *
3240    * @param interfaceClass The interface to create a proxy for.
3241    * @param uri The URI of the REST interface.
3242    * @param serializer The serializer used to serialize POJOs to the body of the HTTP request.
3243    * @param parser The parser used to parse POJOs from the body of the HTTP response.
3244    * @return The new proxy interface.
3245    */
3246   @SuppressWarnings({ "unchecked" })
3247   public <T> T getRrpcInterface(final Class<T> interfaceClass, Object uri, final Serializer serializer, final Parser parser) {
3248
3249      if (uri == null) {
3250         RrpcInterfaceMeta rm = new RrpcInterfaceMeta(interfaceClass, "");
3251         String path = rm.getPath();
3252         if (path.indexOf("://") == -1) {
3253            if (isEmpty(rootUri))
3254               throw new RemoteMetadataException(interfaceClass, "Root URI has not been specified.  Cannot construct absolute path to remote interface.");
3255            path = trimSlashes(rootUri) + '/' + path;
3256         }
3257         uri = path;
3258      }
3259
3260      final String restUrl2 = stringify(uri);
3261
3262      return (T)Proxy.newProxyInstance(
3263         interfaceClass.getClassLoader(),
3264         new Class[] { interfaceClass },
3265         new InvocationHandler() {
3266
3267            final RrpcInterfaceMeta rm = new RrpcInterfaceMeta(interfaceClass, restUrl2);
3268
3269            @Override /* InvocationHandler */
3270            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
3271               RrpcInterfaceMethodMeta rim = rm.getMethodMeta(method);
3272
3273               String uri = rim.getUri();
3274
3275               try {
3276                  RestRequest rc = request("POST", uri, true).serializer(serializer).body(args);
3277
3278                  Object v = rc.run().getBody().as(method.getGenericReturnType());
3279                  if (v == null && method.getReturnType().isPrimitive())
3280                     v = ClassInfo.of(method.getReturnType()).getPrimitiveDefault();
3281                  return v;
3282
3283               } catch (RestCallException e) {
3284                  // Try to throw original exception if possible.
3285                  ThrowableUtils.throwException(e.getServerExceptionName(), e.getServerExceptionMessage(), method.getExceptionTypes());
3286                  throw new RuntimeException(e);
3287               }
3288            }
3289      });
3290   }
3291
3292   @Override
3293   protected void finalize() throws Throwable {
3294      if (leakDetection && ! isClosed && ! keepHttpClientOpen) {
3295         StringBuilder sb = new StringBuilder("WARNING:  RestClient garbage collected before it was finalized.");  // NOT DEBUG
3296         if (creationStack != null) {
3297            sb.append("\nCreation Stack:");  // NOT DEBUG
3298            for (StackTraceElement e : creationStack)
3299               sb.append("\n\t" + e);  // NOT DEBUG
3300         }
3301         log(WARNING, sb.toString());
3302      }
3303   }
3304
3305   /**
3306    * Logs a message.
3307    *
3308    * @param level The log level.
3309    * @param t Thrown exception.  Can be <jk>null</jk>.
3310    * @param msg The message.
3311    * @param args Optional message arguments.
3312    */
3313   protected void log(Level level, Throwable t, String msg, Object...args) {
3314      logger.log(level, t, msg(msg, args));
3315      if (logToConsole) {
3316         console.println(msg(msg, args).get());
3317         if (t != null)
3318            t.printStackTrace(console);
3319      }
3320   }
3321
3322   /**
3323    * Logs a message.
3324    *
3325    * @param level The log level.
3326    * @param msg The message with {@link MessageFormat}-style arguments.
3327    * @param args The arguments.
3328    */
3329   protected void log(Level level, String msg, Object...args) {
3330      logger.log(level, msg(msg, args));
3331      if (logToConsole)
3332         console.println(msg(msg, args).get());
3333   }
3334
3335   private Supplier<String> msg(String msg, Object...args) {
3336      return ()->args.length == 0 ? msg : MessageFormat.format(msg, args);
3337   }
3338
3339
3340   //-----------------------------------------------------------------------------------------------------------------
3341   // RestCallInterceptor methods
3342   //-----------------------------------------------------------------------------------------------------------------
3343
3344   /**
3345    * Interceptor method called immediately after the RestRequest object is created and all headers/query/form-data has been copied from the client.
3346    *
3347    * <p>
3348    * Subclasses can override this method to intercept the request and perform special modifications.
3349    *
3350    * <ul class='seealso'>
3351    *    <li class='jf'>{@link RestClient#RESTCLIENT_interceptors}
3352    *    <li class='jm'>{@link RestClientBuilder#interceptors(Object...)}
3353    * </ul>
3354    *
3355    * @param req The HTTP request.
3356    * @throws RestCallException If any of the interceptors threw an exception.
3357    */
3358   @Override
3359   public void onInit(RestRequest req) throws RestCallException {
3360      try {
3361         for (RestCallInterceptor rci : interceptors)
3362            rci.onInit(req);
3363      } catch (RuntimeException | RestCallException e) {
3364         throw e;
3365      } catch (Exception e) {
3366         throw new RestCallException(null, e, "Interceptor threw an exception on init.");
3367      }
3368   }
3369
3370   /**
3371    * Interceptor method called immediately after an HTTP response has been received.
3372    *
3373    * <p>
3374    * Subclasses can override this method to intercept the response and perform special modifications.
3375    *
3376    * <ul class='seealso'>
3377    *    <li class='jf'>{@link RestClient#RESTCLIENT_interceptors}
3378    *    <li class='jm'>{@link RestClientBuilder#interceptors(Object...)}
3379    * </ul>
3380    *
3381    * @param req The HTTP request.
3382    * @param res The HTTP response.
3383    * @throws RestCallException If any of the interceptors threw an exception.
3384    */
3385   @Override
3386   public void onConnect(RestRequest req, RestResponse res) throws RestCallException {
3387      try {
3388         for (RestCallInterceptor rci : interceptors)
3389            rci.onConnect(req, res);
3390      } catch (RuntimeException | RestCallException e) {
3391         throw e;
3392      } catch (Exception e) {
3393         throw new RestCallException(res, e, "Interceptor threw an exception on connect.");
3394      }
3395   }
3396
3397   /**
3398    * 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.
3399    *
3400    * <p>
3401    * Subclasses can override this method to handle any cleanup operations.
3402    *
3403    * <ul class='seealso'>
3404    *    <li class='jf'>{@link RestClient#RESTCLIENT_interceptors}
3405    *    <li class='jm'>{@link RestClientBuilder#interceptors(Object...)}
3406    * </ul>
3407    *
3408    * @param req The HTTP request.
3409    * @param res The HTTP response.
3410    * @throws RestCallException If any of the interceptors threw an exception.
3411    */
3412   @Override
3413   public void onClose(RestRequest req, RestResponse res) throws RestCallException {
3414      try {
3415         for (RestCallInterceptor rci : interceptors)
3416            rci.onClose(req, res);
3417      } catch (RuntimeException | RestCallException e) {
3418         throw e;
3419      } catch (Exception e) {
3420         throw new RestCallException(res, e, "Interceptor threw an exception on close.");
3421      }
3422   }
3423
3424   //------------------------------------------------------------------------------------------------
3425   // Passthrough methods for HttpClient.
3426   //------------------------------------------------------------------------------------------------
3427
3428   /**
3429    * Obtains the parameters for this client.
3430    *
3431    * These parameters will become defaults for all requests being executed with this client, and for the parameters of dependent objects in this client.
3432    *
3433    * @return The default parameters.
3434    * @deprecated Use {@link RequestConfig}.
3435    */
3436   @Deprecated
3437   @Override /* HttpClient */
3438   public HttpParams getParams() {
3439      return httpClient.getParams();
3440   }
3441
3442   /**
3443    * Obtains the connection manager used by this client.
3444    *
3445    * @return The connection manager.
3446    * @deprecated Use {@link HttpClientBuilder}.
3447    */
3448   @Deprecated
3449   @Override /* HttpClient */
3450   public ClientConnectionManager getConnectionManager() {
3451      return httpClient.getConnectionManager();
3452   }
3453
3454   /**
3455    * Executes HTTP request using the default context.
3456    *
3457    * <ul class='notes'>
3458    *    <li>This method gets passed on directly to the underlying {@link HttpClient} class.
3459    * </ul>
3460    *
3461    * @param request The request to execute.
3462    * @return
3463    *    The response to the request.
3464    *    <br>This is always a final response, never an intermediate response with an 1xx status code.
3465    *    <br>Whether redirects or authentication challenges will be returned or handled automatically depends on the
3466    *       implementation and configuration of this client.
3467    * @throws IOException In case of a problem or the connection was aborted.
3468    * @throws ClientProtocolException In case of an http protocol error.
3469    */
3470   @Override /* HttpClient */
3471   public HttpResponse execute(HttpUriRequest request) throws IOException, ClientProtocolException {
3472      return httpClient.execute(request);
3473   }
3474
3475   /**
3476    * Executes HTTP request using the given context.
3477    *
3478    * <ul class='notes'>
3479    *    <li>This method gets passed on directly to the underlying {@link HttpClient} class.
3480    * </ul>
3481    *
3482    * @param request The request to execute.
3483    * @param context The context to use for the execution, or <jk>null</jk> to use the default context.
3484    * @return
3485    *    The response to the request.
3486    *    <br>This is always a final response, never an intermediate response with an 1xx status code.
3487    *    <br>Whether redirects or authentication challenges will be returned or handled automatically depends on the
3488    *       implementation and configuration of this client.
3489    * @throws IOException In case of a problem or the connection was aborted.
3490    * @throws ClientProtocolException In case of an http protocol error.
3491    */
3492   @Override /* HttpClient */
3493   public HttpResponse execute(HttpUriRequest request, HttpContext context) throws IOException, ClientProtocolException {
3494      return httpClient.execute(request, context);
3495   }
3496
3497   /**
3498    * Executes HTTP request using the default context.
3499    *
3500    * <ul class='notes'>
3501    *    <li>This method gets passed on directly to the underlying {@link HttpClient} class.
3502    * </ul>
3503    *
3504    * @param target The target host for the request.
3505    *    <br>Implementations may accept <jk>null</jk> if they can still determine a route, for example to a default
3506    *       target or by inspecting the request.
3507    * @param request The request to execute.
3508    * @return The response to the request.
3509    *    <br>This is always a final response, never an intermediate response with an 1xx status code.
3510    *    <br>Whether redirects or authentication challenges will be returned or handled automatically depends on the
3511    *       implementation and configuration of this client.
3512    * @throws IOException In case of a problem or the connection was aborted.
3513    * @throws ClientProtocolException In case of an http protocol error.
3514    */
3515   @Override /* HttpClient */
3516   public HttpResponse execute(HttpHost target, HttpRequest request) throws IOException, ClientProtocolException {
3517      return httpClient.execute(target, request);
3518   }
3519
3520   /**
3521    * Executes HTTP request using the given context.
3522    *
3523    * <ul class='notes'>
3524    *    <li>This method gets passed on directly to the underlying {@link HttpClient} class.
3525    *    <li>The {@link #run(HttpHost,HttpRequest,HttpContext)} method has been provided as a wrapper around this method.
3526    *       Subclasses can override these methods for handling requests with and without bodies separately.
3527    *    <li>The {@link RestCallHandler} interface can also be implemented to intercept this method.
3528    * </ul>
3529    *
3530    * @param target The target host for the request.
3531    *    <br>Implementations may accept <jk>null</jk> if they can still determine a route, for example to a default
3532    *       target or by inspecting the request.
3533    * @param request The request to execute.
3534    * @param context The context to use for the execution, or <jk>null</jk> to use the default context.
3535    * @return
3536    *    The response to the request.
3537    *    <br>This is always a final response, never an intermediate response with an 1xx status code.
3538    *    <br>Whether redirects or authentication challenges will be returned or handled automatically depends on the
3539    *       implementation and configuration of this client.
3540    * @throws IOException In case of a problem or the connection was aborted.
3541    * @throws ClientProtocolException In case of an http protocol error.
3542    */
3543   @Override /* HttpClient */
3544   public HttpResponse execute(HttpHost target, HttpRequest request, HttpContext context) throws IOException, ClientProtocolException {
3545      return httpClient.execute(target, request, context);
3546   }
3547
3548   /**
3549    * Executes HTTP request using the default context and processes the response using the given response handler.
3550    *
3551    * <p>
3552    * The content entity associated with the response is fully consumed and the underlying connection is released back
3553    * to the connection manager automatically in all cases relieving individual {@link ResponseHandler ResponseHandlers}
3554    * from having to manage resource deallocation internally.
3555    *
3556    * <ul class='notes'>
3557    *    <li>This method gets passed on directly to the underlying {@link HttpClient} class.
3558    * </ul>
3559    *
3560    * @param request The request to execute.
3561    * @param responseHandler The response handler.
3562    * @return Object returned by response handler.
3563    * @throws IOException In case of a problem or the connection was aborted.
3564    * @throws ClientProtocolException In case of an http protocol error.
3565    */
3566   @Override /* HttpClient */
3567   public <T> T execute(HttpUriRequest request, ResponseHandler<? extends T> responseHandler) throws IOException, ClientProtocolException {
3568      return httpClient.execute(request, responseHandler);
3569   }
3570
3571   /**
3572    * Executes HTTP request using the given context and processes the response using the given response handler.
3573    *
3574    * <p>
3575    * The content entity associated with the response is fully consumed and the underlying connection is released back
3576    * to the connection manager automatically in all cases relieving individual {@link ResponseHandler ResponseHandlers}
3577    * from having to manage resource deallocation internally.
3578    *
3579    * <ul class='notes'>
3580    *    <li>This method gets passed on directly to the underlying {@link HttpClient} class.
3581    * </ul>
3582    *
3583    * @param request The request to execute.
3584    * @param responseHandler The response handler.
3585    * @param context The context to use for the execution, or <jk>null</jk> to use the default context.
3586    * @return The response object as generated by the response handler.
3587    * @throws IOException In case of a problem or the connection was aborted.
3588    * @throws ClientProtocolException In case of an http protocol error.
3589    */
3590   @Override /* HttpClient */
3591   public <T> T execute(HttpUriRequest request, ResponseHandler<? extends T> responseHandler, HttpContext context) throws IOException, ClientProtocolException {
3592      return httpClient.execute(request, responseHandler, context);
3593   }
3594
3595   /**
3596    * Executes HTTP request to the target using the default context and processes the response using the given response handler.
3597    *
3598    * <p>
3599    * The content entity associated with the response is fully consumed and the underlying connection is released back
3600    * to the connection manager automatically in all cases relieving individual {@link ResponseHandler ResponseHandlers}
3601    * from having to manage resource deallocation internally.
3602    *
3603    * <ul class='notes'>
3604    *    <li>This method gets passed on directly to the underlying {@link HttpClient} class.
3605    * </ul>
3606    *
3607    * @param target
3608    *    The target host for the request.
3609    *    <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.
3610    * @param request The request to execute.
3611    * @param responseHandler The response handler.
3612    * @return The response object as generated by the response handler.
3613    * @throws IOException In case of a problem or the connection was aborted.
3614    * @throws ClientProtocolException In case of an http protocol error.
3615    */
3616   @Override /* HttpClient */
3617   public <T> T execute(HttpHost target, HttpRequest request, ResponseHandler<? extends T> responseHandler) throws IOException, ClientProtocolException {
3618      return httpClient.execute(target, request, responseHandler);
3619   }
3620
3621   /**
3622    * Executes a request using the default context and processes the response using the given response handler.
3623    *
3624    * <p>
3625    * The content entity associated with the response is fully consumed and the underlying connection is released back
3626    * to the connection manager automatically in all cases relieving individual {@link ResponseHandler ResponseHandlers}
3627    * from having to manage resource deallocation internally.
3628    *
3629    * <ul class='notes'>
3630    *    <li>This method gets passed on directly to the underlying {@link HttpClient} class.
3631    * </ul>
3632    *
3633    * @param target
3634    *    The target host for the request.
3635    *    <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.
3636    * @param request The request to execute.
3637    * @param responseHandler The response handler.
3638    * @param context The context to use for the execution, or <jk>null</jk> to use the default context.
3639    * @return The response object as generated by the response handler.
3640    * @throws IOException In case of a problem or the connection was aborted.
3641    * @throws ClientProtocolException In case of an http protocol error.
3642    */
3643   @Override /* HttpClient */
3644   public <T> T execute(HttpHost target, HttpRequest request, ResponseHandler<? extends T> responseHandler, HttpContext context) throws IOException, ClientProtocolException {
3645      return httpClient.execute(target, request, responseHandler, context);
3646   }
3647
3648   //-----------------------------------------------------------------------------------------------------------------
3649   // Other methods.
3650   //-----------------------------------------------------------------------------------------------------------------
3651
3652   HttpPartSerializerSession getPartSerializerSession() {
3653      return partSerializer.createPartSession(null);
3654   }
3655
3656   HttpPartParserSession getPartParserSession() {
3657      return partParser.createPartSession(null);
3658   }
3659
3660   private Pattern absUrlPattern = Pattern.compile("^\\w+\\:\\/\\/.*");
3661
3662   URI toURI(Object x, String rootUri) throws RestCallException {
3663      try {
3664         if (x instanceof URI)
3665            return (URI)x;
3666         if (x instanceof URL)
3667            ((URL)x).toURI();
3668         if (x instanceof URIBuilder)
3669            return ((URIBuilder)x).build();
3670         String s = x == null ? "" : x.toString();
3671         if (rootUri != null && ! absUrlPattern.matcher(s).matches()) {
3672            if (s.isEmpty())
3673               s = rootUri;
3674            else {
3675               StringBuilder sb = new StringBuilder(rootUri);
3676               if (! s.startsWith("/"))
3677                  sb.append('/');
3678               sb.append(s);
3679               s = sb.toString();
3680            }
3681         }
3682         s = fixUrl(s);
3683         return new URI(s);
3684      } catch (URISyntaxException e) {
3685         throw new RestCallException(null, e, "Invalid URI encountered:  {0}", x);  // Shouldn't happen.
3686      }
3687   }
3688
3689   ExecutorService getExecutorService() {
3690      if (executorService != null)
3691         return executorService;
3692      synchronized(this) {
3693         executorService = new ThreadPoolExecutor(1, 1, 30, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(10));
3694         return executorService;
3695      }
3696   }
3697
3698   /*
3699    * Returns the serializer that best matches the specified content type.
3700    * If no match found or the content type is null, returns the serializer in the list if it's a list of one.
3701    * Returns null if no serializers are defined.
3702    */
3703   Serializer getMatchingSerializer(String mediaType) {
3704      if (serializers.isEmpty())
3705         return null;
3706      if (mediaType != null) {
3707         Serializer s = serializers.getSerializer(mediaType);
3708         if (s != null)
3709            return s;
3710      }
3711      List<Serializer> l = serializers.getSerializers();
3712      return l.size() == 1 ? l.get(0) : null;
3713   }
3714
3715   /*
3716    * Returns the parser that best matches the specified content type.
3717    * If no match found or the content type is null, returns the parser in the list if it's a list of one.
3718    * Returns null if no parsers are defined.
3719    */
3720   Parser getMatchingParser(String mediaType) {
3721      if (parsers.isEmpty())
3722         return null;
3723      if (mediaType != null) {
3724         Parser p = parsers.getParser(mediaType);
3725         if (p != null)
3726            return p;
3727      }
3728      List<Parser> l = parsers.getParsers();
3729      return l.size() == 1 ? l.get(0) : null;
3730   }
3731
3732   @SuppressWarnings("unchecked")
3733   <T extends Context> T getInstance(Class<T> c) {
3734      Context o = requestContexts.get(c);
3735      if (o == null) {
3736         o = ContextCache.INSTANCE.create(c, getPropertyStore());
3737         requestContexts.put(c, o);
3738      }
3739      return (T)o;
3740   }
3741
3742   @Override /* Context */
3743   public OMap toMap() {
3744      return super.toMap()
3745         .a("RestClient", new DefaultFilteringOMap()
3746            .a("errorCodes", errorCodes)
3747            .a("executorService", executorService)
3748            .a("executorServiceShutdownOnClose", executorServiceShutdownOnClose)
3749            .a("headers", headers)
3750            .a("interceptors", interceptors)
3751            .a("keepHttpClientOpen", keepHttpClientOpen)
3752            .a("partParser", partParser)
3753            .a("partSerializer", partSerializer)
3754            .a("query", query)
3755            .a("rootUri", rootUri)
3756         );
3757   }
3758}