001// *************************************************************************************************************************** 002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * 003// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * 004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * 005// * with the License. You may obtain a copy of the License at * 006// * * 007// * http://www.apache.org/licenses/LICENSE-2.0 * 008// * * 009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * 010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * 011// * specific language governing permissions and limitations under the License. * 012// *************************************************************************************************************************** 013package org.apache.juneau.rest.mock2; 014 015import static org.apache.juneau.internal.StringUtils.*; 016 017import java.io.*; 018import java.security.*; 019import java.util.*; 020 021import javax.servlet.*; 022import javax.servlet.http.*; 023 024import org.apache.http.*; 025import org.apache.juneau.collections.*; 026import org.apache.juneau.internal.*; 027import org.apache.juneau.rest.util.*; 028import org.apache.juneau.rest.util.RestUtils; 029import org.apache.juneau.urlencoding.*; 030 031/** 032 * A mutable implementation of {@link HttpServletRequest} for mocking purposes. 033 * 034 * <ul class='seealso'> 035 * <li class='link'>{@doc juneau-rest-mock} 036 * </ul> 037 */ 038public class MockServletRequest implements HttpServletRequest { 039 040 private String method = "GET"; 041 private Map<String,String[]> queryDataMap = new LinkedHashMap<>(); 042 private Map<String,String[]> formDataMap; 043 private Map<String,String[]> headerMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); 044 private Map<String,Object> attributeMap = new LinkedHashMap<>(); 045 private String characterEncoding = "UTF-8"; 046 private byte[] body = new byte[0]; 047 private String protocol = "HTTP/1.1"; 048 private String scheme = "http"; 049 private String serverName = "localhost"; 050 private int serverPort = 8080; 051 private String remoteAddr = ""; 052 private String remoteHost = ""; 053 private Locale locale = Locale.ENGLISH; 054 private int remotePort; 055 private String localName; 056 private String localAddr; 057 private int localPort; 058 private Map<String,RequestDispatcher> requestDispatcher = new LinkedHashMap<>(); 059 private ServletContext servletContext; 060 private DispatcherType dispatcherType; 061 private String authType; 062 private Cookie[] cookies; 063 private String pathInfo; 064 private String pathTranslated; 065 private String contextPath = ""; 066 private String queryString; 067 private String remoteUser; 068 private Principal userPrincipal; 069 private String requestedSessionId; 070 private String requestURI; 071 private String servletPath = ""; 072 private HttpSession httpSession = MockHttpSession.create(); 073 private String uri = ""; 074 private Set<String> roles = new LinkedHashSet<>(); 075 076 /** 077 * Creates a new servlet request. 078 * 079 * Initialized with the following: 080 * <ul> 081 * <li><c>"Accept: text/json+simple"</c> 082 * <li><c>"Content-Type: text/json"</c> 083 * </ul> 084 * 085 * @return A new request. 086 */ 087 public static MockServletRequest create() { 088 MockServletRequest r = new MockServletRequest(); 089 return r; 090 } 091 092 /** 093 * Creates a new servlet request with the specified method name and request path. 094 * 095 * Initialized with the following: 096 * <ul> 097 * <li><c>"Accept: text/json+simple"</c> 098 * <li><c>"Content-Type: text/json"</c> 099 * </ul> 100 * 101 * @param method The HTTP method name. 102 * @param uri The request path. 103 * @param pathArgs Optional path arguments. 104 * 105 * @return A new request. 106 */ 107 public static MockServletRequest create(String method, String uri, Object...pathArgs) { 108 return create() 109 .method(method) 110 .uri(StringUtils.format(uri, pathArgs)); 111 } 112 113 /** 114 * Fluent setter. 115 * 116 * @param uri The URI of the request. 117 * @return This object (for method chaining). 118 */ 119 public MockServletRequest uri(String uri) { 120 uri = emptyIfNull(uri); 121 this.uri = uri; 122 123 if (uri.indexOf('?') != -1) { 124 String qs = uri.substring(uri.indexOf('?') + 1); 125 if (qs.indexOf('#') != -1) 126 qs = qs.substring(0, qs.indexOf('#')); 127 queryString = qs; 128 queryDataMap.putAll(RestUtils.parseQuery(qs)); 129 } 130 131 return this; 132 } 133 134 /** 135 * Adds the specified roles on this request. 136 * 137 * @param roles The roles to add to this request (e.g. <js>"ROLE_ADMIN"</js>). 138 * @return This object (for method chaining). 139 */ 140 public MockServletRequest roles(String...roles) { 141 this.roles = ASet.of(roles); 142 return this; 143 } 144 145 /** 146 * Adds the specified parent path variables to this servlet request. 147 * 148 * <p> 149 * See {@link MockRestClientBuilder#pathVars(Map)} for an example. 150 * 151 * @param pathVars The 152 * @return This object (for method chaining). 153 * @see MockRestClientBuilder#pathVars(Map) 154 */ 155 public MockServletRequest pathVars(Map<String,String> pathVars) { 156 if (isNotEmpty(pathVars)) 157 this.attributeMap.put("juneau.pathVars", new TreeMap<>(pathVars)); 158 return this; 159 } 160 161 /** 162 * Add resolved path variables to this client. 163 * 164 * <p> 165 * Identical to {@link #pathVars(Map)} but allows you to specify as a list of key/value pairs. 166 * 167 * @param pairs The key/value pairs. Must be an even number of parameters. 168 * @return This object (for method chaining). 169 */ 170 public MockServletRequest pathVars(String...pairs) { 171 return pathVars(AMap.<String,String>ofPairs((Object[])pairs)); 172 } 173 174 /** 175 * Adds the specified role on this request. 176 * 177 * @param role The role to add to this request (e.g. <js>"ROLE_ADMIN"</js>). 178 * @return This object (for method chaining). 179 */ 180 public MockServletRequest role(String role) { 181 this.roles = ASet.of(role); 182 return this; 183 } 184 185 /** 186 * Fluent setter. 187 * 188 * @param value The method name for this request. 189 * @return This object (for method chaining). 190 */ 191 public MockServletRequest method(String value) { 192 this.method = value; 193 return this; 194 } 195 196 /** 197 * Fluent setter. 198 * 199 * @param value The character encoding. 200 * @return This object (for method chaining). 201 */ 202 public MockServletRequest characterEncoding(String value) { 203 this.characterEncoding = value; 204 return this; 205 } 206 207 /** 208 * Fluent setter. 209 * 210 * @param value The protocol. 211 * @return This object (for method chaining). 212 */ 213 public MockServletRequest protocol(String value) { 214 this.protocol = value; 215 return this; 216 } 217 218 /** 219 * Fluent setter. 220 * 221 * @param value The scheme. 222 * @return This object (for method chaining). 223 */ 224 public MockServletRequest scheme(String value) { 225 this.scheme = value; 226 return this; 227 } 228 229 /** 230 * Fluent setter. 231 * 232 * @param value The server name. 233 * @return This object (for method chaining). 234 */ 235 public MockServletRequest serverName(String value) { 236 this.serverName = value; 237 return this; 238 } 239 240 /** 241 * Fluent setter. 242 * 243 * @param value The server port. 244 * @return This object (for method chaining). 245 */ 246 public MockServletRequest serverPort(int value) { 247 this.serverPort = value; 248 return this; 249 } 250 251 /** 252 * Fluent setter. 253 * 254 * @param value The remote address. 255 * @return This object (for method chaining). 256 */ 257 public MockServletRequest remoteAddr(String value) { 258 this.remoteAddr = value; 259 return this; 260 } 261 262 /** 263 * Fluent setter. 264 * 265 * @param value The remote port. 266 * @return This object (for method chaining). 267 */ 268 public MockServletRequest remoteHost(String value) { 269 this.remoteHost = value; 270 return this; 271 } 272 273 /** 274 * Fluent setter. 275 * 276 * @param value The locale. 277 * @return This object (for method chaining). 278 */ 279 public MockServletRequest locale(Locale value) { 280 this.locale = value; 281 return this; 282 } 283 284 /** 285 * Fluent setter. 286 * 287 * @param value The remote port. 288 * @return This object (for method chaining). 289 */ 290 public MockServletRequest remotePort(int value) { 291 this.remotePort = value; 292 return this; 293 } 294 295 /** 296 * Fluent setter. 297 * 298 * @param value The local name. 299 * @return This object (for method chaining). 300 */ 301 public MockServletRequest localName(String value) { 302 this.localName = value; 303 return this; 304 } 305 306 /** 307 * Fluent setter. 308 * 309 * @param value The local address. 310 * @return This object (for method chaining). 311 */ 312 public MockServletRequest localAddr(String value) { 313 this.localAddr = value; 314 return this; 315 } 316 317 /** 318 * Fluent setter. 319 * 320 * @param value The local port. 321 * @return This object (for method chaining). 322 */ 323 public MockServletRequest localPort(int value) { 324 this.localPort = value; 325 return this; 326 } 327 328 /** 329 * Fluent setter. 330 * 331 * @param name The path to resolve. 332 * @param value The request dispatcher. 333 * @return This object (for method chaining). 334 */ 335 public MockServletRequest requestDispatcher(String name, RequestDispatcher value) { 336 this.requestDispatcher.put(name, value); 337 return this; 338 } 339 340 /** 341 * Fluent setter. 342 * 343 * @param value The servlet context. 344 * @return This object (for method chaining). 345 */ 346 public MockServletRequest servletContext(ServletContext value) { 347 this.servletContext = value; 348 return this; 349 } 350 351 /** 352 * Fluent setter. 353 * 354 * @param value The dispatcher type. 355 * @return This object (for method chaining). 356 */ 357 public MockServletRequest dispatcherType(DispatcherType value) { 358 this.dispatcherType = value; 359 return this; 360 } 361 362 /** 363 * Fluent setter. 364 * 365 * @param value The auth type. 366 * @return This object (for method chaining). 367 */ 368 public MockServletRequest authType(String value) { 369 this.authType = value; 370 return this; 371 } 372 373 /** 374 * Fluent setter. 375 * 376 * @param value The cookies. 377 * @return This object (for method chaining). 378 */ 379 public MockServletRequest cookies(Cookie[] value) { 380 this.cookies = value; 381 return this; 382 } 383 384 /** 385 * Fluent setter. 386 * 387 * @param value The path info. 388 * @return This object (for method chaining). 389 */ 390 public MockServletRequest pathInfo(String value) { 391 this.pathInfo = value; 392 return this; 393 } 394 395 /** 396 * Fluent setter. 397 * 398 * @param value The path translated. 399 * @return This object (for method chaining). 400 */ 401 public MockServletRequest pathTranslated(String value) { 402 this.pathTranslated = value; 403 return this; 404 } 405 406 /** 407 * Fluent setter. 408 * 409 * @param value The context path. 410 * @return This object (for method chaining). 411 */ 412 public MockServletRequest contextPath(String value) { 413 this.contextPath = value; 414 return this; 415 } 416 417 /** 418 * Fluent setter. 419 * 420 * @param value The query string. 421 * @return This object (for method chaining). 422 */ 423 public MockServletRequest queryString(String value) { 424 this.queryString = value; 425 return this; 426 } 427 428 /** 429 * Fluent setter. 430 * 431 * @param value The remote user. 432 * @return This object (for method chaining). 433 */ 434 public MockServletRequest remoteUser(String value) { 435 this.remoteUser = value; 436 return this; 437 } 438 439 /** 440 * Fluent setter. 441 * 442 * @param value The user principal. 443 * @return This object (for method chaining). 444 */ 445 public MockServletRequest userPrincipal(Principal value) { 446 this.userPrincipal = value; 447 return this; 448 } 449 450 /** 451 * Fluent setter. 452 * 453 * @param value The requested session ID. 454 * @return This object (for method chaining). 455 */ 456 public MockServletRequest requestedSessionId(String value) { 457 this.requestedSessionId = value; 458 return this; 459 } 460 461 /** 462 * Fluent setter. 463 * 464 * @param value The request URI. 465 * @return This object (for method chaining). 466 */ 467 public MockServletRequest requestURI(String value) { 468 this.requestURI = value; 469 return this; 470 } 471 472 /** 473 * Fluent setter. 474 * 475 * @param value The servlet path. 476 * @return This object (for method chaining). 477 */ 478 public MockServletRequest servletPath(String value) { 479 this.servletPath = value; 480 return this; 481 } 482 483 /** 484 * Fluent setter. 485 * 486 * @param value The HTTP session. 487 * @return This object (for method chaining). 488 */ 489 public MockServletRequest httpSession(HttpSession value) { 490 this.httpSession = value; 491 return this; 492 } 493 494 @Override /* HttpServletRequest */ 495 public Object getAttribute(String name) { 496 return attributeMap.get(name); 497 } 498 499 @Override /* HttpServletRequest */ 500 public Enumeration<String> getAttributeNames() { 501 return Collections.enumeration(attributeMap.keySet()); 502 } 503 504 @Override /* HttpServletRequest */ 505 public String getCharacterEncoding() { 506 return characterEncoding; 507 } 508 509 @Override /* HttpServletRequest */ 510 public void setCharacterEncoding(String characterEncoding) throws UnsupportedEncodingException { 511 this.characterEncoding = characterEncoding; 512 } 513 514 @Override /* HttpServletRequest */ 515 public int getContentLength() { 516 return body == null ? 0 : body.length; 517 } 518 519 @Override /* HttpServletRequest */ 520 public long getContentLengthLong() { 521 return body == null ? 0 : body.length; 522 } 523 524 @Override /* HttpServletRequest */ 525 public String getContentType() { 526 return getHeader("Content-Type"); 527 } 528 529 @Override /* HttpServletRequest */ 530 public ServletInputStream getInputStream() throws IOException { 531 if (formDataMap != null) 532 body = UrlEncodingSerializer.DEFAULT.toString(formDataMap).getBytes(); 533 return new BoundedServletInputStream(new ByteArrayInputStream(body), Integer.MAX_VALUE); 534 } 535 536 @Override /* HttpServletRequest */ 537 public String getParameter(String name) { 538 String[] s = getParameterMap().get(name); 539 return s == null || s.length == 0 ? null : s[0]; 540 } 541 542 @Override /* HttpServletRequest */ 543 public Enumeration<String> getParameterNames() { 544 return Collections.enumeration(new ArrayList<>(getParameterMap().keySet())); 545 } 546 547 @Override /* HttpServletRequest */ 548 public String[] getParameterValues(String name) { 549 return getParameterMap().get(name); 550 } 551 552 @Override /* HttpServletRequest */ 553 public Map<String,String[]> getParameterMap() { 554 if ("POST".equalsIgnoreCase(method)) { 555 if (formDataMap == null) { 556 try { 557 formDataMap = RestUtils.parseQuery(IOUtils.read(body)); 558 } catch (IOException e) { 559 e.printStackTrace(); 560 } 561 } 562 return formDataMap; 563 } 564 return queryDataMap; 565 } 566 567 @Override /* HttpServletRequest */ 568 public String getProtocol() { 569 return protocol; 570 } 571 572 @Override /* HttpServletRequest */ 573 public String getScheme() { 574 return scheme; 575 } 576 577 @Override /* HttpServletRequest */ 578 public String getServerName() { 579 return serverName; 580 } 581 582 @Override /* HttpServletRequest */ 583 public int getServerPort() { 584 return serverPort; 585 } 586 587 @Override /* HttpServletRequest */ 588 public BufferedReader getReader() throws IOException { 589 return new BufferedReader(new InputStreamReader(getInputStream(), characterEncoding)); 590 } 591 592 @Override /* HttpServletRequest */ 593 public String getRemoteAddr() { 594 return remoteAddr; 595 } 596 597 @Override /* HttpServletRequest */ 598 public String getRemoteHost() { 599 return remoteHost; 600 } 601 602 @Override /* HttpServletRequest */ 603 public void setAttribute(String name, Object o) { 604 this.attributeMap.put(name, o); 605 } 606 607 @Override /* HttpServletRequest */ 608 public void removeAttribute(String name) { 609 this.attributeMap.remove(name); 610 } 611 612 @Override /* HttpServletRequest */ 613 public Locale getLocale() { 614 return locale; 615 } 616 617 @Override /* HttpServletRequest */ 618 public Enumeration<Locale> getLocales() { 619 return Collections.enumeration(Arrays.asList(locale)); 620 } 621 622 @Override /* HttpServletRequest */ 623 public boolean isSecure() { 624 return false; 625 } 626 627 @Override /* HttpServletRequest */ 628 public RequestDispatcher getRequestDispatcher(String path) { 629 return requestDispatcher.get(path); 630 } 631 632 @Override /* HttpServletRequest */ 633 public String getRealPath(String path) { 634 return path; 635 } 636 637 @Override /* HttpServletRequest */ 638 public int getRemotePort() { 639 return remotePort; 640 } 641 642 @Override /* HttpServletRequest */ 643 public String getLocalName() { 644 return localName; 645 } 646 647 @Override /* HttpServletRequest */ 648 public String getLocalAddr() { 649 return localAddr; 650 } 651 652 @Override /* HttpServletRequest */ 653 public int getLocalPort() { 654 return localPort; 655 } 656 657 @Override /* HttpServletRequest */ 658 public ServletContext getServletContext() { 659 return servletContext; 660 } 661 662 @Override /* HttpServletRequest */ 663 public AsyncContext startAsync() throws IllegalStateException { 664 return null; 665 } 666 667 @Override /* HttpServletRequest */ 668 public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) throws IllegalStateException { 669 return null; 670 } 671 672 @Override /* HttpServletRequest */ 673 public boolean isAsyncStarted() { 674 return false; 675 } 676 677 @Override /* HttpServletRequest */ 678 public boolean isAsyncSupported() { 679 return false; 680 } 681 682 @Override /* HttpServletRequest */ 683 public AsyncContext getAsyncContext() { 684 return null; 685 } 686 687 @Override /* HttpServletRequest */ 688 public DispatcherType getDispatcherType() { 689 return dispatcherType; 690 } 691 692 @Override /* HttpServletRequest */ 693 public String getAuthType() { 694 return authType; 695 } 696 697 @Override /* HttpServletRequest */ 698 public Cookie[] getCookies() { 699 return cookies; 700 } 701 702 @Override /* HttpServletRequest */ 703 public long getDateHeader(String name) { 704 String s = getHeader(name); 705 return s == null ? 0 : org.apache.juneau.http.header.Date.of(s).asZonedDateTime().toInstant().toEpochMilli(); 706 } 707 708 @Override /* HttpServletRequest */ 709 public String getHeader(String name) { 710 String[] s = headerMap.get(name); 711 return s == null || s.length == 0 ? null : s[0]; 712 } 713 714 @Override /* HttpServletRequest */ 715 public Enumeration<String> getHeaders(String name) { 716 String[] s = headerMap.get(name); 717 return Collections.enumeration(Arrays.asList(s == null ? new String[0] : s)); 718 } 719 720 @Override /* HttpServletRequest */ 721 public Enumeration<String> getHeaderNames() { 722 return Collections.enumeration(headerMap.keySet()); 723 } 724 725 @Override /* HttpServletRequest */ 726 public int getIntHeader(String name) { 727 String s = getHeader(name); 728 return s == null || s.isEmpty() ? 0 : Integer.parseInt(s); 729 } 730 731 @Override /* HttpServletRequest */ 732 public String getMethod() { 733 return method; 734 } 735 736 @Override /* HttpServletRequest */ 737 public String getPathInfo() { 738 if (pathInfo == null) { 739 pathInfo = getRequestURI(); 740 if (isNotEmpty(contextPath)) 741 pathInfo = pathInfo.substring(contextPath.length()); 742 if (isNotEmpty(servletPath)) 743 pathInfo = pathInfo.substring(servletPath.length()); 744 } 745 return nullIfEmpty(urlDecode(pathInfo)); 746 } 747 748 @Override /* HttpServletRequest */ 749 public String getPathTranslated() { 750 if (pathTranslated == null) 751 pathTranslated = "/mock-path" + getPathInfo(); 752 return pathTranslated; 753 } 754 755 @Override /* HttpServletRequest */ 756 public String getContextPath() { 757 return contextPath; 758 } 759 760 @Override /* HttpServletRequest */ 761 public String getQueryString() { 762 if (queryString == null) { 763 if (queryDataMap.isEmpty()) 764 queryString = ""; 765 else { 766 StringBuilder sb = new StringBuilder(); 767 for (Map.Entry<String,String[]> e : queryDataMap.entrySet()) 768 if (e.getValue() == null) 769 sb.append(sb.length() == 0 ? "" : "&").append(urlEncode(e.getKey())); 770 else for (String v : e.getValue()) 771 sb.append(sb.length() == 0 ? "" : "&").append(urlEncode(e.getKey())).append('=').append(urlEncode(v)); 772 queryString = sb.toString(); 773 } 774 } 775 return isEmpty(queryString) ? null : queryString; 776 } 777 778 @Override /* HttpServletRequest */ 779 public String getRemoteUser() { 780 return remoteUser; 781 } 782 783 @Override /* HttpServletRequest */ 784 public boolean isUserInRole(String role) { 785 return roles.contains(role); 786 } 787 788 @Override /* HttpServletRequest */ 789 public Principal getUserPrincipal() { 790 return userPrincipal; 791 } 792 793 @Override /* HttpServletRequest */ 794 public String getRequestedSessionId() { 795 return requestedSessionId; 796 } 797 798 @Override /* HttpServletRequest */ 799 public String getRequestURI() { 800 if (requestURI == null) { 801 requestURI = uri; 802 requestURI = requestURI.replaceAll("^\\w+\\:\\/\\/[^\\/]+", "").replaceAll("\\?.*$", ""); 803 } 804 return requestURI; 805 } 806 807 @Override /* HttpServletRequest */ 808 public StringBuffer getRequestURL() { 809 return new StringBuffer(uri.replaceAll("\\?.*$", "")); 810 } 811 812 @Override /* HttpServletRequest */ 813 public String getServletPath() { 814 return servletPath; 815 } 816 817 @Override /* HttpServletRequest */ 818 public HttpSession getSession(boolean create) { 819 return httpSession; 820 } 821 822 @Override /* HttpServletRequest */ 823 public HttpSession getSession() { 824 return httpSession; 825 } 826 827 @Override /* HttpServletRequest */ 828 public String changeSessionId() { 829 return null; 830 } 831 832 @Override /* HttpServletRequest */ 833 public boolean isRequestedSessionIdValid() { 834 return false; 835 } 836 837 @Override /* HttpServletRequest */ 838 public boolean isRequestedSessionIdFromCookie() { 839 return false; 840 } 841 842 @Override /* HttpServletRequest */ 843 public boolean isRequestedSessionIdFromURL() { 844 return false; 845 } 846 847 @Override /* HttpServletRequest */ 848 public boolean isRequestedSessionIdFromUrl() { 849 return false; 850 } 851 852 @Override /* HttpServletRequest */ 853 public boolean authenticate(HttpServletResponse response) throws IOException, ServletException { 854 return false; 855 } 856 857 @Override /* HttpServletRequest */ 858 public void login(String username, String password) throws ServletException { 859 } 860 861 @Override /* HttpServletRequest */ 862 public void logout() throws ServletException { 863 } 864 865 @Override /* HttpServletRequest */ 866 public Collection<Part> getParts() throws IOException, ServletException { 867 return null; 868 } 869 870 @Override /* HttpServletRequest */ 871 public Part getPart(String name) throws IOException, ServletException { 872 return null; 873 } 874 875 @Override /* HttpServletRequest */ 876 public <T extends HttpUpgradeHandler> T upgrade(Class<T> handlerClass) throws IOException, ServletException { 877 return null; 878 } 879 880 //================================================================================================================= 881 // Convenience methods 882 //================================================================================================================= 883 884 /** 885 * Fluent setter. 886 * 887 * @param name Header name. 888 * @param value 889 * Header value. 890 * <br>The value is converted to a simple string using {@link Object#toString()}. 891 * @return This object (for method chaining). 892 */ 893 public MockServletRequest header(String name, Object value) { 894 if (value != null) { 895 String[] v1 = (value instanceof String[]) ? (String[])value : new String[]{value.toString()}; 896 String[] v2 = headerMap.get(name); 897 String[] v3 = ArrayUtils.combine(v2, v1); 898 headerMap.put(name, v3); 899 } 900 return this; 901 } 902 903 /** 904 * Fluent setter. 905 * 906 * @param name Request attribute name. 907 * @param value Request attribute value. 908 * @return This object (for method chaining). 909 */ 910 public MockServletRequest attribute(String name, Object value) { 911 this.attributeMap.put(name, value); 912 return this; 913 } 914 915 /** 916 * Fluent setter. 917 * 918 * @param value 919 * The body of the request. 920 * <br>Can be any of the following data types: 921 * <ul> 922 * <li><code><jk>byte</jk>[]</code> 923 * <li>{@link Reader} 924 * <li>{@link InputStream} 925 * <li>{@link CharSequence} 926 * </ul> 927 * Any other types are converted to a string using the <c>toString()</c> method. 928 * @return This object (for method chaining). 929 */ 930 public MockServletRequest body(Object value) { 931 try { 932 if (value instanceof byte[]) 933 this.body = (byte[])value; 934 else if (value instanceof Reader) 935 this.body = IOUtils.read((Reader)value).getBytes(); 936 else if (value instanceof InputStream) 937 this.body = IOUtils.readBytes((InputStream)value, 1024); 938 else if (value instanceof CharSequence) 939 this.body = ((CharSequence)value).toString().getBytes(); 940 else if (value != null) 941 this.body = value.toString().getBytes(); 942 } catch (IOException e) { 943 throw new RuntimeException(e); 944 } 945 return this; 946 } 947 948 //================================================================================================================= 949 // Convenience methods - headers 950 //================================================================================================================= 951 952 /** 953 * Enabled debug mode on this request. 954 * 955 * <p> 956 * Causes information about the request execution to be sent to STDERR. 957 * 958 * @param value The enable flag value. 959 * @return This object (for method chaining). 960 */ 961 protected MockServletRequest debug(boolean value) { 962 if (value) 963 header("X-Debug", true); 964 return this; 965 } 966 967 /** 968 * Enabled debug mode on this request. 969 * 970 * <p> 971 * Prevents errors from being logged on the server side if no-trace per-request is enabled. 972 * 973 * @param value The enable flag value. 974 * @return This object (for method chaining). 975 */ 976 public MockServletRequest noTrace(boolean value) { 977 if (value) 978 header("X-NoTrace", true); 979 return this; 980 } 981 982 /** 983 * If the specified request is a {@link MockRestRequest}, applies any of the override values to this servlet request. 984 * 985 * @param req The request to copy overrides from. 986 * @return This object (for method chaining). 987 */ 988 public MockServletRequest applyOverrides(HttpRequest req) { 989 990 if (req instanceof MockRestRequest) { 991 MockRestRequest mreq = (MockRestRequest)req; 992 for (Map.Entry<String,Object> a : mreq.getAttributeMap().entrySet()) 993 attribute(a.getKey(), a.getValue()); 994 for (Map.Entry<String,RequestDispatcher> a : mreq.getRequestDispatcherMap().entrySet()) 995 requestDispatcher(a.getKey(), a.getValue()); 996 if (mreq.getCharacterEncoding() != null) 997 characterEncoding(mreq.getCharacterEncoding()); 998 if (mreq.getProtocol() != null) 999 protocol(mreq.getProtocol()); 1000 if (mreq.getScheme() != null) 1001 scheme(mreq.getScheme()); 1002 if (mreq.getServerName() != null) 1003 serverName(mreq.getServerName()); 1004 if (mreq.getRemoteAddr() != null) 1005 remoteAddr(mreq.getRemoteAddr()); 1006 if (mreq.getRemoteHost() != null) 1007 remoteHost(mreq.getRemoteHost()); 1008 if (mreq.getLocalName() != null) 1009 localName(mreq.getLocalName()); 1010 if (mreq.getLocalAddr() != null) 1011 localAddr(mreq.getLocalAddr()); 1012 if (mreq.getPathInfo() != null) 1013 pathInfo(mreq.getPathInfo()); 1014 if (mreq.getPathTranslated() != null) 1015 pathTranslated(mreq.getPathTranslated()); 1016 if (mreq.getContextPath() != null) 1017 contextPath(mreq.getContextPath()); 1018 if (mreq.getQueryString() != null) 1019 queryString(mreq.getQueryString()); 1020 if (mreq.getRemoteUser() != null) 1021 remoteUser(mreq.getRemoteUser()); 1022 if (mreq.getRequestedSessionId() != null) 1023 requestedSessionId(mreq.getRequestedSessionId()); 1024 if (mreq.getRequestURI() != null) 1025 requestURI(mreq.getRequestURI()); 1026 if (mreq.getServletPath() != null) 1027 servletPath(mreq.getServletPath()); 1028 if (mreq.getAuthType() != null) 1029 authType(mreq.getAuthType()); 1030 if (mreq.getServerPort() != null) 1031 serverPort(mreq.getServerPort()); 1032 if (mreq.getRemotePort() != null) 1033 remotePort(mreq.getRemotePort()); 1034 if (mreq.getLocalPort() != null) 1035 localPort(mreq.getLocalPort()); 1036 if (mreq.getLocale() != null) 1037 locale(mreq.getLocale()); 1038 if (mreq.getServletContext() != null) 1039 servletContext(mreq.getServletContext()); 1040 if (mreq.getDispatcherType() != null) 1041 dispatcherType(mreq.getDispatcherType()); 1042 if (mreq.getCookies() != null) 1043 cookies(mreq.getCookies()); 1044 if (mreq.getUserPrincipal() != null) 1045 userPrincipal(mreq.getUserPrincipal()); 1046 if (mreq.getHttpSession() != null) 1047 httpSession(mreq.getHttpSession()); 1048 if (mreq.getRoles() != null) 1049 roles(mreq.getRoles()); 1050 } 1051 1052 return this; 1053 } 1054}