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}