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