1 package nginx.unit; 2 3 import java.io.BufferedReader; 4 import java.io.ByteArrayOutputStream; 5 import java.io.File; 6 import java.io.InputStreamReader; 7 import java.io.IOException; 8 import java.io.UnsupportedEncodingException; 9 10 import java.lang.IllegalArgumentException; 11 import java.lang.IllegalStateException; 12 import java.lang.Object; 13 import java.lang.String; 14 import java.lang.StringBuffer; 15 16 import java.net.URI; 17 import java.net.URISyntaxException; 18 19 import java.nio.ByteBuffer; 20 import java.nio.charset.Charset; 21 import java.nio.charset.StandardCharsets; 22 23 import java.text.ParseException; 24 import java.text.SimpleDateFormat; 25 26 import java.util.Collection; 27 import java.util.Collections; 28 import java.util.Date; 29 import java.util.Enumeration; 30 import java.util.HashMap; 31 import java.util.HashSet; 32 import java.util.List; 33 import java.util.Locale; 34 import java.util.Map; 35 import java.util.Set; 36 37 import java.security.Principal; 38 39 import javax.servlet.AsyncContext; 40 import javax.servlet.DispatcherType; 41 import javax.servlet.MultipartConfigElement; 42 import javax.servlet.RequestDispatcher; 43 import javax.servlet.ServletContext; 44 import javax.servlet.ServletException; 45 import javax.servlet.ServletInputStream; 46 import javax.servlet.ServletRequest; 47 import javax.servlet.ServletRequestAttributeEvent; 48 import javax.servlet.ServletRequestAttributeListener; 49 import javax.servlet.ServletResponse; 50 import javax.servlet.SessionTrackingMode; 51 import javax.servlet.SessionCookieConfig; 52 import javax.servlet.http.Cookie; 53 import javax.servlet.http.HttpSession; 54 import javax.servlet.http.HttpServletRequest; 55 import javax.servlet.http.HttpServletResponse; 56 import javax.servlet.http.HttpUpgradeHandler; 57 import javax.servlet.http.Part; 58 59 import org.eclipse.jetty.util.IO; 60 import org.eclipse.jetty.util.MultiMap; 61 import org.eclipse.jetty.util.UrlEncoded; 62 import org.eclipse.jetty.util.StringUtil; 63 64 import org.eclipse.jetty.server.CookieCutter; 65 import org.eclipse.jetty.http.MultiPartFormInputStream; 66 import org.eclipse.jetty.http.HttpFields; 67 import org.eclipse.jetty.http.MimeTypes; 68 69 import nginx.unit.websocket.WsSession; 70 import nginx.unit.websocket.WsIOException; 71 72 public class Request implements HttpServletRequest, DynamicPathRequest 73 { 74 private final Context context; 75 private final long req_info_ptr; 76 private final long req_ptr; 77 78 protected String authType = null; 79 80 protected boolean cookiesParsed = false; 81 82 protected CookieCutter cookies = null; 83 84 private final Map<String, Object> attributes = new HashMap<>(); 85 86 private MultiMap<String> parameters = null; 87 88 private final String context_path; 89 private String filter_path = null; 90 private String servlet_path = null; 91 private String path_info = null; 92 private String request_uri = null; 93 private String query_string = null; 94 private boolean query_string_valid = false; 95 96 private DispatcherType dispatcher_type = DispatcherType.REQUEST; 97 98 private String characterEncoding = null; 99 100 /** 101 * The only date format permitted when generating HTTP headers. 102 */ 103 public static final String RFC1123_DATE = 104 "EEE, dd MMM yyyy HH:mm:ss zzz"; 105 106 private static final SimpleDateFormat formats[] = { 107 new SimpleDateFormat(RFC1123_DATE, Locale.US), 108 new SimpleDateFormat("EEEEEE, dd-MMM-yy HH:mm:ss zzz", Locale.US), 109 new SimpleDateFormat("EEE MMMM d HH:mm:ss yyyy", Locale.US) 110 }; 111 112 private InputStream inputStream = null; 113 private BufferedReader reader = null; 114 115 private boolean request_session_id_parsed = false; 116 private String request_session_id = null; 117 private boolean request_session_id_from_cookie = false; 118 private boolean request_session_id_from_url = false; 119 private Session session = null; 120 121 private WsSession wsSession = null; 122 private boolean skip_close_ws = false; 123 124 private final ServletRequestAttributeListener attr_listener; 125 126 public static final String BARE = "nginx.unit.request.bare"; 127 128 private MultiPartFormInputStream multi_parts; 129 private MultipartConfigElement multipart_config; 130 Request(Context ctx, long req_info, long req)131 public Request(Context ctx, long req_info, long req) { 132 context = ctx; 133 req_info_ptr = req_info; 134 req_ptr = req; 135 136 attr_listener = context.getRequestAttributeListener(); 137 context_path = context.getContextPath(); 138 } 139 140 @Override authenticate(HttpServletResponse response)141 public boolean authenticate(HttpServletResponse response) 142 throws IOException, ServletException 143 { 144 log("authenticate"); 145 146 if (response.isCommitted()) { 147 throw new IllegalStateException(); 148 } 149 150 return false; 151 } 152 153 @Override getAuthType()154 public String getAuthType() 155 { 156 log("getAuthType"); 157 158 return authType; 159 } 160 161 @Override getContextPath()162 public String getContextPath() 163 { 164 trace("getContextPath: " + context_path); 165 166 return context_path; 167 } 168 169 @Override getCookies()170 public Cookie[] getCookies() 171 { 172 trace("getCookies"); 173 174 if (!cookiesParsed) { 175 parseCookies(); 176 } 177 178 //Javadoc for Request.getCookies() stipulates null for no cookies 179 if (cookies == null || cookies.getCookies().length == 0) { 180 return null; 181 } 182 183 return cookies.getCookies(); 184 } 185 parseCookies()186 protected void parseCookies() 187 { 188 cookiesParsed = true; 189 190 cookies = new CookieCutter(); 191 192 Enumeration<String> cookie_headers = getHeaders("Cookie"); 193 194 while (cookie_headers.hasMoreElements()) { 195 cookies.addCookieField(cookie_headers.nextElement()); 196 } 197 } 198 199 @Override getDateHeader(String name)200 public long getDateHeader(String name) 201 { 202 trace("getDateHeader: " + name); 203 204 String value = getHeader(name); 205 if (value == null) { 206 return -1L; 207 } 208 209 long res = parseDate(value); 210 if (res == -1L) { 211 throw new IllegalArgumentException(value); 212 } 213 214 return res; 215 } 216 parseDate(String value)217 protected long parseDate(String value) 218 { 219 Date date = null; 220 for (int i = 0; (date == null) && (i < formats.length); i++) { 221 try { 222 date = formats[i].parse(value); 223 } catch (ParseException e) { 224 // Ignore 225 } 226 } 227 if (date == null) { 228 return -1L; 229 } 230 return date.getTime(); 231 } 232 233 @Override getHeader(String name)234 public String getHeader(String name) 235 { 236 String res = getHeader(req_ptr, name, name.length()); 237 238 trace("getHeader: " + name + " = '" + res + "'"); 239 240 return res; 241 } 242 getHeader(long req_ptr, String name, int name_len)243 private static native String getHeader(long req_ptr, String name, int name_len); 244 245 246 @Override getHeaderNames()247 public Enumeration<String> getHeaderNames() 248 { 249 trace("getHeaderNames"); 250 251 return getHeaderNames(req_ptr); 252 } 253 getHeaderNames(long req_ptr)254 private static native Enumeration<String> getHeaderNames(long req_ptr); 255 256 257 @Override getHeaders(String name)258 public Enumeration<String> getHeaders(String name) 259 { 260 trace("getHeaders: " + name); 261 262 return getHeaders(req_ptr, name, name.length()); 263 } 264 getHeaders(long req_ptr, String name, int name_len)265 private static native Enumeration<String> getHeaders(long req_ptr, String name, int name_len); 266 267 268 @Override getIntHeader(String name)269 public int getIntHeader(String name) 270 { 271 trace("getIntHeader: " + name); 272 273 return getIntHeader(req_ptr, name, name.length()); 274 } 275 getIntHeader(long req_ptr, String name, int name_len)276 private static native int getIntHeader(long req_ptr, String name, int name_len); 277 278 279 @Override getMethod()280 public String getMethod() 281 { 282 trace("getMethod"); 283 284 return getMethod(req_ptr); 285 } 286 getMethod(long req_ptr)287 private static native String getMethod(long req_ptr); 288 289 290 @Override getPart(String name)291 public Part getPart(String name) throws IOException, ServletException 292 { 293 trace("getPart: " + name); 294 295 if (multi_parts == null) { 296 parseMultiParts(); 297 } 298 299 return multi_parts.getPart(name); 300 } 301 302 @Override getParts()303 public Collection<Part> getParts() throws IOException, ServletException 304 { 305 trace("getParts"); 306 307 if (multi_parts == null) { 308 parseMultiParts(); 309 } 310 311 return multi_parts.getParts(); 312 } 313 checkMultiPart(String content_type)314 private boolean checkMultiPart(String content_type) 315 { 316 return content_type != null 317 && MimeTypes.Type.MULTIPART_FORM_DATA.is(HttpFields.valueParameters(content_type, null)); 318 } 319 parseMultiParts()320 private void parseMultiParts() throws IOException, ServletException, IllegalStateException 321 { 322 String content_type = getContentType(); 323 324 if (!checkMultiPart(content_type)) { 325 throw new ServletException("Content-Type != multipart/form-data"); 326 } 327 328 if (multipart_config == null) { 329 throw new IllegalStateException("No multipart config for servlet"); 330 } 331 332 parseMultiParts(content_type); 333 } 334 parseMultiParts(String content_type)335 private void parseMultiParts(String content_type) throws IOException 336 { 337 File tmpDir = (File) context.getAttribute(ServletContext.TEMPDIR); 338 339 multi_parts = new MultiPartFormInputStream(getInputStream(), 340 content_type, multipart_config, tmpDir); 341 } 342 setMultipartConfig(MultipartConfigElement mce)343 public void setMultipartConfig(MultipartConfigElement mce) 344 { 345 multipart_config = mce; 346 } 347 getMultipartConfig()348 public MultipartConfigElement getMultipartConfig() 349 { 350 return multipart_config; 351 } 352 353 @Override getPathInfo()354 public String getPathInfo() 355 { 356 trace("getPathInfo: " + path_info); 357 358 return path_info; 359 } 360 361 @Override getPathTranslated()362 public String getPathTranslated() 363 { 364 trace("getPathTranslated"); 365 366 if (path_info == null) { 367 return null; 368 } 369 370 return context.getRealPath(path_info); 371 } 372 373 @Override getQueryString()374 public String getQueryString() 375 { 376 if (!query_string_valid) { 377 query_string = getQueryString(req_ptr); 378 query_string_valid = true; 379 } 380 381 trace("getQueryString: " + query_string); 382 383 return query_string; 384 } 385 getQueryString(long req_ptr)386 private static native String getQueryString(long req_ptr); 387 388 @Override setQueryString(String query)389 public void setQueryString(String query) 390 { 391 trace("setQueryString: " + query); 392 393 query_string = query; 394 query_string_valid = true; 395 } 396 397 @Override getRemoteUser()398 public String getRemoteUser() 399 { 400 log("getRemoteUser"); 401 402 /* TODO */ 403 return null; 404 } 405 406 @Override getRequestedSessionId()407 public String getRequestedSessionId() 408 { 409 trace("getRequestedSessionId"); 410 411 if (!request_session_id_parsed) { 412 parseRequestSessionId(); 413 } 414 415 return request_session_id; 416 } 417 parseRequestSessionId()418 private void parseRequestSessionId() 419 { 420 request_session_id_parsed = true; 421 422 Cookie[] cookies = getCookies(); 423 if (cookies == null) { 424 return; 425 } 426 427 if (context.getEffectiveSessionTrackingModes().contains( 428 SessionTrackingMode.COOKIE)) 429 { 430 final String name = context.getSessionCookieConfig().getName(); 431 432 for (Cookie c : cookies) { 433 if (c.getName().equals(name)) { 434 request_session_id = c.getValue(); 435 request_session_id_from_cookie = true; 436 437 return; 438 } 439 } 440 } 441 } 442 443 @Override getRequestURI()444 public String getRequestURI() 445 { 446 if (request_uri == null) { 447 request_uri = getRequestURI(req_ptr); 448 } 449 450 trace("getRequestURI: " + request_uri); 451 452 return request_uri; 453 } 454 getRequestURI(long req_ptr)455 private static native String getRequestURI(long req_ptr); 456 457 458 @Override setRequestURI(String uri)459 public void setRequestURI(String uri) 460 { 461 trace("setRequestURI: " + uri); 462 463 request_uri = uri; 464 } 465 466 467 @Override getRequestURL()468 public StringBuffer getRequestURL() 469 { 470 String host = getHeader("Host"); 471 String uri = getRequestURI(); 472 StringBuffer res = new StringBuffer("http://" + host + uri); 473 474 trace("getRequestURL: " + res); 475 476 return res; 477 } 478 479 @Override getServletPath()480 public String getServletPath() 481 { 482 trace("getServletPath: " + servlet_path); 483 484 return servlet_path; 485 } 486 487 @Override setServletPath(String servlet_path, String path_info)488 public void setServletPath(String servlet_path, String path_info) 489 { 490 trace("setServletPath: " + servlet_path); 491 492 this.filter_path = servlet_path; 493 this.servlet_path = servlet_path; 494 this.path_info = path_info; 495 } 496 497 @Override setServletPath(String filter_path, String servlet_path, String path_info)498 public void setServletPath(String filter_path, String servlet_path, String path_info) 499 { 500 trace("setServletPath: " + filter_path + ", " + servlet_path); 501 502 this.filter_path = filter_path; 503 this.servlet_path = servlet_path; 504 this.path_info = path_info; 505 } 506 507 @Override getFilterPath()508 public String getFilterPath() 509 { 510 return filter_path; 511 } 512 513 @Override getSession()514 public HttpSession getSession() 515 { 516 return getSession(true); 517 } 518 519 @Override getSession(boolean create)520 public HttpSession getSession(boolean create) 521 { 522 if (session != null) { 523 if (context.isSessionIdValid(session.getId())) { 524 trace("getSession(" + create + "): " + session.getId()); 525 526 return session; 527 } 528 529 session = null; 530 } 531 532 if (!request_session_id_parsed) { 533 parseRequestSessionId(); 534 535 session = context.getSession(request_session_id); 536 } 537 538 if (session != null || !create) { 539 trace("getSession(" + create + "): " + (session != null ? session.getId() : "null")); 540 541 return session; 542 } 543 544 session = context.createSession(); 545 546 if (context.getEffectiveSessionTrackingModes().contains( 547 SessionTrackingMode.COOKIE)) 548 { 549 setSessionIdCookie(); 550 } 551 552 trace("getSession(" + create + "): " + session.getId()); 553 554 return session; 555 } 556 setSessionIdCookie()557 private void setSessionIdCookie() 558 { 559 SessionCookieConfig config = context.getSessionCookieConfig(); 560 561 Cookie c = new Cookie(config.getName(), session.getId()); 562 563 c.setComment(config.getComment()); 564 if (!StringUtil.isBlank(config.getDomain())) { 565 c.setDomain(config.getDomain()); 566 } 567 568 c.setHttpOnly(config.isHttpOnly()); 569 if (!StringUtil.isBlank(config.getPath())) { 570 c.setPath(config.getPath()); 571 } 572 573 c.setMaxAge(config.getMaxAge()); 574 575 getResponse(req_info_ptr).addSessionIdCookie(c); 576 } 577 578 @Override getUserPrincipal()579 public Principal getUserPrincipal() 580 { 581 log("getUserPrincipal"); 582 583 return null; 584 } 585 586 @Override isRequestedSessionIdFromCookie()587 public boolean isRequestedSessionIdFromCookie() 588 { 589 trace("isRequestedSessionIdFromCookie"); 590 591 if (!request_session_id_parsed) { 592 parseRequestSessionId(); 593 } 594 595 return request_session_id_from_cookie; 596 } 597 598 @Override 599 @Deprecated isRequestedSessionIdFromUrl()600 public boolean isRequestedSessionIdFromUrl() 601 { 602 trace("isRequestedSessionIdFromUrl"); 603 604 if (!request_session_id_parsed) { 605 parseRequestSessionId(); 606 } 607 608 return request_session_id_from_url; 609 } 610 611 @Override isRequestedSessionIdFromURL()612 public boolean isRequestedSessionIdFromURL() 613 { 614 trace("isRequestedSessionIdFromURL"); 615 616 if (!request_session_id_parsed) { 617 parseRequestSessionId(); 618 } 619 620 return request_session_id_from_url; 621 } 622 623 @Override isRequestedSessionIdValid()624 public boolean isRequestedSessionIdValid() 625 { 626 trace("isRequestedSessionIdValid"); 627 628 if (!request_session_id_parsed) { 629 parseRequestSessionId(); 630 } 631 632 return context.isSessionIdValid(request_session_id); 633 } 634 635 @Override isUserInRole(String role)636 public boolean isUserInRole(String role) 637 { 638 log("isUserInRole: " + role); 639 640 return false; 641 } 642 643 @Override login(String username, String password)644 public void login(String username, String password) throws ServletException 645 { 646 log("login: " + username + "," + password); 647 } 648 649 @Override logout()650 public void logout() throws ServletException 651 { 652 log("logout"); 653 } 654 655 656 @Override getAsyncContext()657 public AsyncContext getAsyncContext() 658 { 659 log("getAsyncContext"); 660 661 return null; 662 } 663 664 @Override getAttribute(String name)665 public Object getAttribute(String name) 666 { 667 if (BARE.equals(name)) { 668 return this; 669 } 670 671 Object o = attributes.get(name); 672 673 trace("getAttribute: " + name + " = " + o); 674 675 return o; 676 } 677 678 @Override getAttributeNames()679 public Enumeration<String> getAttributeNames() 680 { 681 trace("getAttributeNames"); 682 683 Set<String> names = attributes.keySet(); 684 return Collections.enumeration(names); 685 } 686 687 @Override getCharacterEncoding()688 public String getCharacterEncoding() 689 { 690 trace("getCharacterEncoding"); 691 692 if (characterEncoding != null) { 693 return characterEncoding; 694 } 695 696 getContentType(); 697 698 return characterEncoding; 699 } 700 701 @Override getContentLength()702 public int getContentLength() 703 { 704 trace("getContentLength"); 705 706 return (int) getContentLength(req_ptr); 707 } 708 getContentLength(long req_ptr)709 private static native long getContentLength(long req_ptr); 710 711 @Override getContentLengthLong()712 public long getContentLengthLong() 713 { 714 trace("getContentLengthLong"); 715 716 return getContentLength(req_ptr); 717 } 718 719 @Override getContentType()720 public String getContentType() 721 { 722 trace("getContentType"); 723 724 String content_type = getContentType(req_ptr); 725 726 if (characterEncoding == null && content_type != null) { 727 MimeTypes.Type mime = MimeTypes.CACHE.get(content_type); 728 String charset = (mime == null || mime.getCharset() == null) ? MimeTypes.getCharsetFromContentType(content_type) : mime.getCharset().toString(); 729 if (charset != null) { 730 characterEncoding = charset; 731 } 732 } 733 734 return content_type; 735 } 736 getContentType(long req_ptr)737 private static native String getContentType(long req_ptr); 738 739 740 @Override getDispatcherType()741 public DispatcherType getDispatcherType() 742 { 743 trace("getDispatcherType: " + dispatcher_type); 744 745 return dispatcher_type; 746 } 747 748 @Override setDispatcherType(DispatcherType type)749 public void setDispatcherType(DispatcherType type) 750 { 751 trace("setDispatcherType: " + type); 752 753 dispatcher_type = type; 754 } 755 756 @Override getInputStream()757 public ServletInputStream getInputStream() throws IOException 758 { 759 trace("getInputStream"); 760 761 if (reader != null) { 762 throw new IllegalStateException("getInputStream: getReader() already used"); 763 } 764 765 if (inputStream == null) { 766 inputStream = new InputStream(req_info_ptr); 767 } 768 769 return inputStream; 770 } 771 772 @Override getLocalAddr()773 public String getLocalAddr() 774 { 775 trace("getLocalAddr"); 776 777 return getLocalAddr(req_ptr); 778 } 779 getLocalAddr(long req_ptr)780 private static native String getLocalAddr(long req_ptr); 781 782 783 @Override getLocale()784 public Locale getLocale() 785 { 786 log("getLocale"); 787 788 return Locale.getDefault(); 789 } 790 791 @Override getLocales()792 public Enumeration<Locale> getLocales() 793 { 794 log("getLocales"); 795 796 return Collections.emptyEnumeration(); 797 } 798 799 @Override getLocalName()800 public String getLocalName() 801 { 802 trace("getLocalName"); 803 804 return getLocalName(req_ptr); 805 } 806 getLocalName(long req_ptr)807 private static native String getLocalName(long req_ptr); 808 809 810 @Override getLocalPort()811 public int getLocalPort() 812 { 813 trace("getLocalPort"); 814 815 return getLocalPort(req_ptr); 816 } 817 getLocalPort(long req_ptr)818 private static native int getLocalPort(long req_ptr); 819 820 getParameters()821 public MultiMap<String> getParameters() 822 { 823 if (parameters != null) { 824 return parameters; 825 } 826 827 parameters = new MultiMap<>(); 828 829 String query = getQueryString(); 830 831 if (query != null) { 832 UrlEncoded.decodeUtf8To(query, parameters); 833 } 834 835 int content_length = getContentLength(); 836 837 if (content_length == 0 || !getMethod().equals("POST")) { 838 return parameters; 839 } 840 841 String content_type = getContentType(); 842 843 try { 844 if (content_type.startsWith("application/x-www-form-urlencoded")) { 845 UrlEncoded.decodeUtf8To(new InputStream(req_info_ptr), 846 parameters, content_length, -1); 847 } else if (checkMultiPart(content_type) && multipart_config != null) { 848 if (multi_parts == null) { 849 parseMultiParts(content_type); 850 } 851 852 if (multi_parts != null) { 853 Collection<Part> parts = multi_parts.getParts(); 854 855 String _charset_ = null; 856 Part charset_part = multi_parts.getPart("_charset_"); 857 if (charset_part != null) { 858 try (java.io.InputStream is = charset_part.getInputStream()) 859 { 860 ByteArrayOutputStream os = new ByteArrayOutputStream(); 861 IO.copy(is, os); 862 _charset_ = new String(os.toByteArray(),StandardCharsets.UTF_8); 863 } 864 } 865 866 /* 867 Select Charset to use for this part. (NOTE: charset behavior is for the part value only and not the part header/field names) 868 1. Use the part specific charset as provided in that part's Content-Type header; else 869 2. Use the overall default charset. Determined by: 870 a. if part name _charset_ exists, use that part's value. 871 b. if the request.getCharacterEncoding() returns a value, use that. 872 (note, this can be either from the charset field on the request Content-Type 873 header, or from a manual call to request.setCharacterEncoding()) 874 c. use utf-8. 875 */ 876 Charset def_charset; 877 if (_charset_ != null) { 878 def_charset = Charset.forName(_charset_); 879 } else if (getCharacterEncoding() != null) { 880 def_charset = Charset.forName(getCharacterEncoding()); 881 } else { 882 def_charset = StandardCharsets.UTF_8; 883 } 884 885 ByteArrayOutputStream os = null; 886 for (Part p : parts) { 887 if (p.getSubmittedFileName() != null) { 888 continue; 889 } 890 891 // Servlet Spec 3.0 pg 23, parts without filename must be put into params. 892 String charset = null; 893 if (p.getContentType() != null) { 894 charset = MimeTypes.getCharsetFromContentType(p.getContentType()); 895 } 896 897 try (java.io.InputStream is = p.getInputStream()) 898 { 899 if (os == null) { 900 os = new ByteArrayOutputStream(); 901 } 902 IO.copy(is, os); 903 904 String content = new String(os.toByteArray(), charset == null ? def_charset : Charset.forName(charset)); 905 parameters.add(p.getName(), content); 906 } 907 os.reset(); 908 } 909 } 910 } 911 } catch (IOException e) { 912 log("Unhandled IOException: " + e); 913 } 914 915 return parameters; 916 } 917 setParameters(MultiMap<String> p)918 public void setParameters(MultiMap<String> p) 919 { 920 parameters = p; 921 } 922 923 @Override getParameter(String name)924 public String getParameter(String name) 925 { 926 trace("getParameter: " + name); 927 928 return getParameters().getValue(name, 0); 929 } 930 931 @Override getParameterMap()932 public Map<String,String[]> getParameterMap() 933 { 934 trace("getParameterMap"); 935 936 return Collections.unmodifiableMap(getParameters().toStringArrayMap()); 937 } 938 939 @Override getParameterNames()940 public Enumeration<String> getParameterNames() 941 { 942 trace("getParameterNames"); 943 944 return Collections.enumeration(getParameters().keySet()); 945 } 946 947 @Override getParameterValues(String name)948 public String[] getParameterValues(String name) 949 { 950 trace("getParameterValues: " + name); 951 952 List<String> vals = getParameters().getValues(name); 953 if (vals == null) 954 return null; 955 return vals.toArray(new String[vals.size()]); 956 } 957 958 @Override getProtocol()959 public String getProtocol() 960 { 961 trace("getProtocol"); 962 963 return getProtocol(req_ptr); 964 } 965 getProtocol(long req_ptr)966 private static native String getProtocol(long req_ptr); 967 968 @Override getReader()969 public BufferedReader getReader() throws IOException 970 { 971 trace("getReader"); 972 973 if (inputStream != null) { 974 throw new IllegalStateException("getReader: getInputStream() already used"); 975 } 976 977 if (reader == null) { 978 reader = new BufferedReader(new InputStreamReader(new InputStream(req_info_ptr))); 979 } 980 981 return reader; 982 } 983 984 @Override 985 @Deprecated getRealPath(String path)986 public String getRealPath(String path) 987 { 988 trace("getRealPath: " + path); 989 990 return context.getRealPath(path); 991 } 992 993 @Override getRemoteAddr()994 public String getRemoteAddr() 995 { 996 String res = getRemoteAddr(req_ptr); 997 998 trace("getRemoteAddr: " + res); 999 1000 return res; 1001 } 1002 getRemoteAddr(long req_ptr)1003 private static native String getRemoteAddr(long req_ptr); 1004 1005 1006 @Override getRemoteHost()1007 public String getRemoteHost() 1008 { 1009 String res = getRemoteHost(req_ptr); 1010 1011 trace("getRemoteHost: " + res); 1012 1013 return res; 1014 } 1015 getRemoteHost(long req_ptr)1016 private static native String getRemoteHost(long req_ptr); 1017 1018 1019 @Override getRemotePort()1020 public int getRemotePort() 1021 { 1022 int res = getRemotePort(req_ptr); 1023 1024 trace("getRemotePort: " + res); 1025 1026 return res; 1027 } 1028 getRemotePort(long req_ptr)1029 private static native int getRemotePort(long req_ptr); 1030 1031 1032 @Override getRequestDispatcher(String path)1033 public RequestDispatcher getRequestDispatcher(String path) 1034 { 1035 trace("getRequestDispatcher: " + path); 1036 1037 if (path.startsWith("/")) { 1038 return context.getRequestDispatcher(path); 1039 } 1040 1041 try { 1042 URI uri = new URI(getRequestURI()); 1043 uri = uri.resolve(path); 1044 1045 return context.getRequestDispatcher(uri); 1046 } catch (URISyntaxException e) { 1047 log("getRequestDispatcher: failed to create dispatcher: " + e); 1048 } 1049 1050 return null; 1051 } 1052 1053 1054 @Override getScheme()1055 public String getScheme() 1056 { 1057 trace("getScheme"); 1058 1059 return getScheme(req_ptr); 1060 } 1061 getScheme(long req_ptr)1062 private static native String getScheme(long req_ptr); 1063 1064 1065 @Override getServerName()1066 public String getServerName() 1067 { 1068 String res = getServerName(req_ptr); 1069 1070 trace("getServerName: " + res); 1071 1072 return res; 1073 } 1074 getServerName(long req_ptr)1075 private static native String getServerName(long req_ptr); 1076 1077 1078 @Override getServerPort()1079 public int getServerPort() 1080 { 1081 int res = getServerPort(req_ptr); 1082 1083 trace("getServerPort: " + res); 1084 1085 return res; 1086 } 1087 getServerPort(long req_ptr)1088 private static native int getServerPort(long req_ptr); 1089 1090 @Override getServletContext()1091 public ServletContext getServletContext() 1092 { 1093 trace("getServletContext"); 1094 1095 return context; 1096 } 1097 1098 @Override isAsyncStarted()1099 public boolean isAsyncStarted() 1100 { 1101 log("isAsyncStarted"); 1102 1103 return false; 1104 } 1105 1106 @Override isAsyncSupported()1107 public boolean isAsyncSupported() 1108 { 1109 log("isAsyncSupported"); 1110 1111 return false; 1112 } 1113 1114 @Override isSecure()1115 public boolean isSecure() 1116 { 1117 trace("isSecure"); 1118 1119 return isSecure(req_ptr); 1120 } 1121 isSecure(long req_ptr)1122 private static native boolean isSecure(long req_ptr); 1123 1124 @Override removeAttribute(String name)1125 public void removeAttribute(String name) 1126 { 1127 trace("removeAttribute: " + name); 1128 1129 Object prev = attributes.remove(name); 1130 1131 if (attr_listener == null || prev == null) { 1132 return; 1133 } 1134 1135 attr_listener.attributeRemoved( 1136 new ServletRequestAttributeEvent(context, this, name, prev)); 1137 } 1138 1139 @Override setAttribute(String name, Object o)1140 public void setAttribute(String name, Object o) 1141 { 1142 trace("setAttribute: " + name + ", " + o); 1143 1144 Object prev; 1145 1146 if (o != null) { 1147 prev = attributes.put(name, o); 1148 } else { 1149 prev = attributes.remove(name); 1150 } 1151 1152 if (attr_listener == null) { 1153 return; 1154 } 1155 1156 if (prev == null) { 1157 if (o == null) { 1158 return; 1159 } 1160 1161 attr_listener.attributeAdded(new ServletRequestAttributeEvent( 1162 context, this, name, o)); 1163 } else { 1164 if (o != null) { 1165 attr_listener.attributeReplaced( 1166 new ServletRequestAttributeEvent(context, this, name, prev)); 1167 } else { 1168 attr_listener.attributeRemoved( 1169 new ServletRequestAttributeEvent(context, this, name, prev)); 1170 } 1171 } 1172 } 1173 setAttribute_(String name, Object o)1174 public void setAttribute_(String name, Object o) 1175 { 1176 trace("setAttribute_: " + name + ", " + o); 1177 1178 if (o != null) { 1179 attributes.put(name, o); 1180 } else { 1181 attributes.remove(name); 1182 } 1183 } 1184 1185 @Override setCharacterEncoding(String env)1186 public void setCharacterEncoding(String env) throws UnsupportedEncodingException 1187 { 1188 trace("setCharacterEncoding: " + env); 1189 1190 characterEncoding = env; 1191 } 1192 1193 @Override startAsync()1194 public AsyncContext startAsync() throws IllegalStateException 1195 { 1196 log("startAsync"); 1197 1198 return null; 1199 } 1200 1201 @Override startAsync(ServletRequest servletRequest, ServletResponse servletResponse)1202 public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) throws IllegalStateException 1203 { 1204 log("startAsync(Req, resp)"); 1205 1206 return null; 1207 } 1208 1209 @Override upgrade( Class<T> httpUpgradeHandlerClass)1210 public <T extends HttpUpgradeHandler> T upgrade( 1211 Class<T> httpUpgradeHandlerClass) throws java.io.IOException, ServletException 1212 { 1213 trace("upgrade: " + httpUpgradeHandlerClass.getName()); 1214 1215 T handler; 1216 1217 try { 1218 handler = httpUpgradeHandlerClass.getConstructor().newInstance(); 1219 } catch (Exception e) { 1220 throw new ServletException(e); 1221 } 1222 1223 upgrade(req_info_ptr); 1224 1225 return handler; 1226 } 1227 upgrade(long req_info_ptr)1228 private static native void upgrade(long req_info_ptr); 1229 isUpgrade()1230 public boolean isUpgrade() 1231 { 1232 return isUpgrade(req_info_ptr); 1233 } 1234 isUpgrade(long req_info_ptr)1235 private static native boolean isUpgrade(long req_info_ptr); 1236 1237 @Override changeSessionId()1238 public String changeSessionId() 1239 { 1240 trace("changeSessionId"); 1241 1242 getSession(false); 1243 1244 if (session == null) { 1245 return null; 1246 } 1247 1248 context.changeSessionId(session); 1249 1250 if (context.getEffectiveSessionTrackingModes().contains( 1251 SessionTrackingMode.COOKIE)) 1252 { 1253 setSessionIdCookie(); 1254 } 1255 1256 return session.getId(); 1257 } 1258 log(String msg)1259 private void log(String msg) 1260 { 1261 msg = "Request." + msg; 1262 log(req_info_ptr, msg, msg.length()); 1263 } 1264 log(long req_info_ptr, String msg, int msg_len)1265 public static native void log(long req_info_ptr, String msg, int msg_len); 1266 1267 trace(String msg)1268 private void trace(String msg) 1269 { 1270 msg = "Request." + msg; 1271 trace(req_info_ptr, msg, msg.length()); 1272 } 1273 trace(long req_info_ptr, String msg, int msg_len)1274 public static native void trace(long req_info_ptr, String msg, int msg_len); 1275 getResponse(long req_info_ptr)1276 private static native Response getResponse(long req_info_ptr); 1277 1278 setWsSession(WsSession s)1279 public void setWsSession(WsSession s) 1280 { 1281 wsSession = s; 1282 } 1283 processWsFrame(ByteBuffer buf, byte opCode, boolean last)1284 private void processWsFrame(ByteBuffer buf, byte opCode, boolean last) 1285 throws IOException 1286 { 1287 trace("processWsFrame: " + opCode + ", [" + buf.position() + ", " + buf.limit() + "]"); 1288 try { 1289 wsSession.processFrame(buf, opCode, last); 1290 } catch (WsIOException e) { 1291 wsSession.onClose(e.getCloseReason()); 1292 } 1293 } 1294 closeWsSession()1295 private void closeWsSession() 1296 { 1297 trace("closeWsSession"); 1298 skip_close_ws = true; 1299 1300 wsSession.onClose(); 1301 } 1302 sendWsFrame(ByteBuffer payload, byte opCode, boolean last, long timeoutExpiry)1303 public void sendWsFrame(ByteBuffer payload, byte opCode, boolean last, 1304 long timeoutExpiry) throws IOException 1305 { 1306 trace("sendWsFrame: " + opCode + ", [" + payload.position() + 1307 ", " + payload.limit() + "]"); 1308 1309 if (payload.isDirect()) { 1310 sendWsFrame(req_info_ptr, payload, payload.position(), 1311 payload.limit() - payload.position(), opCode, last); 1312 } else { 1313 sendWsFrame(req_info_ptr, payload.array(), payload.position(), 1314 payload.limit() - payload.position(), opCode, last); 1315 } 1316 } 1317 sendWsFrame(long req_info_ptr, ByteBuffer buf, int pos, int len, byte opCode, boolean last)1318 private static native void sendWsFrame(long req_info_ptr, 1319 ByteBuffer buf, int pos, int len, byte opCode, boolean last); 1320 sendWsFrame(long req_info_ptr, byte[] arr, int pos, int len, byte opCode, boolean last)1321 private static native void sendWsFrame(long req_info_ptr, 1322 byte[] arr, int pos, int len, byte opCode, boolean last); 1323 1324 closeWs()1325 public void closeWs() 1326 { 1327 if (skip_close_ws) { 1328 return; 1329 } 1330 1331 trace("closeWs"); 1332 1333 closeWs(req_info_ptr); 1334 } 1335 closeWs(long req_info_ptr)1336 private static native void closeWs(long req_info_ptr); 1337 } 1338 1339