1 7 package winstone; 8 9 import java.io.BufferedReader ; 10 import java.io.IOException ; 11 import java.io.InputStream ; 12 import java.io.InputStreamReader ; 13 import java.io.UnsupportedEncodingException ; 14 import java.security.MessageDigest ; 15 import java.security.NoSuchAlgorithmException ; 16 import java.security.Principal ; 17 import java.text.DateFormat ; 18 import java.text.SimpleDateFormat ; 19 import java.util.ArrayList ; 20 import java.util.Arrays ; 21 import java.util.Collection ; 22 import java.util.Collections ; 23 import java.util.Date ; 24 import java.util.Enumeration ; 25 import java.util.HashMap ; 26 import java.util.HashSet ; 27 import java.util.Hashtable ; 28 import java.util.Iterator ; 29 import java.util.List ; 30 import java.util.Locale ; 31 import java.util.Map ; 32 import java.util.Random ; 33 import java.util.Set ; 34 import java.util.Stack ; 35 import java.util.StringTokenizer ; 36 import java.util.TimeZone ; 37 38 import javax.servlet.ServletInputStream ; 39 import javax.servlet.ServletRequestAttributeEvent ; 40 import javax.servlet.ServletRequestAttributeListener ; 41 import javax.servlet.ServletRequestListener ; 42 import javax.servlet.http.Cookie ; 43 import javax.servlet.http.HttpServletRequest ; 44 import javax.servlet.http.HttpSession ; 45 46 47 53 public class WinstoneRequest implements HttpServletRequest { 54 protected static DateFormat headerDF = new SimpleDateFormat ( 55 "EEE, dd MMM yyyy HH:mm:ss z", Locale.US); 56 protected static Random rnd = null; 57 static { 58 headerDF.setTimeZone(TimeZone.getTimeZone("GMT")); 59 rnd = new Random (System.currentTimeMillis()); 60 } 61 62 static final String CONTENT_LENGTH_HEADER = "Content-Length"; 64 static final String CONTENT_TYPE_HEADER = "Content-Type"; 65 static final String AUTHORIZATION_HEADER = "Authorization"; 66 static final String LOCALE_HEADER = "Accept-Language"; 67 static final String HOST_HEADER = "Host"; 68 static final String IN_COOKIE_HEADER1 = "Cookie"; 69 static final String IN_COOKIE_HEADER2 = "Cookie2"; 70 static final String METHOD_HEAD = "HEAD"; 71 static final String METHOD_GET = "GET"; 72 static final String METHOD_POST = "POST"; 73 static final String POST_PARAMETERS = "application/x-www-form-urlencoded"; 74 75 protected Map attributes; 76 protected Map parameters; 77 protected Stack attributesStack; 78 protected Stack parametersStack; 79 81 protected String headers[]; 82 protected Cookie cookies[]; 83 84 protected String method; 85 protected String scheme; 86 protected String serverName; 87 protected String requestURI; 88 protected String servletPath; 89 protected String pathInfo; 90 protected String queryString; 91 protected String protocol; 92 protected int contentLength; 93 protected String contentType; 94 protected String encoding; 95 96 protected int serverPort; 97 protected String remoteIP; 98 protected String remoteName; 99 protected int remotePort; 100 protected String localAddr; 101 protected String localName; 102 protected int localPort; 103 protected Boolean parsedParameters; 104 protected Map requestedSessionIds; 105 protected Map currentSessionIds; 106 protected String deadRequestedSessionId; 107 protected List locales; 108 protected String authorization; 109 protected boolean isSecure; 110 111 protected WinstoneInputStream inputData; 112 protected BufferedReader inputReader; 113 protected ServletConfiguration servletConfig; 114 protected WebAppConfiguration webappConfig; 115 protected HostGroup hostGroup; 116 117 protected AuthenticationPrincipal authenticatedUser; 118 protected ServletRequestAttributeListener requestAttributeListeners[]; 119 protected ServletRequestListener requestListeners[]; 120 121 private MessageDigest md5Digester; 122 123 private Set usedSessions; 124 125 128 public WinstoneRequest() throws IOException { 129 this.attributes = new Hashtable (); 130 this.parameters = new Hashtable (); 131 this.locales = new ArrayList (); 132 this.attributesStack = new Stack (); 133 this.parametersStack = new Stack (); 134 this.requestedSessionIds = new Hashtable (); 136 this.currentSessionIds = new Hashtable (); 137 this.usedSessions = new HashSet (); 138 this.contentLength = -1; 139 this.isSecure = false; 140 try { 141 this.md5Digester = MessageDigest.getInstance("MD5"); 142 } catch (NoSuchAlgorithmException err) { 143 throw new WinstoneException( 144 "MD5 digester unavailable - what the ...?"); 145 } 146 } 147 148 151 public void cleanUp() { 152 this.requestListeners = null; 153 this.requestAttributeListeners = null; 154 this.attributes.clear(); 155 this.parameters.clear(); 156 this.attributesStack.clear(); 157 this.parametersStack.clear(); 158 this.usedSessions.clear(); 160 this.headers = null; 161 this.cookies = null; 162 this.method = null; 163 this.scheme = null; 164 this.serverName = null; 165 this.requestURI = null; 166 this.servletPath = null; 167 this.pathInfo = null; 168 this.queryString = null; 169 this.protocol = null; 170 this.contentLength = -1; 171 this.contentType = null; 172 this.encoding = null; 173 this.inputData = null; 174 this.inputReader = null; 175 this.servletConfig = null; 176 this.webappConfig = null; 177 this.hostGroup = null; 178 this.serverPort = -1; 179 this.remoteIP = null; 180 this.remoteName = null; 181 this.remotePort = -1; 182 this.localAddr = null; 183 this.localName = null; 184 this.localPort = -1; 185 this.parsedParameters = null; 186 this.requestedSessionIds.clear(); 187 this.currentSessionIds.clear(); 188 this.deadRequestedSessionId = null; 189 this.locales.clear(); 190 this.authorization = null; 191 this.isSecure = false; 192 this.authenticatedUser = null; 193 } 194 195 198 private String extractFirstHeader(String name) { 199 for (int n = 0; n < this.headers.length; n++) { 200 if (this.headers[n].toUpperCase().startsWith(name.toUpperCase() + ':')) { 201 return this.headers[n].substring(name.length() + 1).trim(); } 203 } 204 return null; 205 } 206 207 private Collection extractHeaderNameList() { 208 Collection headerNames = new HashSet (); 209 for (int n = 0; n < this.headers.length; n++) { 210 String name = this.headers[n]; 211 int colonPos = name.indexOf(':'); 212 headerNames.add(name.substring(0, colonPos)); 213 } 214 return headerNames; 215 } 216 217 public Map getAttributes() { 218 return this.attributes; 219 } 220 221 public Map getParameters() { 222 return this.parameters; 223 } 224 229 public Stack getAttributesStack() { 230 return this.attributesStack; 231 } 232 233 public Stack getParametersStack() { 234 return this.parametersStack; 235 } 236 237 public Map getCurrentSessionIds() { 238 return this.currentSessionIds; 239 } 240 241 public Map getRequestedSessionIds() { 242 return this.requestedSessionIds; 243 } 244 245 public String getDeadRequestedSessionId() { 246 return this.deadRequestedSessionId; 247 } 248 249 public HostGroup getHostGroup() { 250 return this.hostGroup; 251 } 252 253 public WebAppConfiguration getWebAppConfig() { 254 return this.webappConfig; 255 } 256 257 public ServletConfiguration getServletConfig() { 258 return this.servletConfig; 259 } 260 261 public String getEncoding() { 262 return this.encoding; 263 } 264 265 public Boolean getParsedParameters() { 266 return this.parsedParameters; 267 } 268 269 public List getListLocales() { 270 return this.locales; 271 } 272 273 public void setInputStream(WinstoneInputStream inputData) { 274 this.inputData = inputData; 275 } 276 277 public void setHostGroup(HostGroup hostGroup) { 278 this.hostGroup = hostGroup; 279 } 280 281 public void setWebAppConfig(WebAppConfiguration webappConfig) { 282 this.webappConfig = webappConfig; 283 } 284 285 public void setServletConfig(ServletConfiguration servletConfig) { 286 this.servletConfig = servletConfig; 287 } 288 289 public void setServerPort(int port) { 290 this.serverPort = port; 291 } 292 293 public void setRemoteIP(String remoteIP) { 294 this.remoteIP = remoteIP; 295 } 296 297 public void setRemoteName(String name) { 298 this.remoteName = name; 299 } 300 301 public void setRemotePort(int port) { 302 this.remotePort = port; 303 } 304 305 public void setLocalAddr(String ip) { 306 this.localName = ip; 307 } 308 309 public void setLocalName(String name) { 310 this.localName = name; 311 } 312 313 public void setLocalPort(int port) { 314 this.localPort = port; 315 } 316 317 public void setMethod(String method) { 318 this.method = method; 319 } 320 321 public void setIsSecure(boolean isSecure) { 322 this.isSecure = isSecure; 323 } 324 325 public void setQueryString(String queryString) { 326 this.queryString = queryString; 327 } 328 329 public void setServerName(String name) { 330 this.serverName = name; 331 } 332 333 public void setRequestURI(String requestURI) { 334 this.requestURI = requestURI; 335 } 336 337 public void setScheme(String scheme) { 338 this.scheme = scheme; 339 } 340 341 public void setServletPath(String servletPath) { 342 this.servletPath = servletPath; 343 } 344 345 public void setPathInfo(String pathInfo) { 346 this.pathInfo = pathInfo; 347 } 348 349 public void setProtocol(String protocolString) { 350 this.protocol = protocolString; 351 } 352 353 public void setRemoteUser(AuthenticationPrincipal user) { 354 this.authenticatedUser = user; 355 } 356 357 public void setContentLength(int len) { 358 this.contentLength = len; 359 } 360 361 public void setContentType(String type) { 362 this.contentType = type; 363 } 364 365 public void setAuthorization(String auth) { 366 this.authorization = auth; 367 } 368 369 public void setLocales(List locales) { 370 this.locales = locales; 371 } 372 373 public void setCurrentSessionIds(Map currentSessionIds) { 374 this.currentSessionIds = currentSessionIds; 375 } 376 377 public void setRequestedSessionIds(Map requestedSessionIds) { 378 this.requestedSessionIds = requestedSessionIds; 379 } 380 381 public void setDeadRequestedSessionId(String deadRequestedSessionId) { 382 this.deadRequestedSessionId = deadRequestedSessionId; 383 } 384 385 public void setEncoding(String encoding) { 386 this.encoding = encoding; 387 } 388 389 public void setParsedParameters(Boolean parsed) { 390 this.parsedParameters = parsed; 391 } 392 393 public void setRequestListeners(ServletRequestListener rl[]) { 394 this.requestListeners = rl; 395 } 396 397 public void setRequestAttributeListeners( 398 ServletRequestAttributeListener ral[]) { 399 this.requestAttributeListeners = ral; 400 } 401 402 405 public static void extractParameters(String urlEncodedParams, 406 String encoding, Map outputParams, boolean overwrite) { 407 Logger.log(Logger.DEBUG, Launcher.RESOURCES, 408 "WinstoneRequest.ParsingParameters", new String [] { 409 urlEncodedParams, encoding }); 410 StringTokenizer st = new StringTokenizer (urlEncodedParams, "&", false); 411 Set overwrittenParamNames = null; 412 while (st.hasMoreTokens()) { 413 String token = st.nextToken(); 414 int equalPos = token.indexOf('='); 415 try { 416 String decodedNameDefault = decodeURLToken(equalPos == -1 ? token 417 : token.substring(0, equalPos)); 418 String decodedValueDefault = (equalPos == -1 ? "" 419 : decodeURLToken(token.substring(equalPos + 1))); 420 String decodedName = (encoding == null ? decodedNameDefault 421 : new String (decodedNameDefault.getBytes("8859_1"), encoding)); 422 String decodedValue = (encoding == null ? decodedValueDefault 423 : new String (decodedValueDefault.getBytes("8859_1"), encoding)); 424 425 Object already = null; 426 if (overwrite) { 427 if (overwrittenParamNames == null) { 428 overwrittenParamNames = new HashSet (); 429 } 430 if (!overwrittenParamNames.contains(decodedName)) { 431 overwrittenParamNames.add(decodedName); 432 outputParams.remove(decodedName); 433 } 434 } 435 already = outputParams.get(decodedName); 436 if (already == null) { 437 outputParams.put(decodedName, decodedValue); 438 } else if (already instanceof String ) { 439 String pair[] = new String [2]; 440 pair[0] = (String ) already; 441 pair[1] = decodedValue; 442 outputParams.put(decodedName, pair); 443 } else if (already instanceof String []) { 444 String alreadyArray[] = (String []) already; 445 String oneMore[] = new String [alreadyArray.length + 1]; 446 System.arraycopy(alreadyArray, 0, oneMore, 0, 447 alreadyArray.length); 448 oneMore[oneMore.length - 1] = decodedValue; 449 outputParams.put(decodedName, oneMore); 450 } else { 451 Logger.log(Logger.WARNING, Launcher.RESOURCES, 452 "WinstoneRequest.UnknownParameterType", 453 decodedName + " = " + decodedValue.getClass()); 454 } 455 } catch (UnsupportedEncodingException err) { 456 Logger.log(Logger.ERROR, Launcher.RESOURCES, 457 "WinstoneRequest.ErrorParameters", err); 458 } 459 } 460 } 461 462 465 public static String decodeURLToken(String in) { 466 StringBuffer workspace = new StringBuffer (); 467 for (int n = 0; n < in.length(); n++) { 468 char thisChar = in.charAt(n); 469 if (thisChar == '+') 470 workspace.append(' '); 471 else if (thisChar == '%') { 472 String token = in.substring(Math.min(n + 1, in.length()), 473 Math.min(n + 3, in.length())); 474 try { 475 int decoded = Integer.parseInt(token, 16); 476 workspace.append((char) decoded); 477 n += 2; 478 } catch (RuntimeException err) { 479 Logger.log(Logger.WARNING, Launcher.RESOURCES, "WinstoneRequest.InvalidURLTokenChar", token); 480 workspace.append(thisChar); 481 } 482 } else 483 workspace.append(thisChar); 484 } 485 return workspace.toString(); 486 } 487 488 public void discardRequestBody() { 489 if (getContentLength() > 0) { 490 try { 491 Logger.log(Logger.DEBUG, Launcher.RESOURCES, "WinstoneResponse.ForceBodyParsing"); 492 if ((this.parsedParameters == null) || 494 (this.parsedParameters.equals(Boolean.FALSE))) { 495 InputStream in = getInputStream(); 497 byte buffer[] = new byte[2048]; 498 while (in.read(buffer) != -1) 499 ; 500 } 501 } catch (IOException err) { 502 Logger.log(Logger.DEBUG, Launcher.RESOURCES, "WinstoneResponse.ErrorForceBodyParsing", err); 503 } 504 } 505 } 506 507 511 public void parseRequestParameters() { 512 if ((parsedParameters != null) && !parsedParameters.booleanValue()) { 513 Logger.log(Logger.WARNING, Launcher.RESOURCES, 514 "WinstoneRequest.BothMethods"); 515 this.parsedParameters = Boolean.TRUE; 516 } else if (parsedParameters == null) { 517 Map workingParameters = new HashMap (); 518 try { 519 if ((method.equals(METHOD_GET) || method.equals(METHOD_HEAD) || 521 method.equals(METHOD_POST)) 522 && (this.queryString != null)) { 523 extractParameters(this.queryString, this.encoding, workingParameters, false); 524 Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES, 525 "WinstoneRequest.ParamLine", "" + workingParameters); 526 } 527 528 if (method.equals(METHOD_POST) && (contentType != null) 529 && contentType.equals(POST_PARAMETERS)) { 530 Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES, 531 "WinstoneRequest.ParsingBodyParameters"); 532 533 byte paramBuffer[] = new byte[contentLength]; 535 int readCount = this.inputData.read(paramBuffer); 536 if (readCount != contentLength) 537 Logger.log(Logger.WARNING, Launcher.RESOURCES, 538 "WinstoneRequest.IncorrectContentLength", 539 new String [] { contentLength + "", 540 readCount + "" }); 541 String paramLine = (this.encoding == null ? new String ( 542 paramBuffer) : new String (paramBuffer, 543 this.encoding)); 544 extractParameters(paramLine.trim(), this.encoding, workingParameters, false); 545 Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES, 546 "WinstoneRequest.ParamLine", "" + workingParameters); 547 } 548 549 this.parameters.putAll(workingParameters); 550 this.parsedParameters = Boolean.TRUE; 551 } catch (Throwable err) { 552 Logger.log(Logger.ERROR, Launcher.RESOURCES, 553 "WinstoneRequest.ErrorBodyParameters", err); 554 this.parsedParameters = null; 555 } 556 } 557 } 558 559 563 public void parseHeaders(List headerList) { 564 List outHeaderList = new ArrayList (); 566 List cookieList = new ArrayList (); 567 for (Iterator i = headerList.iterator(); i.hasNext();) { 568 String header = (String ) i.next(); 569 int colonPos = header.indexOf(':'); 570 String name = header.substring(0, colonPos); 571 String value = header.substring(colonPos + 1).trim(); 572 573 outHeaderList.add(header); 575 578 if (name.equalsIgnoreCase(AUTHORIZATION_HEADER)) 579 this.authorization = value; 580 else if (name.equalsIgnoreCase(LOCALE_HEADER)) 581 this.locales = parseLocales(value); 582 else if (name.equalsIgnoreCase(CONTENT_LENGTH_HEADER)) 583 this.contentLength = Integer.parseInt(value); 584 else if (name.equalsIgnoreCase(HOST_HEADER)) { 585 int nextColonPos = value.indexOf(':'); 586 if ((nextColonPos == -1) || (nextColonPos == value.length() - 1)) { 587 this.serverName = value; 588 if (this.scheme != null) { 589 if (this.scheme.equals("http")) { 590 this.serverPort = 80; 591 } else if (this.scheme.equals("https")) { 592 this.serverPort = 443; 593 } 594 } 595 } else { 596 this.serverName = value.substring(0, nextColonPos); 597 this.serverPort = Integer.parseInt(value.substring(nextColonPos + 1)); 598 } 599 } 600 else if (name.equalsIgnoreCase(CONTENT_TYPE_HEADER)) { 601 this.contentType = value; 602 int semicolon = value.lastIndexOf(';'); 603 if (semicolon != -1) { 604 String encodingClause = value.substring(semicolon + 1).trim(); 605 if (encodingClause.startsWith("charset=")) 606 this.encoding = encodingClause.substring(8); 607 } 608 } else if (name.equalsIgnoreCase(IN_COOKIE_HEADER1) 609 || name.equalsIgnoreCase(IN_COOKIE_HEADER2)) 610 parseCookieLine(value, cookieList); 611 } 612 this.headers = (String []) outHeaderList.toArray(new String [0]); 613 if (cookieList.isEmpty()) { 614 this.cookies = null; 615 } else { 616 this.cookies = (Cookie []) cookieList.toArray(new Cookie [0]); 617 } 618 } 619 620 private static String nextToken(StringTokenizer st) { 621 if (st.hasMoreTokens()) { 622 return st.nextToken(); 623 } else { 624 return null; 625 } 626 } 627 628 private void parseCookieLine(String headerValue, List cookieList) { 629 StringTokenizer st = new StringTokenizer (headerValue, ";", false); 630 int version = 0; 631 String cookieLine = nextToken(st); 632 633 if (cookieLine.startsWith("$Version=")) { 635 int equalPos = cookieLine.indexOf('='); 636 try { 637 version = Integer.parseInt(extractFromQuotes( 638 cookieLine.substring(equalPos + 1).trim())); 639 } catch (NumberFormatException err) { 640 version = 0; 641 } 642 cookieLine = nextToken(st); 643 } 644 645 while (cookieLine != null) { 647 cookieLine = cookieLine.trim(); 648 int equalPos = cookieLine.indexOf('='); 649 if (equalPos == -1) { 650 cookieLine = nextToken(st); 652 } else { 653 String name = cookieLine.substring(0, equalPos); 654 String value = extractFromQuotes(cookieLine.substring(equalPos + 1)); 655 Cookie thisCookie = new Cookie (name, value); 656 thisCookie.setVersion(version); 657 thisCookie.setSecure(isSecure()); 658 cookieList.add(thisCookie); 659 660 cookieLine = nextToken(st); 662 while ((cookieLine != null) && cookieLine.trim().startsWith("$")) { 663 cookieLine = cookieLine.trim(); 664 equalPos = cookieLine.indexOf('='); 665 String attrValue = equalPos == -1 ? "" : cookieLine 666 .substring(equalPos + 1).trim(); 667 if (cookieLine.startsWith("$Path")) { 668 thisCookie.setPath(extractFromQuotes(attrValue)); 669 } else if (cookieLine.startsWith("$Domain")) { 670 thisCookie.setDomain(extractFromQuotes(attrValue)); 671 } 672 cookieLine = nextToken(st); 673 } 674 675 Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES, 676 "WinstoneRequest.CookieFound", thisCookie.toString()); 677 if (thisCookie.getName().equals(WinstoneSession.SESSION_COOKIE_NAME)) { 678 HostConfiguration hostConfig = this.hostGroup.getHostByName(this.serverName); 680 WebAppConfiguration ownerContext = hostConfig.getWebAppBySessionKey(thisCookie.getValue()); 681 if (ownerContext != null) { 682 this.requestedSessionIds.put(ownerContext.getContextPath(), 683 thisCookie.getValue()); 684 this.currentSessionIds.put(ownerContext.getContextPath(), 685 thisCookie.getValue()); 686 } 687 else { 689 this.deadRequestedSessionId = thisCookie.getValue(); 690 } 691 Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES, 694 "WinstoneRequest.SessionCookieFound", 695 new String [] {thisCookie.getValue(), 696 ownerContext == null ? "" : "prefix:" + ownerContext.getContextPath()}); 697 } 698 } 699 } 700 } 701 702 private static String extractFromQuotes(String input) { 703 if ((input != null) && input.startsWith("\"") && input.endsWith("\"")) { 704 return input.substring(1, input.length() - 1); 705 } else { 706 return input; 707 } 708 } 709 710 private List parseLocales(String header) { 711 StringBuffer lb = new StringBuffer (); 713 for (int n = 0; n < header.length(); n++) { 714 char c = header.charAt(n); 715 if (!Character.isWhitespace(c)) 716 lb.append(c); 717 } 718 719 Map localeEntries = new HashMap (); 721 StringTokenizer commaTK = new StringTokenizer (lb.toString(), ",", false); 722 for (; commaTK.hasMoreTokens();) { 723 String clause = commaTK.nextToken(); 724 725 Float quality = new Float (1); 727 if (clause.indexOf(";q=") != -1) { 728 int pos = clause.indexOf(";q="); 729 try { 730 quality = new Float (clause.substring(pos + 3)); 731 } catch (NumberFormatException err) { 732 quality = new Float (0); 733 } 734 clause = clause.substring(0, pos); 735 } 736 737 String language = ""; 739 String country = ""; 740 String variant = ""; 741 int dpos = clause.indexOf('-'); 742 if (dpos == -1) 743 language = clause; 744 else { 745 language = clause.substring(0, dpos); 746 String remainder = clause.substring(dpos + 1); 747 int d2pos = remainder.indexOf('-'); 748 if (d2pos == -1) 749 country = remainder; 750 else { 751 country = remainder.substring(0, d2pos); 752 variant = remainder.substring(d2pos + 1); 753 } 754 } 755 Locale loc = new Locale (language, country, variant); 756 757 List localeList = (List ) localeEntries.get(quality); 759 if (localeList == null) { 760 localeList = new ArrayList (); 761 localeEntries.put(quality, localeList); 762 } 763 localeList.add(loc); 764 } 765 766 Float orderKeys[] = (Float []) localeEntries.keySet().toArray(new Float [0]); 768 Arrays.sort(orderKeys); 769 List outputLocaleList = new ArrayList (); 770 for (int n = 0; n < orderKeys.length; n++) { 771 int reversedIndex = (orderKeys.length - 1) - n; 773 if ((orderKeys[reversedIndex].floatValue() <= 0) 774 || (orderKeys[reversedIndex].floatValue() > 1)) 775 continue; 776 List localeList = (List ) localeEntries.get(orderKeys[reversedIndex]); 777 for (Iterator i = localeList.iterator(); i.hasNext();) 778 outputLocaleList.add(i.next()); 779 } 780 781 return outputLocaleList; 782 } 783 784 public void addIncludeQueryParameters(String queryString) { 785 Map lastParams = new Hashtable (); 786 if (!this.parametersStack.isEmpty()) { 787 lastParams.putAll((Map ) this.parametersStack.peek()); 788 } 789 Map newQueryParams = new HashMap (); 790 if (queryString != null) { 791 extractParameters(queryString, this.encoding, newQueryParams, false); 792 } 793 lastParams.putAll(newQueryParams); 794 this.parametersStack.push(lastParams); 795 } 796 797 public void addIncludeAttributes(String requestURI, String contextPath, 798 String servletPath, String pathInfo, String queryString) { 799 Map includeAttributes = new HashMap (); 800 if (requestURI != null) { 801 includeAttributes.put(RequestDispatcher.INCLUDE_REQUEST_URI, requestURI); 802 } 803 if (contextPath != null) { 804 includeAttributes.put(RequestDispatcher.INCLUDE_CONTEXT_PATH, contextPath); 805 } 806 if (servletPath != null) { 807 includeAttributes.put(RequestDispatcher.INCLUDE_SERVLET_PATH, servletPath); 808 } 809 if (pathInfo != null) { 810 includeAttributes.put(RequestDispatcher.INCLUDE_PATH_INFO, pathInfo); 811 } 812 if (queryString != null) { 813 includeAttributes.put(RequestDispatcher.INCLUDE_QUERY_STRING, queryString); 814 } 815 this.attributesStack.push(includeAttributes); 816 } 817 818 public void removeIncludeQueryString() { 819 if (!this.parametersStack.isEmpty()) { 820 this.parametersStack.pop(); 821 } 822 } 823 824 public void clearIncludeStackForForward() { 825 this.parametersStack.clear(); 826 this.attributesStack.clear(); 827 } 828 829 public void setForwardQueryString(String forwardQueryString) { 830 832 if (forwardQueryString != null) { 834 String oldQueryString = this.queryString == null ? "" : this.queryString; 835 boolean needJoiner = !forwardQueryString.equals("") && !oldQueryString.equals(""); 836 this.queryString = forwardQueryString + (needJoiner ? "&" : "") + oldQueryString; 837 838 if (this.parsedParameters != null) { 839 Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES, 840 "WinstoneRequest.ParsingParameters", new String [] { 841 forwardQueryString, this.encoding }); 842 extractParameters(forwardQueryString, this.encoding, this.parameters, true); 843 Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES, 844 "WinstoneRequest.ParamLine", "" + this.parameters); 845 } 846 } 847 848 } 849 850 public void removeIncludeAttributes() { 851 if (!this.attributesStack.isEmpty()) { 852 this.attributesStack.pop(); 853 } 854 } 855 856 public Object getAttribute(String name) { 858 if (!this.attributesStack.isEmpty()) { 859 Map includedAttributes = (Map ) this.attributesStack.peek(); 860 Object value = includedAttributes.get(name); 861 if (value != null) { 862 return value; 863 } 864 } 865 return this.attributes.get(name); 866 } 867 868 public Enumeration getAttributeNames() { 869 Map attributes = new HashMap (this.attributes); 870 if (!this.attributesStack.isEmpty()) { 871 Map includedAttributes = (Map ) this.attributesStack.peek(); 872 attributes.putAll(includedAttributes); 873 } 874 return Collections.enumeration(attributes.keySet()); 875 } 876 877 public void removeAttribute(String name) { 878 Object value = attributes.get(name); 879 if (value == null) 880 return; 881 882 if (this.requestAttributeListeners != null) { 884 for (int n = 0; n < this.requestAttributeListeners.length; n++) { 885 ClassLoader cl = Thread.currentThread().getContextClassLoader(); 886 Thread.currentThread().setContextClassLoader(getWebAppConfig().getLoader()); 887 this.requestAttributeListeners[n].attributeRemoved( 888 new ServletRequestAttributeEvent (this.webappConfig, 889 this, name, value)); 890 Thread.currentThread().setContextClassLoader(cl); 891 } 892 } 893 894 this.attributes.remove(name); 895 } 896 897 public void setAttribute(String name, Object o) { 898 if ((name != null) && (o != null)) { 899 Object oldValue = attributes.get(name); 900 attributes.put(name, o); 902 if (this.requestAttributeListeners != null) { 904 if (oldValue == null) { 905 for (int n = 0; n < this.requestAttributeListeners.length; n++) { 906 ClassLoader cl = Thread.currentThread().getContextClassLoader(); 907 Thread.currentThread().setContextClassLoader(getWebAppConfig().getLoader()); 908 this.requestAttributeListeners[n].attributeAdded( 909 new ServletRequestAttributeEvent (this.webappConfig, 910 this, name, o)); 911 Thread.currentThread().setContextClassLoader(cl); 912 } 913 } else { 914 for (int n = 0; n < this.requestAttributeListeners.length; n++) { 915 ClassLoader cl = Thread.currentThread().getContextClassLoader(); 916 Thread.currentThread().setContextClassLoader(getWebAppConfig().getLoader()); 917 this.requestAttributeListeners[n] 918 .attributeReplaced(new ServletRequestAttributeEvent ( 919 this.webappConfig, this, name, oldValue)); 920 Thread.currentThread().setContextClassLoader(cl); 921 } 922 } 923 } 924 } else if (name != null) { 925 removeAttribute(name); 926 } 927 } 928 929 public String getCharacterEncoding() { 930 return this.encoding; 931 } 932 933 public void setCharacterEncoding(String encoding) throws UnsupportedEncodingException { 934 "blah".getBytes(encoding); if (this.inputReader == null) { 936 Logger.log(Logger.DEBUG, Launcher.RESOURCES, "WinstoneRequest.SetCharEncoding", 937 new String [] { this.encoding, encoding }); 938 this.encoding = encoding; 939 } 940 } 941 942 public int getContentLength() { 943 return this.contentLength; 944 } 945 946 public String getContentType() { 947 return this.contentType; 948 } 949 950 public Locale getLocale() { 951 return this.locales.isEmpty() ? Locale.getDefault() 952 : (Locale ) this.locales.get(0); 953 } 954 955 public Enumeration getLocales() { 956 List sendLocales = this.locales; 957 if (sendLocales.isEmpty()) 958 sendLocales.add(Locale.getDefault()); 959 return Collections.enumeration(sendLocales); 960 } 961 962 public String getProtocol() { 963 return this.protocol; 964 } 965 966 public String getScheme() { 967 return this.scheme; 968 } 969 970 public boolean isSecure() { 971 return this.isSecure; 972 } 973 974 public BufferedReader getReader() throws IOException { 975 if (this.inputReader != null) { 976 return this.inputReader; 977 } else { 978 if (this.parsedParameters != null) { 979 if (this.parsedParameters.equals(Boolean.TRUE)) { 980 Logger.log(Logger.WARNING, Launcher.RESOURCES, "WinstoneRequest.BothMethodsReader"); 981 } else { 982 throw new IllegalStateException (Launcher.RESOURCES.getString( 983 "WinstoneRequest.CalledReaderAfterStream")); 984 } 985 } 986 if (this.encoding != null) { 987 this.inputReader = new BufferedReader (new InputStreamReader ( 988 this.inputData, this.encoding)); 989 } else { 990 this.inputReader = new BufferedReader (new InputStreamReader ( 991 this.inputData)); 992 } 993 this.parsedParameters = new Boolean (false); 994 return this.inputReader; 995 } 996 } 997 998 public ServletInputStream getInputStream() throws IOException { 999 if (this.inputReader != null) { 1000 throw new IllegalStateException (Launcher.RESOURCES.getString( 1001 "WinstoneRequest.CalledStreamAfterReader")); 1002 } 1003 if (this.parsedParameters != null) { 1004 if (this.parsedParameters.equals(Boolean.TRUE)) { 1005 Logger.log(Logger.WARNING, Launcher.RESOURCES, "WinstoneRequest.BothMethods"); 1006 } 1007 } 1008 this.parsedParameters = new Boolean (false); 1009 return this.inputData; 1010 } 1011 1012 public String getParameter(String name) { 1013 parseRequestParameters(); 1014 Object param = null; 1015 if (!this.parametersStack.isEmpty()) { 1016 param = ((Map ) this.parametersStack.peek()).get(name); 1017 } 1018 if (param == null) { 1022 param = this.parameters.get(name); 1023 } 1024 if (param == null) 1025 return null; 1026 else if (param instanceof String ) 1027 return (String ) param; 1028 else if (param instanceof String []) 1029 return ((String []) param)[0]; 1030 else 1031 return param.toString(); 1032 } 1033 1034 public Enumeration getParameterNames() { 1035 parseRequestParameters(); 1036 Set parameterKeys = new HashSet (this.parameters.keySet()); 1037 if (!this.parametersStack.isEmpty()) { 1039 parameterKeys.addAll(((Map ) this.parametersStack.peek()).keySet()); 1040 } 1041 return Collections.enumeration(parameterKeys); 1042 } 1043 1044 public String [] getParameterValues(String name) { 1045 parseRequestParameters(); 1046 Object param = null; 1047 if (!this.parametersStack.isEmpty()) { 1048 param = ((Map ) this.parametersStack.peek()).get(name); 1049 } 1050 if (param == null) { 1054 param = this.parameters.get(name); 1055 } 1056 if (param == null) 1057 return null; 1058 else if (param instanceof String ) { 1059 return new String [] {(String ) param}; 1060 } else if (param instanceof String []) 1061 return (String []) param; 1062 else 1063 throw new WinstoneException(Launcher.RESOURCES.getString( 1064 "WinstoneRequest.UnknownParameterType", name + " - " 1065 + param.getClass())); 1066 } 1067 1068 public Map getParameterMap() { 1069 Hashtable paramMap = new Hashtable (); 1070 for (Enumeration names = this.getParameterNames(); names 1071 .hasMoreElements();) { 1072 String name = (String ) names.nextElement(); 1073 paramMap.put(name, getParameterValues(name)); 1074 } 1075 return paramMap; 1076 } 1077 1078 public String getServerName() { 1079 return this.serverName; 1080 } 1081 1082 public int getServerPort() { 1083 return this.serverPort; 1084 } 1085 1086 public String getRemoteAddr() { 1087 return this.remoteIP; 1088 } 1089 1090 public String getRemoteHost() { 1091 return this.remoteName; 1092 } 1093 1094 public int getRemotePort() { 1095 return this.remotePort; 1096 } 1097 1098 public String getLocalAddr() { 1099 return this.localAddr; 1100 } 1101 1102 public String getLocalName() { 1103 return this.localName; 1104 } 1105 1106 public int getLocalPort() { 1107 return this.localPort; 1108 } 1109 1110 public javax.servlet.RequestDispatcher getRequestDispatcher(String path) { 1111 if (path.startsWith("/")) 1112 return this.webappConfig.getRequestDispatcher(path); 1113 1114 String fullPath = getServletPath() 1116 + (getPathInfo() == null ? "" : getPathInfo()); 1117 int lastSlash = fullPath.lastIndexOf('/'); 1118 String currentDir = (lastSlash == -1 ? "/" : fullPath.substring(0, 1119 lastSlash + 1)); 1120 return this.webappConfig.getRequestDispatcher(currentDir + path); 1121 } 1122 1123 public String getContextPath() { 1125 return this.webappConfig.getContextPath(); 1126 } 1127 1128 public Cookie [] getCookies() { 1129 return this.cookies; 1130 } 1131 1132 public long getDateHeader(String name) { 1133 String dateHeader = getHeader(name); 1134 if (dateHeader == null) { 1135 return -1; 1136 } else try { 1137 Date date = null; 1138 synchronized (headerDF) { 1139 date = headerDF.parse(dateHeader); 1140 } 1141 return date.getTime(); 1142 } catch (java.text.ParseException err) { 1143 throw new IllegalArgumentException (Launcher.RESOURCES.getString( 1144 "WinstoneRequest.BadDate", dateHeader)); 1145 } 1146 } 1147 1148 public int getIntHeader(String name) { 1149 String header = getHeader(name); 1150 return header == null ? -1 : Integer.parseInt(header); 1151 } 1152 1153 public String getHeader(String name) { 1154 return extractFirstHeader(name); 1155 } 1156 1157 public Enumeration getHeaderNames() { 1158 return Collections.enumeration(extractHeaderNameList()); 1159 } 1160 1161 public Enumeration getHeaders(String name) { 1162 List headers = new ArrayList (); 1163 for (int n = 0; n < this.headers.length; n++) 1164 if (this.headers[n].toUpperCase().startsWith( 1165 name.toUpperCase() + ':')) 1166 headers 1167 .add(this.headers[n].substring(name.length() + 1) 1168 .trim()); return Collections.enumeration(headers); 1170 } 1171 1172 public String getMethod() { 1173 return this.method; 1174 } 1175 1176 public String getPathInfo() { 1177 return this.pathInfo; 1178 } 1179 1180 public String getPathTranslated() { 1181 return this.webappConfig.getRealPath(this.pathInfo); 1182 } 1183 1184 public String getQueryString() { 1185 return this.queryString; 1186 } 1187 1188 public String getRequestURI() { 1189 return this.requestURI; 1190 } 1191 1192 public String getServletPath() { 1193 return this.servletPath; 1194 } 1195 1196 public String getRequestedSessionId() { 1197 String actualSessionId = (String ) this.requestedSessionIds.get(this.webappConfig.getContextPath()); 1198 if (actualSessionId != null) { 1199 return actualSessionId; 1200 } else { 1201 return this.deadRequestedSessionId; 1202 } 1203 } 1204 1205 public StringBuffer getRequestURL() { 1206 StringBuffer url = new StringBuffer (); 1207 url.append(getScheme()).append("://"); 1208 url.append(getServerName()); 1209 if (!((getServerPort() == 80) && getScheme().equals("http")) 1210 && !((getServerPort() == 443) && getScheme().equals("https"))) 1211 url.append(':').append(getServerPort()); 1212 url.append(this.webappConfig.getContextPath()); 1213 url.append(getServletPath()); 1214 if (getPathInfo() != null) 1215 url.append(getPathInfo()); 1216 return url; 1217 } 1218 1219 public Principal getUserPrincipal() { 1220 return this.authenticatedUser; 1221 } 1222 1223 public boolean isUserInRole(String role) { 1224 if (this.authenticatedUser == null) 1225 return false; 1226 else if (this.servletConfig.getSecurityRoleRefs() == null) 1227 return this.authenticatedUser.isUserIsInRole(role); 1228 else { 1229 String replacedRole = (String ) this.servletConfig.getSecurityRoleRefs().get(role); 1230 return this.authenticatedUser 1231 .isUserIsInRole(replacedRole == null ? role : replacedRole); 1232 } 1233 } 1234 1235 public String getAuthType() { 1236 return this.authenticatedUser == null ? null : this.authenticatedUser 1237 .getAuthType(); 1238 } 1239 1240 public String getRemoteUser() { 1241 return this.authenticatedUser == null ? null : this.authenticatedUser 1242 .getName(); 1243 } 1244 1245 public boolean isRequestedSessionIdFromCookie() { 1246 return (getRequestedSessionId() != null); 1247 } 1248 1249 public boolean isRequestedSessionIdFromURL() { 1250 return false; 1251 } 1252 1253 public boolean isRequestedSessionIdValid() { 1254 String requestedId = getRequestedSessionId(); 1255 if (requestedId == null) { 1256 return false; 1257 } 1258 WinstoneSession ws = this.webappConfig.getSessionById(requestedId, false); 1259 return (ws != null); 1260 } 1266 1267 public HttpSession getSession() { 1268 return getSession(true); 1269 } 1270 1271 public HttpSession getSession(boolean create) { 1272 String cookieValue = (String ) this.currentSessionIds.get(this.webappConfig.getContextPath()); 1273 1274 if (cookieValue == null) { 1276 if (!create) { 1277 return null; 1278 } else { 1279 cookieValue = makeNewSession().getId(); 1280 } 1281 } 1282 1283 WinstoneSession session = this.webappConfig.getSessionById(cookieValue, false); 1285 if (session != null) { 1286 } 1292 if (create && (session == null)) { 1293 session = makeNewSession(); 1294 } 1295 if (session != null) { 1296 this.usedSessions.add(session); 1297 session.addUsed(this); 1298 } 1299 return session; 1300 } 1301 1302 1305 private WinstoneSession makeNewSession() { 1306 String cookieValue = "Winstone_" + this.remoteIP + "_" 1307 + this.serverPort + "_" + System.currentTimeMillis() + rnd.nextLong(); 1308 byte digestBytes[] = this.md5Digester.digest(cookieValue.getBytes()); 1309 1310 char outArray[] = new char[32]; 1312 for (int n = 0; n < digestBytes.length; n++) { 1313 int hiNibble = (digestBytes[n] & 0xFF) >> 4; 1314 int loNibble = (digestBytes[n] & 0xF); 1315 outArray[2 * n] = (hiNibble > 9 ? (char) (hiNibble + 87) 1316 : (char) (hiNibble + 48)); 1317 outArray[2 * n + 1] = (loNibble > 9 ? (char) (loNibble + 87) 1318 : (char) (loNibble + 48)); 1319 } 1320 1321 String newSessionId = new String (outArray); 1322 this.currentSessionIds.put(this.webappConfig.getContextPath(), newSessionId); 1323 return this.webappConfig.makeNewSession(newSessionId); 1324 } 1325 1326 public void markSessionsAsRequestFinished(long lastAccessedTime, boolean saveSessions) { 1327 for (Iterator i = this.usedSessions.iterator(); i.hasNext(); ) { 1328 WinstoneSession session = (WinstoneSession) i.next(); 1329 session.setLastAccessedDate(lastAccessedTime); 1330 session.removeUsed(this); 1331 if (saveSessions) { 1332 session.saveToTemp(); 1333 } 1334 } 1335 this.usedSessions.clear(); 1336 } 1337 1338 1341 public String getRealPath(String path) { 1342 return this.webappConfig.getRealPath(path); 1343 } 1344 1345 1348 public boolean isRequestedSessionIdFromUrl() { 1349 return isRequestedSessionIdFromURL(); 1350 } 1351 1352} 1353 | Popular Tags |