001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.juneau.rest.mock;
018
019import static java.util.Collections.*;
020import static org.apache.juneau.Enablement.*;
021import static org.apache.juneau.commons.utils.CollectionUtils.*;
022import static org.apache.juneau.commons.utils.Utils.*;
023import static org.apache.juneau.rest.util.RestUtils.*;
024
025import java.io.*;
026import java.lang.annotation.*;
027import java.net.*;
028import java.util.*;
029import java.util.concurrent.*;
030import java.util.function.*;
031import java.util.logging.*;
032import java.util.zip.*;
033
034import javax.net.ssl.*;
035
036import org.apache.http.*;
037import org.apache.http.auth.*;
038import org.apache.http.client.*;
039import org.apache.http.client.CookieStore;
040import org.apache.http.client.config.*;
041import org.apache.http.client.entity.*;
042import org.apache.http.client.methods.*;
043import org.apache.http.config.*;
044import org.apache.http.conn.*;
045import org.apache.http.conn.routing.*;
046import org.apache.http.conn.socket.*;
047import org.apache.http.conn.util.*;
048import org.apache.http.cookie.*;
049import org.apache.http.entity.*;
050import org.apache.http.impl.client.*;
051import org.apache.http.message.*;
052import org.apache.http.protocol.*;
053import org.apache.juneau.*;
054import org.apache.juneau.commons.collections.*;
055import org.apache.juneau.commons.function.*;
056import org.apache.juneau.commons.reflect.*;
057import org.apache.juneau.http.header.ContentType;
058import org.apache.juneau.http.remote.*;
059import org.apache.juneau.httppart.*;
060import org.apache.juneau.marshaller.*;
061import org.apache.juneau.parser.*;
062import org.apache.juneau.rest.*;
063import org.apache.juneau.rest.annotation.*;
064import org.apache.juneau.rest.client.*;
065import org.apache.juneau.rest.client.RestRequest;
066import org.apache.juneau.rest.client.RestResponse;
067import org.apache.juneau.rest.logger.*;
068import org.apache.juneau.serializer.*;
069import org.apache.juneau.uon.*;
070import jakarta.servlet.http.*;
071
072/**
073 * Mocked {@link RestClient}.
074 *
075 * <p>
076 *    This class is used for performing serverless unit testing of {@link Rest @Rest}-annotated and {@link Remote @Remote}-annotated classes.
077 *
078 * <p>
079 *    The class itself extends from {@link RestClient} providing it with the rich feature set of that API and combines
080 *    it with the Apache HttpClient {@link HttpClientConnection} interface for processing requests.
081 *  The class converts {@link HttpRequest} objects to instances of {@link MockServletRequest} and {@link MockServletResponse} which are passed directly
082 *  to the call handler on the resource class {@link RestContext#execute(Object,HttpServletRequest,HttpServletResponse)}.
083 *  In effect, you're fully testing your REST API as if it were running in a live servlet container, yet not
084 *  actually having to run in a servlet container.
085 *  All aspects of the client and server side code are tested, yet no servlet container is required.  The actual
086 *  over-the-wire transmission is the only aspect being bypassed.
087 *
088 * <p>
089 * The following shows a simple example of invoking a PUT method on a simple REST interface and asserting the correct status code and response body:
090 *
091 * <h5 class='figure'>Example:</h5>
092 * <p class='bjava'>
093 *    <jk>public class</jk> MockTest {
094 *
095 *       <jc>// A simple bean with one field.</jc>
096 *       <jk>public static class</jk> MyBean {
097 *          <jk>public int</jk> <jf>foo</jf> = 1;
098 *       }
099 *
100 *       <jc>// Our REST resource to test.</jc>
101 *       <jc>// Simply echos the response.</jc>
102 *       <ja>@Rest</ja>(
103 *          serializers=Json5Serializer.<jk>class</jk>,
104 *          parsers=JsonParser.<jk>class</jk>
105 *       )
106 *       <jk>public static class</jk> EchoRest {
107 *
108 *          <ja>@RestPut</ja>(
109 *             path=<js>"/echo"</js>
110 *          )
111 *          <jk>public</jk> MyBean echo(<ja>@Content</ja> MyBean <jv>bean</jv>) {
112 *             <jk>return</jk> <jv>bean</jv>;
113 *          }
114 *       }
115 *
116 *       <jc>// Our JUnit test.</jc>
117 *       <ja>@Test</ja>
118 *       <jk>public void</jk> testEcho() <jk>throws</jk> Exception {
119 *
120 *          MyBean <jv>myBean</jv> = <jk>new</jk> MyBean();
121 *
122 *          <jc>// Do a round-trip on the bean through the REST interface</jc>
123 *          <jv>myBean</jv> = MockRestClient
124 *             .<jsm>create</jsm>(EchoRest.<jk>class</jk>)
125 *             .json5()
126 *             .build()
127 *             .put(<js>"/echo"</js>, <jv>myBean</jv>)
128 *             .run()
129 *             .assertStatus().is(200)
130 *             .assertContent().is(<js>"{foo:1}"</js>)
131 *             .getContent().as(MyBean.<jk>class</jk>);
132 *
133 *          <jsm>assertEquals</jsm>(1, <jv>myBean</jv>.<jf>foo</jf>);
134 *       }
135 *    }
136 * </p>
137 * <p>
138 *    Breaking apart the fluent method call above will help you understand how this works.
139 *
140 * <p class='bjava'>
141 *    <ja>@Test</ja>
142 *    <jk>public void</jk> testEcho() <jk>throws</jk> Exception {
143 *
144 *       <jc>// Instantiate our mock client.</jc>
145 *       MockRestClient <jv>client</jv> = MockRestClient
146 *          .<jsm>create</jsm>(EchoRest.<jk>class</jk>)
147 *          .json5()
148 *          .build();
149 *
150 *       <jc>// Create a request.</jc>
151 *       RestRequest <jv>req</jv> = <jv>client</jv>.put(<js>"/echo"</js>, <jv>bean</jv>);
152 *
153 *       <jc>// Execute it (by calling RestCallHandler.service(...) and then returning the response object).</jc>
154 *       RestResponse <jv>res</jv> = <jv>req</jv>.run();
155 *
156 *       <jc>// Run assertion tests on the results.</jc>
157 *       <jv>res</jv>.assertStatus().is(200);
158 *       <jv>res</jv>.assertContent().is(<js>"'foo'"</js>);
159 *
160 *       <jc>// Convert the content of the response to a bean.</jc>
161 *       <jv>bean</jv> = <jv>res</jv>.getContent().as(MyBean.<jk>class</jk>);
162 *    }
163 * </p>
164 *
165 * <p>
166 *    The <c>create(Object)</c> method can take in either <c>Class</c> objects or pre-instantiated beans.
167 *    The latter is particularly useful for testing Spring beans.
168 *
169 * <p>
170 *    The {@link MockRestRequest} object has convenience methods provided to allow you to set any properties
171 *    directly on the underlying {@link HttpServletRequest} object.  The following example shows how
172 *    this can be used to directly set roles on the request object to perform security testing.
173 *
174 * <h5 class='figure'>Example:</h5>
175 * <p class='bjava'>
176 *    <ja>@Rest</ja>(roleGuard=<js>"ADMIN"</js>)
177 *    <jk>public class</jk> A {
178 *       <ja>@RestGet</ja>
179 *       <jk>public</jk> String get() {
180 *          <jk>return</jk> <js>"OK"</js>;
181 *       }
182 *    }
183 *
184 *    <ja>@Test</ja>
185 *    <jk>public void</jk> mytest() <jk>throws</jk> Exception {
186 *       MockRestClient <jv>client</jv> = MockRestClient.<jsm>build</jsm>(A.<jk>class</jk>);
187 *
188 *       <jc>// Admin user should get 200, but anyone else should get 403-Unauthorized.</jc>
189 *       <jv>client</jv>.get().roles(<js>"ADMIN"</js>).run().assertStatus().is(200);
190 *       <jv>client</jv>.get().roles(<js>"USER"</js>).run().assertStatus().is(403);
191 *    }
192 * </p>
193 *
194 * <p>
195 *    Debug mode is provided that will cause your HTTP requests and responses to be sent to the console:
196 *
197 * <h5 class='figure'>Example:</h5>
198 * <p class='bjava'>
199 *    MockRestClient <jv>client</jv> = MockRestClient
200 *       .<jsm>create</jsm>(MyRest.<jk>class</jk>)
201 *       .debug()
202 *       .json5()
203 *       .build();
204 * </p>
205 *
206 * <p>
207 *    The class can also be used for testing of {@link Remote @Remote}-annotated interfaces against {@link Rest @Rest}-annotated resources.
208 *
209 * <h5 class='figure'>Example:</h5>
210 * <p class='bjava'>
211 *    <jc>// Our remote resource to test.</jc>
212 *    <ja>@Remote</ja>
213 *    <jk>public interface</jk> MyRemoteInterface {
214 *
215 *       <ja>@RemoteGet</ja>(<js>"/echoQuery"</js>)
216 *       <jk>public int</jk> echoQuery(<ja>@Query</ja>(name=<js>"id"</js>) <jk>int</jk> <jv>id</jv>);
217 *    }
218 *
219 *    <jc>// Our mocked-up REST interface to test against.</jc>
220 *    <ja>@Rest</ja>
221 *    <jk>public class</jk> MyRest {
222 *
223 *       <ja>@RestGet</ja>(path=<js>"/echoQuery"</js>)
224 *       <jk>public int</jk> echoQuery(<ja>@Query</ja>(<js>"id"</js>) String <jv>id</jv>) {
225 *          <jk>return</jk> <jv>id</jv>;
226 *       }
227 *    }
228 *
229 *    <ja>@Test</ja>
230 *    <jk>public void</jk> testProxy() {
231 *       MyRemoteInterface <jv>client</jv> = MockRestClient
232 *          .create(MyRest.<jk>class</jk>)
233 *          .json()
234 *          .build()
235 *          .getRemote(MyRemoteInterface.<jk>class</jk>);
236 *
237 *       <jsm>assertEquals</jsm>(123, <jv>client</jv>.echoQuery(123));
238 *    }
239 * </p>
240 *
241 * <h5 class='section'>Notes:</h5><ul>
242 *    <li class='note'>This class is thread safe and reusable.
243 * </ul>
244 *
245 * <h5 class='section'>See Also:</h5><ul>
246 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauRestMockBasics">juneau-rest-mock Basics</a>
247 * </ul>
248 */
249public class MockRestClient extends RestClient implements HttpClientConnection {
250   /**
251    * Builder class.
252    */
253   public static class Builder extends RestClient.Builder {
254
255      Object restBean;
256      String contextPath, servletPath;
257      RestContext restContext;
258      Map<String,String> pathVars;
259
260      /**
261       * No-arg constructor.
262       *
263       * <p>
264       * Provided so that this class can be easily subclassed.
265       */
266      protected Builder() {
267         connectionManager(new MockHttpClientConnectionManager());
268      }
269
270      @Override /* Overridden from Builder */
271      public Builder accept(String value) {
272         super.accept(value);
273         return this;
274      }
275
276      @Override /* Overridden from Builder */
277      public Builder acceptCharset(String value) {
278         super.acceptCharset(value);
279         return this;
280      }
281
282      @Override /* Overridden from Builder */
283      public Builder addBeanTypes() {
284         super.addBeanTypes();
285         return this;
286      }
287
288      @Override /* Overridden from Builder */
289      public Builder addInterceptorFirst(HttpRequestInterceptor itcp) {
290         super.addInterceptorFirst(itcp);
291         return this;
292      }
293
294      @Override /* Overridden from Builder */
295      public Builder addInterceptorFirst(HttpResponseInterceptor itcp) {
296         super.addInterceptorFirst(itcp);
297         return this;
298      }
299
300      @Override /* Overridden from Builder */
301      public Builder addInterceptorLast(HttpRequestInterceptor itcp) {
302         super.addInterceptorLast(itcp);
303         return this;
304      }
305
306      @Override /* Overridden from Builder */
307      public Builder addInterceptorLast(HttpResponseInterceptor itcp) {
308         super.addInterceptorLast(itcp);
309         return this;
310      }
311
312      @Override /* Overridden from Builder */
313      public Builder addRootType() {
314         super.addRootType();
315         return this;
316      }
317
318      @Override /* Overridden from Builder */
319      public Builder annotations(Annotation...values) {
320         super.annotations(values);
321         return this;
322      }
323
324      @Override /* Overridden from Builder */
325      public Builder apply(AnnotationWorkList work) {
326         super.apply(work);
327         return this;
328      }
329
330      @Override /* Overridden from Builder */
331      public Builder applyAnnotations(Class<?>...from) {
332         super.applyAnnotations(from);
333         return this;
334      }
335
336      @Override /* Overridden from Builder */
337      public Builder applyAnnotations(Object...from) {
338         super.applyAnnotations(from);
339         return this;
340      }
341
342      @Override /* Overridden from Builder */
343      public Builder backoffManager(BackoffManager backoffManager) {
344         super.backoffManager(backoffManager);
345         return this;
346      }
347
348      @Override /* Overridden from Builder */
349      public Builder basicAuth(String host, int port, String user, String pw) {
350         super.basicAuth(host, port, user, pw);
351         return this;
352      }
353
354      @Override /* Overridden from Builder */
355      public Builder beanClassVisibility(Visibility value) {
356         super.beanClassVisibility(value);
357         return this;
358      }
359
360      @Override /* Overridden from Builder */
361      public Builder beanConstructorVisibility(Visibility value) {
362         super.beanConstructorVisibility(value);
363         return this;
364      }
365
366      @Override /* Overridden from Builder */
367      public Builder beanContext(BeanContext value) {
368         super.beanContext(value);
369         return this;
370      }
371
372      @Override /* Overridden from Builder */
373      public Builder beanContext(BeanContext.Builder value) {
374         super.beanContext(value);
375         return this;
376      }
377
378      @Override /* Overridden from Builder */
379      public Builder beanDictionary(java.lang.Class<?>...values) {
380         super.beanDictionary(values);
381         return this;
382      }
383
384      @Override /* Overridden from Builder */
385      public Builder beanFieldVisibility(Visibility value) {
386         super.beanFieldVisibility(value);
387         return this;
388      }
389
390      @Override /* Overridden from Builder */
391      public Builder beanInterceptor(Class<?> on, Class<? extends org.apache.juneau.swap.BeanInterceptor<?>> value) {
392         super.beanInterceptor(on, value);
393         return this;
394      }
395
396      @Override /* Overridden from Builder */
397      public Builder beanMapPutReturnsOldValue() {
398         super.beanMapPutReturnsOldValue();
399         return this;
400      }
401
402      @Override /* Overridden from Builder */
403      public Builder beanMethodVisibility(Visibility value) {
404         super.beanMethodVisibility(value);
405         return this;
406      }
407
408      @Override /* Overridden from Builder */
409      public Builder beanProperties(Class<?> beanClass, String properties) {
410         super.beanProperties(beanClass, properties);
411         return this;
412      }
413
414      @Override /* Overridden from Builder */
415      public Builder beanProperties(Map<String,Object> values) {
416         super.beanProperties(values);
417         return this;
418      }
419
420      @Override /* Overridden from Builder */
421      public Builder beanProperties(String beanClassName, String properties) {
422         super.beanProperties(beanClassName, properties);
423         return this;
424      }
425
426      @Override /* Overridden from Builder */
427      public Builder beanPropertiesExcludes(Class<?> beanClass, String properties) {
428         super.beanPropertiesExcludes(beanClass, properties);
429         return this;
430      }
431
432      @Override /* Overridden from Builder */
433      public Builder beanPropertiesExcludes(Map<String,Object> values) {
434         super.beanPropertiesExcludes(values);
435         return this;
436      }
437
438      @Override /* Overridden from Builder */
439      public Builder beanPropertiesExcludes(String beanClassName, String properties) {
440         super.beanPropertiesExcludes(beanClassName, properties);
441         return this;
442      }
443
444      @Override /* Overridden from Builder */
445      public Builder beanPropertiesReadOnly(Class<?> beanClass, String properties) {
446         super.beanPropertiesReadOnly(beanClass, properties);
447         return this;
448      }
449
450      @Override /* Overridden from Builder */
451      public Builder beanPropertiesReadOnly(Map<String,Object> values) {
452         super.beanPropertiesReadOnly(values);
453         return this;
454      }
455
456      @Override /* Overridden from Builder */
457      public Builder beanPropertiesReadOnly(String beanClassName, String properties) {
458         super.beanPropertiesReadOnly(beanClassName, properties);
459         return this;
460      }
461
462      @Override /* Overridden from Builder */
463      public Builder beanPropertiesWriteOnly(Class<?> beanClass, String properties) {
464         super.beanPropertiesWriteOnly(beanClass, properties);
465         return this;
466      }
467
468      @Override /* Overridden from Builder */
469      public Builder beanPropertiesWriteOnly(Map<String,Object> values) {
470         super.beanPropertiesWriteOnly(values);
471         return this;
472      }
473
474      @Override /* Overridden from Builder */
475      public Builder beanPropertiesWriteOnly(String beanClassName, String properties) {
476         super.beanPropertiesWriteOnly(beanClassName, properties);
477         return this;
478      }
479
480      @Override /* Overridden from Builder */
481      public Builder beansRequireDefaultConstructor() {
482         super.beansRequireDefaultConstructor();
483         return this;
484      }
485
486      @Override /* Overridden from Builder */
487      public Builder beansRequireSerializable() {
488         super.beansRequireSerializable();
489         return this;
490      }
491
492      @Override /* Overridden from Builder */
493      public Builder beansRequireSettersForGetters() {
494         super.beansRequireSettersForGetters();
495         return this;
496      }
497
498      @Override /* Overridden from Context.Builder */
499      public MockRestClient build() {
500         return build(MockRestClient.class);
501      }
502
503      @Override /* Overridden from Builder */
504      public Builder cache(Cache<HashKey,? extends org.apache.juneau.Context> value) {
505         super.cache(value);
506         return this;
507      }
508
509      @Override /* Overridden from Builder */
510      public Builder callHandler(Class<? extends org.apache.juneau.rest.client.RestCallHandler> value) {
511         super.callHandler(value);
512         return this;
513      }
514
515      @Override /* Overridden from Builder */
516      public Builder clientVersion(String value) {
517         super.clientVersion(value);
518         return this;
519      }
520
521      @Override /* Overridden from Builder */
522      public Builder connectionBackoffStrategy(ConnectionBackoffStrategy connectionBackoffStrategy) {
523         super.connectionBackoffStrategy(connectionBackoffStrategy);
524         return this;
525      }
526
527      @Override /* Overridden from Builder */
528      public Builder connectionManager(HttpClientConnectionManager value) {
529         super.connectionManager(value);
530         return this;
531      }
532
533      @Override /* Overridden from Builder */
534      public Builder connectionManagerShared(boolean shared) {
535         super.connectionManagerShared(shared);
536         return this;
537      }
538
539      @Override /* Overridden from Builder */
540      public Builder connectionReuseStrategy(ConnectionReuseStrategy reuseStrategy) {
541         super.connectionReuseStrategy(reuseStrategy);
542         return this;
543      }
544
545      @Override /* Overridden from Builder */
546      public Builder connectionTimeToLive(long connTimeToLive, TimeUnit connTimeToLiveTimeUnit) {
547         super.connectionTimeToLive(connTimeToLive, connTimeToLiveTimeUnit);
548         return this;
549      }
550
551      @Override /* Overridden from Builder */
552      public Builder console(PrintStream value) {
553         super.console(value);
554         return this;
555      }
556
557      @Override /* Overridden from Builder */
558      public Builder contentDecoderRegistry(Map<String,InputStreamFactory> contentDecoderMap) {
559         super.contentDecoderRegistry(contentDecoderMap);
560         return this;
561      }
562
563      @Override /* Overridden from Builder */
564      public Builder contentType(String value) {
565         super.contentType(value);
566         return this;
567      }
568
569      /**
570       * Identifies the context path for the REST resource.
571       *
572       * <p>
573       *    This value is used to deconstruct the request URL and set the appropriate URL getters on the {@link HttpServletRequest}
574       *    object correctly.
575       *
576       * <p>
577       *    Should either be a value such as <js>"/foo"</js> or an empty string.
578       *
579       * <p>
580       *    The following fixes are applied to non-conforming strings.
581       * <ul>
582       *    <li><jk>nulls</jk> and <js>"/"</js> are converted to empty strings.
583       *    <li>Trailing slashes are trimmed.
584       *    <li>Leading slash is added if needed.
585       * </ul>
586       *
587       * @param value The context path.
588       * @return This object.
589       */
590      public Builder contextPath(String value) {
591         contextPath = toValidContextPath(value);
592         return this;
593      }
594
595      @Override /* Overridden from Context.Builder */
596      public Builder copy() {
597         throw new NoSuchMethodError("Not implemented.");
598      }
599
600      @Override /* Overridden from Context.Builder */
601      public Builder debug() {
602         header("Debug", "true");
603         super.debug();
604         return this;
605      }
606
607      @Override /* Overridden from Builder */
608      public Builder debugOutputLines(int value) {
609         super.debugOutputLines(value);
610         return this;
611      }
612
613      @Override /* Overridden from Builder */
614      public Builder defaultAuthSchemeRegistry(Lookup<AuthSchemeProvider> authSchemeRegistry) {
615         super.defaultAuthSchemeRegistry(authSchemeRegistry);
616         return this;
617      }
618
619      @Override /* Overridden from Builder */
620      public Builder defaultConnectionConfig(ConnectionConfig config) {
621         super.defaultConnectionConfig(config);
622         return this;
623      }
624
625      @Override /* Overridden from Builder */
626      public Builder defaultCookieSpecRegistry(Lookup<CookieSpecProvider> cookieSpecRegistry) {
627         super.defaultCookieSpecRegistry(cookieSpecRegistry);
628         return this;
629      }
630
631      @Override /* Overridden from Builder */
632      public Builder defaultCookieStore(CookieStore cookieStore) {
633         super.defaultCookieStore(cookieStore);
634         return this;
635      }
636
637      @Override /* Overridden from Builder */
638      public Builder defaultCredentialsProvider(CredentialsProvider credentialsProvider) {
639         super.defaultCredentialsProvider(credentialsProvider);
640         return this;
641      }
642
643      @Override /* Overridden from Builder */
644      public Builder defaultRequestConfig(RequestConfig config) {
645         super.defaultRequestConfig(config);
646         return this;
647      }
648
649      @Override /* Overridden from Builder */
650      public Builder defaultSocketConfig(SocketConfig config) {
651         super.defaultSocketConfig(config);
652         return this;
653      }
654
655      @Override /* Overridden from Builder */
656      public Builder detectLeaks() {
657         super.detectLeaks();
658         return this;
659      }
660
661      @Override /* Overridden from Builder */
662      public Builder detectRecursions() {
663         super.detectRecursions();
664         return this;
665      }
666
667      @Override /* Overridden from Builder */
668      public Builder dictionaryOn(Class<?> on, java.lang.Class<?>...values) {
669         super.dictionaryOn(on, values);
670         return this;
671      }
672
673      @Override /* Overridden from Builder */
674      public Builder disableAuthCaching() {
675         super.disableAuthCaching();
676         return this;
677      }
678
679      @Override /* Overridden from Builder */
680      public Builder disableAutomaticRetries() {
681         super.disableAutomaticRetries();
682         return this;
683      }
684
685      @Override /* Overridden from Builder */
686      public Builder disableBeansRequireSomeProperties() {
687         super.disableBeansRequireSomeProperties();
688         return this;
689      }
690
691      @Override /* Overridden from Builder */
692      public Builder disableConnectionState() {
693         super.disableConnectionState();
694         return this;
695      }
696
697      @Override /* Overridden from Builder */
698      public Builder disableContentCompression() {
699         super.disableContentCompression();
700         return this;
701      }
702
703      @Override /* Overridden from Builder */
704      public Builder disableCookieManagement() {
705         super.disableCookieManagement();
706         return this;
707      }
708
709      @Override /* Overridden from Builder */
710      public Builder disableIgnoreMissingSetters() {
711         super.disableIgnoreMissingSetters();
712         return this;
713      }
714
715      @Override /* Overridden from Builder */
716      public Builder disableIgnoreTransientFields() {
717         super.disableIgnoreTransientFields();
718         return this;
719      }
720
721      @Override /* Overridden from Builder */
722      public Builder disableIgnoreUnknownNullBeanProperties() {
723         super.disableIgnoreUnknownNullBeanProperties();
724         return this;
725      }
726
727      @Override /* Overridden from Builder */
728      public Builder disableInterfaceProxies() {
729         super.disableInterfaceProxies();
730         return this;
731      }
732
733      @Override /* Overridden from Builder */
734      public Builder disableRedirectHandling() {
735         super.disableRedirectHandling();
736         return this;
737      }
738
739      @Override /* Overridden from Builder */
740      public Builder errorCodes(Predicate<Integer> value) {
741         super.errorCodes(value);
742         return this;
743      }
744
745      @Override /* Overridden from Builder */
746      public Builder evictExpiredConnections() {
747         super.evictExpiredConnections();
748         return this;
749      }
750
751      @Override /* Overridden from Builder */
752      public Builder evictIdleConnections(long maxIdleTime, TimeUnit maxIdleTimeUnit) {
753         super.evictIdleConnections(maxIdleTime, maxIdleTimeUnit);
754         return this;
755      }
756
757      @Override /* Overridden from Builder */
758      public <T> Builder example(Class<T> pojoClass, String json) {
759         super.example(pojoClass, json);
760         return this;
761      }
762
763      @Override /* Overridden from Builder */
764      public <T> Builder example(Class<T> pojoClass, T o) {
765         super.example(pojoClass, o);
766         return this;
767      }
768
769      @Override /* Overridden from Builder */
770      public Builder executorService(ExecutorService executorService, boolean shutdownOnClose) {
771         super.executorService(executorService, shutdownOnClose);
772         return this;
773      }
774
775      @Override /* Overridden from Builder */
776      public Builder findFluentSetters() {
777         super.findFluentSetters();
778         return this;
779      }
780
781      @Override /* Overridden from Builder */
782      public Builder findFluentSetters(Class<?> on) {
783         super.findFluentSetters(on);
784         return this;
785      }
786
787      @Override /* Overridden from Builder */
788      public Builder formData(NameValuePair...parts) {
789         super.formData(parts);
790         return this;
791      }
792
793      @Override /* Overridden from Builder */
794      public Builder formData(String name, String value) {
795         super.formData(name, value);
796         return this;
797      }
798
799      @Override /* Overridden from Builder */
800      public Builder formData(String name, Supplier<String> value) {
801         super.formData(name, value);
802         return this;
803      }
804
805      @Override /* Overridden from Builder */
806      public Builder header(String name, String value) {
807         super.header(name, value);
808         return this;
809      }
810
811      @Override /* Overridden from Builder */
812      public Builder header(String name, Supplier<String> value) {
813         super.header(name, value);
814         return this;
815      }
816
817      @Override /* Overridden from Builder */
818      public Builder headers(Header...parts) {
819         super.headers(parts);
820         return this;
821      }
822
823      @Override /* Overridden from Builder */
824      public Builder html() {
825         super.html();
826         return this;
827      }
828
829      @Override /* Overridden from Builder */
830      public Builder htmlDoc() {
831         super.htmlDoc();
832         return this;
833      }
834
835      @Override /* Overridden from Builder */
836      public Builder htmlStrippedDoc() {
837         super.htmlStrippedDoc();
838         return this;
839      }
840
841      @Override /* Overridden from Builder */
842      public Builder httpClient(CloseableHttpClient value) {
843         super.httpClient(value);
844         return this;
845      }
846
847      @Override /* Overridden from Builder */
848      public Builder httpClientBuilder(HttpClientBuilder value) {
849         super.httpClientBuilder(value);
850         return this;
851      }
852
853      @Override /* Overridden from Builder */
854      public Builder httpProcessor(HttpProcessor httpprocessor) {
855         super.httpProcessor(httpprocessor);
856         return this;
857      }
858
859      @Override /* Overridden from Builder */
860      public Builder ignoreErrors() {
861         super.ignoreErrors();
862         return this;
863      }
864
865      @Override /* Overridden from Builder */
866      public Builder ignoreInvocationExceptionsOnGetters() {
867         super.ignoreInvocationExceptionsOnGetters();
868         return this;
869      }
870
871      @Override /* Overridden from Builder */
872      public Builder ignoreInvocationExceptionsOnSetters() {
873         super.ignoreInvocationExceptionsOnSetters();
874         return this;
875      }
876
877      @Override /* Overridden from Builder */
878      public Builder ignoreRecursions() {
879         super.ignoreRecursions();
880         return this;
881      }
882
883      @Override /* Overridden from Builder */
884      public Builder ignoreUnknownBeanProperties() {
885         super.ignoreUnknownBeanProperties();
886         return this;
887      }
888
889      @Override /* Overridden from Builder */
890      public Builder ignoreUnknownEnumValues() {
891         super.ignoreUnknownEnumValues();
892         return this;
893      }
894
895      @Override /* Overridden from Builder */
896      public Builder impl(Context value) {
897         super.impl(value);
898         return this;
899      }
900
901      @Override /* Overridden from Builder */
902      public Builder implClass(Class<?> interfaceClass, Class<?> implClass) {
903         super.implClass(interfaceClass, implClass);
904         return this;
905      }
906
907      @Override /* Overridden from Builder */
908      public Builder implClasses(Map<Class<?>,Class<?>> values) {
909         super.implClasses(values);
910         return this;
911      }
912
913      @Override /* Overridden from Builder */
914      public Builder initialDepth(int value) {
915         super.initialDepth(value);
916         return this;
917      }
918
919      @Override /* Overridden from Builder */
920      public Builder interceptors(java.lang.Class<?>...values) throws Exception {
921         super.interceptors(values);
922         return this;
923      }
924
925      @Override /* Overridden from Builder */
926      public Builder interceptors(Object...value) {
927         super.interceptors(value);
928         return this;
929      }
930
931      @Override /* Overridden from Builder */
932      public Builder interfaceClass(Class<?> on, Class<?> value) {
933         super.interfaceClass(on, value);
934         return this;
935      }
936
937      @Override /* Overridden from Builder */
938      public Builder interfaces(java.lang.Class<?>...value) {
939         super.interfaces(value);
940         return this;
941      }
942
943      @Override /* Overridden from Builder */
944      public Builder json() {
945         super.json();
946         return this;
947      }
948
949      @Override /* Overridden from Builder */
950      public Builder json5() {
951         super.json5();
952         return this;
953      }
954
955      @Override /* Overridden from Builder */
956      public Builder keepAliveStrategy(ConnectionKeepAliveStrategy keepAliveStrategy) {
957         super.keepAliveStrategy(keepAliveStrategy);
958         return this;
959      }
960
961      @Override /* Overridden from Builder */
962      public Builder keepHttpClientOpen() {
963         super.keepHttpClientOpen();
964         return this;
965      }
966
967      @Override /* Overridden from Builder */
968      public Builder keepNullProperties() {
969         super.keepNullProperties();
970         return this;
971      }
972
973      @Override /* Overridden from Builder */
974      public Builder locale(Locale value) {
975         super.locale(value);
976         return this;
977      }
978
979      @Override /* Overridden from Builder */
980      public Builder logger(Logger value) {
981         super.logger(value);
982         return this;
983      }
984
985      @Override /* Overridden from Builder */
986      public Builder logRequests(DetailLevel detail, Level level, BiPredicate<RestRequest,RestResponse> test) {
987         super.logRequests(detail, level, test);
988         return this;
989      }
990
991      @Override /* Overridden from Builder */
992      public Builder logToConsole() {
993         super.logToConsole();
994         return this;
995      }
996
997      @Override /* Overridden from Builder */
998      public Builder marshaller(Marshaller value) {
999         super.marshaller(value);
1000         return this;
1001      }
1002
1003      @Override /* Overridden from Builder */
1004      public Builder marshallers(Marshaller...value) {
1005         super.marshallers(value);
1006         return this;
1007      }
1008
1009      @Override /* Overridden from Builder */
1010      public Builder maxConnPerRoute(int maxConnPerRoute) {
1011         super.maxConnPerRoute(maxConnPerRoute);
1012         return this;
1013      }
1014
1015      @Override /* Overridden from Builder */
1016      public Builder maxConnTotal(int maxConnTotal) {
1017         super.maxConnTotal(maxConnTotal);
1018         return this;
1019      }
1020
1021      @Override /* Overridden from Builder */
1022      public Builder maxDepth(int value) {
1023         super.maxDepth(value);
1024         return this;
1025      }
1026
1027      @Override /* Overridden from Builder */
1028      public Builder maxIndent(int value) {
1029         super.maxIndent(value);
1030         return this;
1031      }
1032
1033      @Override /* Overridden from Builder */
1034      public Builder mediaType(MediaType value) {
1035         super.mediaType(value);
1036         return this;
1037      }
1038
1039      @Override /* Overridden from Builder */
1040      public Builder mediaType(String value) {
1041         super.mediaType(value);
1042         return this;
1043      }
1044
1045      @Override /* Overridden from Builder */
1046      public Builder msgPack() {
1047         super.msgPack();
1048         return this;
1049      }
1050
1051      @Override /* Overridden from Builder */
1052      public Builder notBeanClasses(java.lang.Class<?>...values) {
1053         super.notBeanClasses(values);
1054         return this;
1055      }
1056
1057      @Override /* Overridden from Builder */
1058      public Builder notBeanPackages(String...values) {
1059         super.notBeanPackages(values);
1060         return this;
1061      }
1062
1063      @Override /* Overridden from Builder */
1064      public Builder noTrace() {
1065         super.noTrace();
1066         return this;
1067      }
1068
1069      @Override /* Overridden from Builder */
1070      public Builder oapiCollectionFormat(HttpPartCollectionFormat value) {
1071         super.oapiCollectionFormat(value);
1072         return this;
1073      }
1074
1075      @Override /* Overridden from Builder */
1076      public Builder oapiFormat(HttpPartFormat value) {
1077         super.oapiFormat(value);
1078         return this;
1079      }
1080
1081      @Override /* Overridden from Builder */
1082      public Builder openApi() {
1083         super.openApi();
1084         return this;
1085      }
1086
1087      @Override /* Overridden from Builder */
1088      public Builder paramFormat(ParamFormat value) {
1089         super.paramFormat(value);
1090         return this;
1091      }
1092
1093      @Override /* Overridden from Builder */
1094      public Builder paramFormatPlain() {
1095         super.paramFormatPlain();
1096         return this;
1097      }
1098
1099      @Override /* Overridden from Builder */
1100      public Builder parser(Class<? extends org.apache.juneau.parser.Parser> value) {
1101         super.parser(value);
1102         return this;
1103      }
1104
1105      @Override /* Overridden from Builder */
1106      public Builder parser(Parser value) {
1107         super.parser(value);
1108         return this;
1109      }
1110
1111      @Override /* Overridden from Builder */
1112      @SuppressWarnings("unchecked")
1113      public Builder parsers(java.lang.Class<? extends org.apache.juneau.parser.Parser>...value) {
1114         super.parsers(value);
1115         return this;
1116      }
1117
1118      @Override /* Overridden from Builder */
1119      public Builder parsers(Parser...value) {
1120         super.parsers(value);
1121         return this;
1122      }
1123
1124      @Override /* Overridden from Builder */
1125      public Builder partParser(Class<? extends org.apache.juneau.httppart.HttpPartParser> value) {
1126         super.partParser(value);
1127         return this;
1128      }
1129
1130      @Override /* Overridden from Builder */
1131      public Builder partParser(HttpPartParser value) {
1132         super.partParser(value);
1133         return this;
1134      }
1135
1136      @Override /* Overridden from Builder */
1137      public Builder partSerializer(Class<? extends org.apache.juneau.httppart.HttpPartSerializer> value) {
1138         super.partSerializer(value);
1139         return this;
1140      }
1141
1142      @Override /* Overridden from Builder */
1143      public Builder partSerializer(HttpPartSerializer value) {
1144         super.partSerializer(value);
1145         return this;
1146      }
1147
1148      @Override /* Overridden from Builder */
1149      public Builder pathData(NameValuePair...parts) {
1150         super.pathData(parts);
1151         return this;
1152      }
1153
1154      @Override /* Overridden from Builder */
1155      public Builder pathData(String name, String value) {
1156         super.pathData(name, value);
1157         return this;
1158      }
1159
1160      @Override /* Overridden from Builder */
1161      public Builder pathData(String name, Supplier<String> value) {
1162         super.pathData(name, value);
1163         return this;
1164      }
1165
1166      /**
1167       * Add resolved path variables to this client.
1168       *
1169       * <p>
1170       * Allows you to add resolved parent path variables when performing tests on child resource classes.
1171       *
1172       * <h5 class='section'>Example:</h5>
1173       * <p class='bjava'>
1174       *    <jc>// A parent class with a path variable.</jc>
1175       *    <ja>@Rest</ja>(
1176       *       path=<js>"/parent/{foo}"</js>,
1177       *       children={
1178       *          Child.<jk>class</jk>
1179       *       }
1180       *    )
1181       *    <jk>public class</jk> Parent { ... }
1182       *
1183       *    <jc>// A child class that uses the parent path variable.</jc>
1184       *    <ja>@Rest</ja>
1185       *    <jk>public class</jk> Child {
1186       *
1187       *       <jk>@RestGet</jk>
1188       *       <jk>public</jk> String get(<ja>@Path</ja>(<js>"foo"</js>) String <jv>foo</jv>) {
1189       *          <jk>return</jk> <jv>foo</jv>;
1190       *       }
1191       *    }
1192       * </p>
1193       * <p class='bjava'>
1194       *    <jc>// Test the method that uses the parent path variable.</jc>
1195       *    MockRestClient
1196       *       .<jsm>create</jsm>(Child.<jk>class</jk>)
1197       *       .json5()
1198       *       .pathVars(<js>"foo"</js>,<js>"bar"</js>)
1199       *       .build()
1200       *       .get(<js>"/"</js>)
1201       *       .run()
1202       *       .assertStatus().asCode().is(200)
1203       *       .assertContent().is(<js>"bar"</js>);
1204       * </p>
1205       *
1206       * <review>Needs review</review>
1207       *
1208       * @param value The path variables.
1209       * @return This object.
1210       * @see MockServletRequest#pathVars(Map)
1211       */
1212      public Builder pathVars(Map<String,String> value) {
1213         pathVars = value;
1214         return this;
1215      }
1216
1217      /**
1218       * Add resolved path variables to this client.
1219       *
1220       * <p>
1221       * Identical to {@link #pathVars(Map)} but allows you to specify as a list of key/value pairs.
1222       *
1223       * @param pairs The key/value pairs.  Must be an even number of parameters.
1224       * @return This object.
1225       */
1226      public Builder pathVars(String...pairs) {
1227         return pathVars(mapb(String.class, String.class).addPairs((Object[])pairs).build());
1228      }
1229
1230      @Override /* Overridden from Builder */
1231      public Builder plainText() {
1232         super.plainText();
1233         return this;
1234      }
1235
1236      @Override /* Overridden from Builder */
1237      public Builder pooled() {
1238         super.pooled();
1239         return this;
1240      }
1241
1242      @Override /* Overridden from Builder */
1243      public Builder propertyNamer(Class<?> on, Class<? extends org.apache.juneau.PropertyNamer> value) {
1244         super.propertyNamer(on, value);
1245         return this;
1246      }
1247
1248      @Override /* Overridden from Builder */
1249      public Builder propertyNamer(Class<? extends org.apache.juneau.PropertyNamer> value) {
1250         super.propertyNamer(value);
1251         return this;
1252      }
1253
1254      @Override /* Overridden from Builder */
1255      public Builder proxy(HttpHost proxy) {
1256         super.proxy(proxy);
1257         return this;
1258      }
1259
1260      @Override /* Overridden from Builder */
1261      public Builder proxyAuthenticationStrategy(AuthenticationStrategy proxyAuthStrategy) {
1262         super.proxyAuthenticationStrategy(proxyAuthStrategy);
1263         return this;
1264      }
1265
1266      @Override /* Overridden from Builder */
1267      public Builder publicSuffixMatcher(PublicSuffixMatcher publicSuffixMatcher) {
1268         super.publicSuffixMatcher(publicSuffixMatcher);
1269         return this;
1270      }
1271
1272      @Override /* Overridden from Builder */
1273      public Builder queryData(NameValuePair...parts) {
1274         super.queryData(parts);
1275         return this;
1276      }
1277
1278      @Override /* Overridden from Builder */
1279      public Builder queryData(String name, String value) {
1280         super.queryData(name, value);
1281         return this;
1282      }
1283
1284      @Override /* Overridden from Builder */
1285      public Builder queryData(String name, Supplier<String> value) {
1286         super.queryData(name, value);
1287         return this;
1288      }
1289
1290      @Override /* Overridden from Builder */
1291      public Builder quoteChar(char value) {
1292         super.quoteChar(value);
1293         return this;
1294      }
1295
1296      @Override /* Overridden from Builder */
1297      public Builder redirectStrategy(RedirectStrategy redirectStrategy) {
1298         super.redirectStrategy(redirectStrategy);
1299         return this;
1300      }
1301
1302      @Override /* Overridden from Builder */
1303      public Builder requestExecutor(HttpRequestExecutor requestExec) {
1304         super.requestExecutor(requestExec);
1305         return this;
1306      }
1307
1308      /**
1309       * Specifies the {@link Rest}-annotated bean class or instance to test against.
1310       *
1311       * @param value The {@link Rest}-annotated bean class or instance.
1312       * @return This object.
1313       */
1314      public Builder restBean(Object value) {
1315         restBean = value;
1316         return this;
1317      }
1318
1319      /**
1320       * Specifies the {@link RestContext} created for the REST bean.
1321       *
1322       * @param value The {@link RestContext} created for the REST bean.
1323       * @return This object.
1324       */
1325      public Builder restContext(RestContext value) {
1326         restContext = value;
1327         return this;
1328      }
1329
1330      @Override /* Overridden from Builder */
1331      public Builder retryHandler(HttpRequestRetryHandler retryHandler) {
1332         super.retryHandler(retryHandler);
1333         return this;
1334      }
1335
1336      @Override /* Overridden from Builder */
1337      public Builder rootUrl(Object value) {
1338         super.rootUrl(value);
1339         return this;
1340      }
1341
1342      @Override /* Overridden from Builder */
1343      public Builder routePlanner(HttpRoutePlanner routePlanner) {
1344         super.routePlanner(routePlanner);
1345         return this;
1346      }
1347
1348      @Override /* Overridden from Builder */
1349      public Builder schemePortResolver(SchemePortResolver schemePortResolver) {
1350         super.schemePortResolver(schemePortResolver);
1351         return this;
1352      }
1353
1354      @Override /* Overridden from Builder */
1355      public Builder serializer(Class<? extends org.apache.juneau.serializer.Serializer> value) {
1356         super.serializer(value);
1357         return this;
1358      }
1359
1360      @Override /* Overridden from Builder */
1361      public Builder serializer(Serializer value) {
1362         super.serializer(value);
1363         return this;
1364      }
1365
1366      @Override /* Overridden from Builder */
1367      @SuppressWarnings("unchecked")
1368      public Builder serializers(java.lang.Class<? extends org.apache.juneau.serializer.Serializer>...value) {
1369         super.serializers(value);
1370         return this;
1371      }
1372
1373      @Override /* Overridden from Builder */
1374      public Builder serializers(Serializer...value) {
1375         super.serializers(value);
1376         return this;
1377      }
1378
1379      @Override /* Overridden from Builder */
1380      public Builder serviceUnavailableRetryStrategy(ServiceUnavailableRetryStrategy serviceUnavailStrategy) {
1381         super.serviceUnavailableRetryStrategy(serviceUnavailStrategy);
1382         return this;
1383      }
1384
1385      /**
1386       * Identifies the servlet path for the REST resource.
1387       *
1388       * <p>
1389       *    This value is used to deconstruct the request URL and set the appropriate URL getters on the {@link HttpServletRequest}
1390       *    object correctly.
1391       *
1392       * <p>
1393       *    Should either be a value such as <js>"/foo"</js> or an empty string.
1394       *
1395       * <p>
1396       *    The following fixes are applied to non-conforming strings.
1397       * <ul>
1398       *    <li><jk>nulls</jk> and <js>"/"</js> are converted to empty strings.
1399       *    <li>Trailing slashes are trimmed.
1400       *    <li>Leading slash is added if needed.
1401       * </ul>
1402       *
1403       * @param value The context path.
1404       * @return This object.
1405       */
1406      public Builder servletPath(String value) {
1407         servletPath = toValidContextPath(value);
1408         return this;
1409      }
1410
1411      @Override /* Overridden from Builder */
1412      public Builder skipEmptyFormData() {
1413         super.skipEmptyFormData();
1414         return this;
1415      }
1416
1417      @Override /* Overridden from Builder */
1418      public Builder skipEmptyFormData(boolean value) {
1419         super.skipEmptyFormData(value);
1420         return this;
1421      }
1422
1423      @Override /* Overridden from Builder */
1424      public Builder skipEmptyHeaderData() {
1425         super.skipEmptyHeaderData();
1426         return this;
1427      }
1428
1429      @Override /* Overridden from Builder */
1430      public Builder skipEmptyHeaderData(boolean value) {
1431         super.skipEmptyHeaderData(value);
1432         return this;
1433      }
1434
1435      @Override /* Overridden from Builder */
1436      public Builder skipEmptyQueryData() {
1437         super.skipEmptyQueryData();
1438         return this;
1439      }
1440
1441      @Override /* Overridden from Builder */
1442      public Builder skipEmptyQueryData(boolean value) {
1443         super.skipEmptyQueryData(value);
1444         return this;
1445      }
1446
1447      @Override /* Overridden from Builder */
1448      public Builder sortCollections() {
1449         super.sortCollections();
1450         return this;
1451      }
1452
1453      @Override /* Overridden from Builder */
1454      public Builder sortMaps() {
1455         super.sortMaps();
1456         return this;
1457      }
1458
1459      @Override /* Overridden from Builder */
1460      public Builder sortProperties() {
1461         super.sortProperties();
1462         return this;
1463      }
1464
1465      @Override /* Overridden from Builder */
1466      public Builder sortProperties(java.lang.Class<?>...on) {
1467         super.sortProperties(on);
1468         return this;
1469      }
1470
1471      @Override /* Overridden from Builder */
1472      public Builder sq() {
1473         super.sq();
1474         return this;
1475      }
1476
1477      @Override /* Overridden from Builder */
1478      public Builder sslContext(SSLContext sslContext) {
1479         super.sslContext(sslContext);
1480         return this;
1481      }
1482
1483      @Override /* Overridden from Builder */
1484      public Builder sslHostnameVerifier(HostnameVerifier hostnameVerifier) {
1485         super.sslHostnameVerifier(hostnameVerifier);
1486         return this;
1487      }
1488
1489      @Override /* Overridden from Builder */
1490      public Builder sslSocketFactory(LayeredConnectionSocketFactory sslSocketFactory) {
1491         super.sslSocketFactory(sslSocketFactory);
1492         return this;
1493      }
1494
1495      @Override /* Overridden from Builder */
1496      public Builder stopClass(Class<?> on, Class<?> value) {
1497         super.stopClass(on, value);
1498         return this;
1499      }
1500
1501      @Override /* Overridden from Builder */
1502      public Builder strict() {
1503         super.strict();
1504         return this;
1505      }
1506
1507      /**
1508       * Suppress logging on this client.
1509       *
1510       * @return This object.
1511       */
1512      public Builder suppressLogging() {
1513         return logRequests(DetailLevel.NONE, null, null);
1514      }
1515
1516      @Override /* Overridden from Builder */
1517      public <T,S> Builder swap(Class<T> normalClass, Class<S> swappedClass, ThrowingFunction<T,S> swapFunction) {
1518         super.swap(normalClass, swappedClass, swapFunction);
1519         return this;
1520      }
1521
1522      @Override /* Overridden from Builder */
1523      public <T,S> Builder swap(Class<T> normalClass, Class<S> swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> unswapFunction) {
1524         super.swap(normalClass, swappedClass, swapFunction, unswapFunction);
1525         return this;
1526      }
1527
1528      @Override /* Overridden from Builder */
1529      public Builder swaps(Class<?>...values) {
1530         super.swaps(values);
1531         return this;
1532      }
1533
1534      @Override /* Overridden from Builder */
1535      public Builder swaps(Object...values) {
1536         super.swaps(values);
1537         return this;
1538      }
1539
1540      @Override /* Overridden from Builder */
1541      public Builder targetAuthenticationStrategy(AuthenticationStrategy targetAuthStrategy) {
1542         super.targetAuthenticationStrategy(targetAuthStrategy);
1543         return this;
1544      }
1545
1546      @Override /* Overridden from Builder */
1547      public Builder timeZone(TimeZone value) {
1548         super.timeZone(value);
1549         return this;
1550      }
1551
1552      @Override /* Overridden from Builder */
1553      public Builder trimEmptyCollections() {
1554         super.trimEmptyCollections();
1555         return this;
1556      }
1557
1558      @Override /* Overridden from Builder */
1559      public Builder trimEmptyMaps() {
1560         super.trimEmptyMaps();
1561         return this;
1562      }
1563
1564      @Override /* Overridden from Builder */
1565      public Builder trimStringsOnRead() {
1566         super.trimStringsOnRead();
1567         return this;
1568      }
1569
1570      @Override /* Overridden from Builder */
1571      public Builder trimStringsOnWrite() {
1572         super.trimStringsOnWrite();
1573         return this;
1574      }
1575
1576      @Override /* Overridden from Builder */
1577      public Builder type(Class<? extends org.apache.juneau.Context> value) {
1578         super.type(value);
1579         return this;
1580      }
1581
1582      @Override /* Overridden from Builder */
1583      public Builder typeName(Class<?> on, String value) {
1584         super.typeName(on, value);
1585         return this;
1586      }
1587
1588      @Override /* Overridden from Builder */
1589      public Builder typePropertyName(Class<?> on, String value) {
1590         super.typePropertyName(on, value);
1591         return this;
1592      }
1593
1594      @Override /* Overridden from Builder */
1595      public Builder typePropertyName(String value) {
1596         super.typePropertyName(value);
1597         return this;
1598      }
1599
1600      @Override /* Overridden from Builder */
1601      public Builder uon() {
1602         super.uon();
1603         return this;
1604      }
1605
1606      @Override /* Overridden from Builder */
1607      public Builder uriContext(UriContext value) {
1608         super.uriContext(value);
1609         return this;
1610      }
1611
1612      @Override /* Overridden from Builder */
1613      public Builder uriRelativity(UriRelativity value) {
1614         super.uriRelativity(value);
1615         return this;
1616      }
1617
1618      @Override /* Overridden from Builder */
1619      public Builder uriResolution(UriResolution value) {
1620         super.uriResolution(value);
1621         return this;
1622      }
1623
1624      @Override /* Overridden from Builder */
1625      public Builder urlEnc() {
1626         super.urlEnc();
1627         return this;
1628      }
1629
1630      @Override /* Overridden from Builder */
1631      public Builder useEnumNames() {
1632         super.useEnumNames();
1633         return this;
1634      }
1635
1636      @Override /* Overridden from Builder */
1637      public Builder useJavaBeanIntrospector() {
1638         super.useJavaBeanIntrospector();
1639         return this;
1640      }
1641
1642      @Override /* Overridden from Builder */
1643      public Builder userTokenHandler(UserTokenHandler userTokenHandler) {
1644         super.userTokenHandler(userTokenHandler);
1645         return this;
1646      }
1647
1648      @Override /* Overridden from Builder */
1649      public Builder useSystemProperties() {
1650         super.useSystemProperties();
1651         return this;
1652      }
1653
1654      @Override /* Overridden from Builder */
1655      public Builder useWhitespace() {
1656         super.useWhitespace();
1657         return this;
1658      }
1659
1660      @Override /* Overridden from Builder */
1661      public Builder ws() {
1662         super.ws();
1663         return this;
1664      }
1665
1666      @Override /* Overridden from Builder */
1667      public Builder xml() {
1668         super.xml();
1669         return this;
1670      }
1671   }
1672
1673   private static Map<Class<?>,RestContext> REST_CONTEXTS = new ConcurrentHashMap<>();
1674
1675   /**
1676    * Creates a new {@link RestClient} with no registered serializer or parser.
1677    *
1678    * <p>
1679    * Equivalent to calling:
1680    * <p class='bjava'>
1681    *    MockRestClient.<jsm>create</jsm>(<jv>impl</jv>).build();
1682    * </p>
1683    *
1684    * @param impl
1685    *    The REST bean or bean class annotated with {@link Rest @Rest}.
1686    *    <br>If a class, it must have a no-arg constructor.
1687    * @return A new builder.
1688    */
1689   public static MockRestClient build(Object impl) {
1690      return create(impl).build();
1691   }
1692
1693   /**
1694    * Creates a new {@link RestClient} with JSON marshalling support.
1695    *
1696    * <p>
1697    * Equivalent to calling:
1698    * <p class='bjava'>
1699    *    MockRestClient.<jsm>create</jsm>(<jv>impl</jv>).json().build();
1700    * </p>
1701    *
1702    * @param impl
1703    *    The REST bean or bean class annotated with {@link Rest @Rest}.
1704    *    <br>If a class, it must have a no-arg constructor.
1705    * @return A new builder.
1706    */
1707   public static MockRestClient buildJson(Object impl) {
1708      return create(impl).json().build();
1709   }
1710
1711   /**
1712    * Creates a new {@link RestClient} with Simplified-JSON marshalling support.
1713    *
1714    * <p>
1715    * Equivalent to calling:
1716    * <p class='bjava'>
1717    *    MockRestClient.<jsm>create</jsm>(<jv>impl</jv>).json().build();
1718    * </p>
1719    *
1720    * @param impl
1721    *    The REST bean or bean class annotated with {@link Rest @Rest}.
1722    *    <br>If a class, it must have a no-arg constructor.
1723    * @return A new builder.
1724    */
1725   public static MockRestClient buildJson5(Object impl) {
1726      return create(impl).json5().build();
1727   }
1728
1729   /**
1730    * Creates a new {@link RestClient} with Simplified-JSON marshalling support.
1731    *
1732    * <p>
1733    * Same as {@link #buildJson5(Object)} but HTTP 400+ codes don't trigger {@link RestCallException RestCallExceptions}.
1734    *
1735    * <p>
1736    * Equivalent to calling:
1737    * <p class='bjava'>
1738    *    MockRestClient.<jsm>create</jsm>(<jv>impl</jv>).json().ignoreErrors().build();
1739    * </p>
1740    *
1741    * @param impl
1742    *    The REST bean or bean class annotated with {@link Rest @Rest}.
1743    *    <br>If a class, it must have a no-arg constructor.
1744    * @return A new builder.
1745    */
1746   public static MockRestClient buildJson5Lax(Object impl) {
1747      return create(impl).json5().ignoreErrors().noTrace().build();
1748   }
1749
1750   /**
1751    * Creates a new {@link RestClient} with JSON marshalling support.
1752    *
1753    * <p>
1754    * Same as {@link #buildJson(Object)} but HTTP 400+ codes don't trigger {@link RestCallException RestCallExceptions}.
1755    *
1756    * <p>
1757    * Equivalent to calling:
1758    * <p class='bjava'>
1759    *    MockRestClient.<jsm>create</jsm>(<jv>impl</jv>).json().ignoreErrors().build();
1760    * </p>
1761    *
1762    * @param impl
1763    *    The REST bean or bean class annotated with {@link Rest @Rest}.
1764    *    <br>If a class, it must have a no-arg constructor.
1765    * @return A new builder.
1766    */
1767   public static MockRestClient buildJsonLax(Object impl) {
1768      return create(impl).json().ignoreErrors().noTrace().build();
1769   }
1770
1771   /**
1772    * Creates a new {@link RestClient} with no registered serializer or parser.
1773    *
1774    * <p>
1775    * Same as {@link #build(Object)} but HTTP 400+ codes don't trigger {@link RestCallException RestCallExceptions}.
1776    *
1777    * <p>
1778    * Equivalent to calling:
1779    * <p class='bjava'>
1780    *    MockRestClient.<jsm>create</jsm>(<jv>impl</jv>).ignoreErrors().noTrace().build();
1781    * </p>
1782    *
1783    * @param impl
1784    *    The REST bean or bean class annotated with {@link Rest @Rest}.
1785    *    <br>If a class, it must have a no-arg constructor.
1786    * @return A new builder.
1787    */
1788   public static MockRestClient buildLax(Object impl) {
1789      return create(impl).ignoreErrors().noTrace().build();
1790   }
1791
1792   /**
1793    * Creates a new {@link org.apache.juneau.rest.client.RestClient.Builder} configured with the specified REST implementation bean or bean class.
1794    *
1795    * @param impl
1796    *    The REST bean or bean class annotated with {@link Rest @Rest}.
1797    *    <br>If a class, it must have a no-arg constructor.
1798    * @return A new builder.
1799    */
1800   public static Builder create(Object impl) {
1801      return new Builder().restBean(impl);
1802   }
1803
1804   /**
1805    * Creates a new {@link org.apache.juneau.rest.client.RestClient.Builder} configured with the specified REST implementation bean or bean class.
1806    *
1807    * <p>
1808    * Same as {@link #create(Object)} but HTTP 400+ codes don't trigger {@link RestCallException RestCallExceptions}.
1809    *
1810    * @param impl
1811    *    The REST bean or bean class annotated with {@link Rest @Rest}.
1812    *    <br>If a class, it must have a no-arg constructor.
1813    * @return A new builder.
1814    */
1815   public static Builder createLax(Object impl) {
1816      return new Builder().restBean(impl).ignoreErrors().noTrace();
1817   }
1818
1819   private static Builder preInit(Builder builder) {
1820      try {
1821         var restBean = builder.restBean;
1822         var contextPath = builder.contextPath;
1823         var servletPath = builder.servletPath;
1824         var rootUrl = builder.getRootUri();
1825         if (rootUrl == null)
1826            rootUrl = "http://localhost";
1827
1828         var c = restBean instanceof Class restBean2 ? (Class<?>)restBean2 : restBean.getClass();
1829         if (! REST_CONTEXTS.containsKey(c)) {
1830            var isClass = restBean instanceof Class;
1831            var o = isClass ? ((Class<?>)restBean).getDeclaredConstructor().newInstance() : restBean;
1832            // @formatter:off
1833            RestContext rc = RestContext
1834               .create(o.getClass(), null, null)
1835               .defaultClasses(BasicTestCallLogger.class)
1836               .debugDefault(CONDITIONAL)
1837               .init(()->o)
1838               .build()
1839               .postInit()
1840               .postInitChildFirst();
1841            // @formatter:on
1842            REST_CONTEXTS.put(c, rc);
1843         }
1844         var restBeanCtx = REST_CONTEXTS.get(c);
1845         builder.restContext(restBeanCtx);
1846
1847         if (servletPath == null)
1848            servletPath = toValidContextPath(restBeanCtx.getFullPath());
1849
1850         rootUrl = rootUrl + emptyIfNull(contextPath) + emptyIfNull(servletPath);
1851
1852         builder.servletPath = servletPath;
1853         builder.rootUrl(rootUrl);
1854         return builder;
1855      } catch (Exception e) {
1856         throw new ConfigException(e, "Could not initialize MockRestClient");
1857      }
1858   }
1859
1860   private final RestContext restContext;
1861   private final Object restObject;
1862   private final String contextPath, servletPath;
1863
1864   private final Map<String,String> pathVars;
1865   private final ThreadLocal<HttpRequest> rreq = new ThreadLocal<>();
1866   private final ThreadLocal<MockRestResponse> rres = new ThreadLocal<>();
1867   private final ThreadLocal<MockServletRequest> sreq = new ThreadLocal<>();
1868
1869   private final ThreadLocal<MockServletResponse> sres = new ThreadLocal<>();
1870
1871   /**
1872    * Constructor.
1873    *
1874    * @param builder
1875    *    The builder for this object.
1876    */
1877   public MockRestClient(Builder builder) {
1878      super(preInit(builder));
1879      restContext = builder.restContext;
1880      contextPath = nn(builder.contextPath) ? builder.contextPath : "";
1881      servletPath = nn(builder.servletPath) ? builder.servletPath : "";
1882      pathVars = nn(builder.pathVars) ? builder.pathVars : emptyMap();
1883      restObject = restContext.getResource();
1884
1885      HttpClientConnectionManager ccm = getHttpClientConnectionManager();
1886      if (ccm instanceof MockHttpClientConnectionManager ccm2)
1887         ccm2.init(this);
1888   }
1889
1890   @Override /* Overridden from RestClient */
1891   public MockRestRequest callback(String callString) throws RestCallException {
1892      return (MockRestRequest)super.callback(callString);
1893   }
1894
1895   @Override /* Overridden from HttpClientConnection */
1896   public void close() throws IOException {
1897      // Don't call super.close() because it will close the client.
1898      rreq.remove();
1899      rres.remove();
1900      sreq.remove();
1901      sres.remove();
1902   }
1903
1904   @Override /* Overridden from RestClient */
1905   public MockRestRequest delete(Object url) throws RestCallException {
1906      return (MockRestRequest)super.delete(url);
1907   }
1908
1909   @Override /* Overridden from HttpClientConnection */
1910   public void flush() throws IOException {}
1911
1912   @Override /* Overridden from RestClient */
1913   public MockRestRequest formPost(Object url) throws RestCallException {
1914      return (MockRestRequest)super.formPost(url);
1915   }
1916
1917   @Override /* Overridden from RestClient */
1918   public MockRestRequest formPost(Object url, Object body) throws RestCallException {
1919      return (MockRestRequest)super.formPost(url, body);
1920   }
1921
1922   @Override /* Overridden from RestClient */
1923   public MockRestRequest formPostPairs(Object url, String...parameters) throws RestCallException {
1924      return (MockRestRequest)super.formPostPairs(url, parameters);
1925   }
1926
1927   @Override /* Overridden from RestClient */
1928   public MockRestRequest get() throws RestCallException {
1929      return (MockRestRequest)super.get();
1930   }
1931
1932   @Override /* Overridden from RestClient */
1933   public MockRestRequest get(Object url) throws RestCallException {
1934      return (MockRestRequest)super.get(url);
1935   }
1936
1937   /**
1938    * Returns the current client-side REST request.
1939    *
1940    * <p>
1941    * Note that this uses a {@link ThreadLocal} object for storage and so will not work on requests executed in
1942    * separate threads such as when using {@link Future Futures}.
1943    *
1944    * @return The current client-side REST request, or <jk>null</jk> if not set.
1945    */
1946   public HttpRequest getCurrentClientRequest() { return rreq.get(); }
1947
1948   /**
1949    * Returns the current client-side REST response.
1950    *
1951    * <p>
1952    * Note that this uses a {@link ThreadLocal} object for storage and so will not work on requests executed in
1953    * separate threads such as when using {@link Future Futures}.
1954    *
1955    * @return The current client-side REST response, or <jk>null</jk> if not set.
1956    */
1957   public MockRestResponse getCurrentClientResponse() { return rres.get(); }
1958
1959   /**
1960    * Returns the current server-side REST request.
1961    *
1962    * <p>
1963    * Note that this uses a {@link ThreadLocal} object for storage and so will not work on requests executed in
1964    * separate threads such as when using {@link Future Futures}.
1965    *
1966    * @return The current server-side REST request, or <jk>null</jk> if not set.
1967    */
1968   public MockServletRequest getCurrentServerRequest() { return sreq.get(); }
1969
1970   /**
1971    * Returns the current server-side REST response.
1972    *
1973    * <p>
1974    * Note that this uses a {@link ThreadLocal} object for storage and so will not work on requests executed in
1975    * separate threads such as when using {@link Future Futures}.
1976    *
1977    * @return The current server-side REST response, or <jk>null</jk> if not set.
1978    */
1979   public MockServletResponse getCurrentServerResponse() { return sres.get(); }
1980
1981   @Override /* Overridden from HttpClientConnection */
1982   public HttpConnectionMetrics getMetrics() { return null; }
1983
1984   @Override /* Overridden from HttpClientConnection */
1985   public int getSocketTimeout() { return Integer.MAX_VALUE; }
1986
1987   @Override /* Overridden from RestClient */
1988   public MockRestRequest head(Object url) throws RestCallException {
1989      return (MockRestRequest)super.head(url);
1990   }
1991
1992   @Override /* Overridden from HttpClientConnection */
1993   public boolean isOpen() { return true; }
1994
1995   @Override /* Overridden from HttpClientConnection */
1996   public boolean isResponseAvailable(int timeout) throws IOException {
1997      return true;
1998   }
1999
2000   @Override /* Overridden from HttpClientConnection */
2001   public boolean isStale() { return false; }
2002
2003   @Override /* Overridden from RestClient */
2004   public MockRestRequest options(Object url) throws RestCallException {
2005      return (MockRestRequest)super.options(url);
2006   }
2007
2008   @Override /* Overridden from RestClient */
2009   public MockRestRequest patch(Object url) throws RestCallException {
2010      return (MockRestRequest)super.patch(url);
2011   }
2012
2013   @Override /* Overridden from RestClient */
2014   public MockRestRequest patch(Object url, Object body) throws RestCallException {
2015      return (MockRestRequest)super.patch(url, body);
2016   }
2017
2018   @Override /* Overridden from RestClient */
2019   public MockRestRequest patch(Object url, String body, ContentType contentType) throws RestCallException {
2020      return (MockRestRequest)super.patch(url, body, contentType);
2021   }
2022
2023   @Override /* Overridden from RestClient */
2024   public MockRestRequest post(Object url) throws RestCallException {
2025      return (MockRestRequest)super.post(url);
2026   }
2027
2028   @Override /* Overridden from RestClient */
2029   public MockRestRequest post(Object url, Object body) throws RestCallException {
2030      return (MockRestRequest)super.post(url, body);
2031   }
2032
2033   @Override /* Overridden from RestClient */
2034   public MockRestRequest post(Object url, String body, ContentType contentType) throws RestCallException {
2035      return (MockRestRequest)super.post(url, body, contentType);
2036   }
2037
2038   @Override /* Overridden from RestClient */
2039   public MockRestRequest put(Object url) throws RestCallException {
2040      return (MockRestRequest)super.put(url);
2041   }
2042
2043   @Override /* Overridden from RestClient */
2044   public MockRestRequest put(Object url, Object body) throws RestCallException {
2045      return (MockRestRequest)super.put(url, body);
2046   }
2047
2048   @Override /* Overridden from RestClient */
2049   public MockRestRequest put(Object url, String body, ContentType contentType) throws RestCallException {
2050      return (MockRestRequest)super.put(url, body, contentType);
2051   }
2052
2053   @Override /* Overridden from HttpClientConnection */
2054   public void receiveResponseEntity(HttpResponse response) throws HttpException, IOException {
2055      InputStream is = new ByteArrayInputStream(sres.get().getContent());
2056      var contentEncoding = response.getLastHeader("Content-Encoding");
2057      if (nn(contentEncoding) && contentEncoding.getValue().equalsIgnoreCase("gzip"))
2058         is = new GZIPInputStream(is);
2059      response.setEntity(new InputStreamEntity(is));
2060   }
2061
2062   @Override /* Overridden from HttpClientConnection */
2063   public HttpResponse receiveResponseHeader() throws HttpException, IOException {
2064      try {
2065         var res = MockServletResponse.create();
2066         restContext.execute(restObject, sreq.get(), res);
2067
2068         // If the status isn't set, something's broken.
2069         if (res.getStatus() == 0)
2070            throw new IllegalStateException("Response status was 0.");
2071
2072         // A bug in HttpClient causes an infinite loop if the response is less than 200.
2073         // As a workaround, just add 1000 to the status code (which is better than an infinite loop).
2074         if (res.getStatus() < 200)
2075            res.setStatus(1000 + res.getStatus());
2076
2077         sres.set(res);
2078
2079         var response = new BasicHttpResponse(new BasicStatusLine(HttpVersion.HTTP_1_1, res.getStatus(), res.getMessage()));
2080         res.getHeaders().forEach((k, v) -> {
2081            for (var hv : v)
2082               response.addHeader(k, hv);
2083         });
2084
2085         return response;
2086      } catch (Exception e) {
2087         throw new HttpException(emptyIfNull(e.getMessage()), e);
2088      }
2089   }
2090
2091   @Override /* Overridden from RestClient */
2092   public MockRestRequest request(RestOperation op) throws RestCallException {
2093      return (MockRestRequest)super.request(op);
2094   }
2095
2096   @Override /* Overridden from RestClient */
2097   public MockRestRequest request(String method, Object url) throws RestCallException {
2098      return (MockRestRequest)super.request(method, url);
2099   }
2100
2101   @Override /* Overridden from RestClient */
2102   public MockRestRequest request(String method, Object url, boolean hasBody) throws RestCallException {
2103      return (MockRestRequest)super.request(method, url, hasBody);
2104   }
2105
2106   @Override /* Overridden from RestClient */
2107   public MockRestRequest request(String method, Object url, Object body) throws RestCallException {
2108      return (MockRestRequest)super.request(method, url, body);
2109   }
2110
2111   @Override /* Overridden from HttpClientConnection */
2112   public void sendRequestEntity(HttpEntityEnclosingRequest request) throws HttpException, IOException {
2113      byte[] body = {};
2114      var entity = request.getEntity();
2115      if (nn(entity)) {
2116         var length = entity.getContentLength();
2117         if (length < 0)
2118            length = 1024;
2119         var baos = new ByteArrayOutputStream((int)Math.min(length, 1024));
2120         entity.writeTo(baos);
2121         baos.flush();
2122         body = baos.toByteArray();
2123      }
2124      sreq.get().content(body);
2125   }
2126
2127   @Override /* Overridden from HttpClientConnection */
2128   public void sendRequestHeader(HttpRequest request) throws HttpException, IOException {
2129      try {
2130         var rl = request.getRequestLine();
2131         var path = rl.getUri();
2132         var target = findTarget(request);
2133
2134         var req = findRestRequest(request);
2135         rreq.set(req);
2136         rres.remove();
2137         sreq.remove();
2138         sres.remove();
2139
2140         path = target + path;
2141
2142         var pr = new MockPathResolver(target, contextPath, servletPath, path, null);
2143         if (nn(pr.getError()))
2144            throw new IllegalStateException(pr.getError());
2145
2146         var r = MockServletRequest.create(request.getRequestLine().getMethod(), pr.getURI()).contextPath(pr.getContextPath()).servletPath(pr.getServletPath()).pathVars(pathVars).debug(isDebug());
2147
2148         for (var h : request.getAllHeaders())
2149            r.header(h.getName(), h.getValue());
2150
2151         sreq.set(r);
2152         sreq.get().applyOverrides(req);
2153      } catch (Exception e) {
2154         throw new HttpException(e.getMessage(), e);
2155      }
2156   }
2157
2158   @Override /* Overridden from HttpClientConnection */
2159   public void setSocketTimeout(int timeout) {}
2160
2161   @Override /* Overridden from HttpClientConnection */
2162   public void shutdown() throws IOException {}
2163
2164   /**
2165    * Attempts to unwrap the request to find the underlying RestRequest object.
2166    * Returns the same object if one of the low-level client methods are used (e.g. execute(HttpUriRequest)).
2167    */
2168   private HttpRequest findRestRequest(HttpRequest req) {
2169      if (req instanceof RestRequestCreated req2)
2170         return req2.getRestRequest();
2171      if (req instanceof HttpRequestWrapper req3)
2172         return findRestRequest(req3.getOriginal());
2173      return req;
2174   }
2175
2176   private static String findTarget(HttpRequest req) {
2177      if (req instanceof HttpRequestWrapper req2) {
2178         var httpHost = req2.getTarget();
2179         if (nn(httpHost))
2180            return httpHost.toURI();
2181      }
2182      return "http://localhost";
2183   }
2184
2185   @Override /* Overridden from RestClient */
2186   protected MockRestRequest createRequest(URI uri, String method, boolean hasBody) throws RestCallException {
2187      return new MockRestRequest(this, uri, method, hasBody);
2188   }
2189
2190   @Override /* Overridden from RestClient */
2191   protected MockRestResponse createResponse(RestRequest req, HttpResponse httpResponse, Parser parser) throws RestCallException {
2192      return new MockRestResponse(this, req, httpResponse, parser);
2193   }
2194
2195   MockRestClient currentResponse(MockRestResponse value) {
2196      rres.set(value);
2197      return this;
2198   }
2199}