001package org.apache.turbine.services.rundata; 002 003/* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022import java.io.IOException; 023import java.io.PrintWriter; 024import java.nio.charset.Charset; 025import java.util.ArrayList; 026import java.util.HashMap; 027import java.util.List; 028import java.util.Locale; 029import java.util.Map; 030 031import javax.naming.Context; 032import javax.servlet.ServletConfig; 033import javax.servlet.ServletContext; 034import javax.servlet.http.HttpServletRequest; 035import javax.servlet.http.HttpServletResponse; 036import javax.servlet.http.HttpSession; 037 038import org.apache.commons.lang3.StringUtils; 039import org.apache.fulcrum.parser.CookieParser; 040import org.apache.fulcrum.parser.ParameterParser; 041import org.apache.fulcrum.security.acl.AccessControlList; 042import org.apache.fulcrum.security.model.turbine.TurbineAccessControlList; 043import org.apache.logging.log4j.LogManager; 044import org.apache.logging.log4j.Logger; 045import org.apache.turbine.Turbine; 046import org.apache.turbine.TurbineConstants; 047import org.apache.turbine.om.security.User; 048import org.apache.turbine.pipeline.DefaultPipelineData; 049import org.apache.turbine.services.TurbineServices; 050import org.apache.turbine.services.template.TemplateService; 051import org.apache.turbine.util.FormMessages; 052import org.apache.turbine.util.LocaleUtils; 053import org.apache.turbine.util.ServerData; 054import org.apache.turbine.util.SystemError; 055import org.apache.turbine.util.template.TemplateInfo; 056 057/** 058 * DefaultTurbineRunData is the default implementation of the 059 * TurbineRunData interface, which is distributed by the Turbine 060 * RunData service, if another implementation is not defined in 061 * the default or specified RunData configuration. 062 * TurbineRunData is an extension to RunData, which 063 * is an interface to run-time information that is passed 064 * within Turbine. This provides the threading mechanism for the 065 * entire system because multiple requests can potentially come in 066 * at the same time. Thus, there is only one RunData instance 067 * for each request that is being serviced. 068 * 069 * <p>DefaultTurbineRunData implements the Recyclable interface making 070 * it possible to pool its instances for recycling. 071 * 072 * @author <a href="mailto:ilkka.priha@simsoft.fi">Ilkka Priha</a> 073 * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a> 074 * @author <a href="mailto:bhoeneis@ee.ethz.ch">Bernie Hoeneisen</a> 075 * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a> 076 * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a> 077 * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a> 078 * @version $Id$ 079 */ 080public class DefaultTurbineRunData 081 extends DefaultPipelineData 082 implements TurbineRunData 083{ 084 /** 085 * The disposed flag. 086 */ 087 private boolean disposed; 088 089 /** Cached action name to execute for this request. */ 090 private String action; 091 092 /** This is the layout that the page will use to render the screen. */ 093 private String layout; 094 095 /** Cached screen name to execute for this request. */ 096 private String screen; 097 098 /** The character encoding of template files. */ 099 private String templateEncoding; 100 101 /** This is what will build the <title></title> of the document. */ 102 private String title; 103 104 /** Determines if there is information in the outputstream or not. */ 105 private boolean outSet; 106 107 /** 108 * Cache the output stream because it can be used in many 109 * different places. 110 */ 111 private PrintWriter out; 112 113 /** The HTTP charset. */ 114 private Charset charSet; 115 116 /** The HTTP content type to return. */ 117 private String contentType = TurbineConstants.DEFAULT_HTML_CONTENT_TYPE; 118 119 /** If this is set, also set the status code to 302. */ 120 private String redirectURI; 121 122 /** The HTTP status code to return. */ 123 private int statusCode = HttpServletResponse.SC_OK; 124 125 /** This is a List to hold critical system errors. */ 126 private final List<SystemError> errors = new ArrayList<>(); 127 128 /** JNDI Contexts. */ 129 private Map<String, Context> jndiContexts; 130 131 /** @see #getRemoteAddr() */ 132 private String remoteAddr; 133 134 /** @see #getRemoteHost() */ 135 private String remoteHost; 136 137 /** @see #getUserAgent() */ 138 private String userAgent; 139 140 /** A holder for stack trace. */ 141 private String stackTrace; 142 143 /** A holder for stack trace exception. */ 144 private Throwable stackTraceException; 145 146 /** 147 * Put things here and they will be shown on the default Error 148 * screen. This is great for debugging variable values when an 149 * exception is thrown. 150 */ 151 private final Map<String, Object> debugVariables = new HashMap<>(); 152 153 /** Logging */ 154 private static final Logger log = LogManager.getLogger(DefaultTurbineRunData.class); 155 156 /** 157 * Attempts to get the User object from the session. If it does 158 * not exist, it returns null. 159 * 160 * @param session An HttpSession. 161 * 162 * @param <T> a type extending {@link User} 163 * 164 * @return A User. 165 */ 166 public static <T extends User> T getUserFromSession(HttpSession session) 167 { 168 try 169 { 170 @SuppressWarnings("unchecked") 171 T user = (T) session.getAttribute(User.SESSION_KEY); 172 return user; 173 } 174 catch (ClassCastException e) 175 { 176 return null; 177 } 178 } 179 180 /** 181 * Allows one to invalidate the user in a session. 182 * 183 * @param session An HttpSession. 184 * @return True if user was invalidated. 185 */ 186 public static boolean removeUserFromSession(HttpSession session) 187 { 188 try 189 { 190 session.removeAttribute(User.SESSION_KEY); 191 } 192 catch (Exception e) 193 { 194 return false; 195 } 196 return true; 197 } 198 199 /** 200 * Constructs a run data object. 201 */ 202 public DefaultTurbineRunData() 203 { 204 super(); 205 206 // a map to hold information to be added to pipelineData 207 put(Turbine.class, new HashMap<Class<?>, Object>()); 208 recycle(); 209 } 210 211 /** 212 * Recycles the object by removing its disposed flag. 213 */ 214 @Override 215 public void recycle() 216 { 217 disposed = false; 218 } 219 220 /** 221 * Disposes a run data object. 222 */ 223 @Override 224 public void dispose() 225 { 226 // empty pipelinedata map 227 get(Turbine.class).clear(); 228 229 action = null; 230 layout = null; 231 screen = null; 232 templateEncoding = null; 233 title = null; 234 outSet = false; 235 out = null; 236 charSet = null; 237 contentType = TurbineConstants.DEFAULT_HTML_CONTENT_TYPE; 238 redirectURI = null; 239 statusCode = HttpServletResponse.SC_OK; 240 errors.clear(); 241 jndiContexts = null; 242 remoteAddr = null; 243 remoteHost = null; 244 userAgent = null; 245 stackTrace = null; 246 stackTraceException = null; 247 debugVariables.clear(); 248 } 249 250 // *************************************** 251 // Implementation of the RunData interface 252 // *************************************** 253 254 /** 255 * Gets the parameters. 256 * 257 * @return a parameter parser. 258 */ 259 @Override 260 public ParameterParser getParameters() 261 { 262 // Parse the parameters first, if not yet done. 263 ParameterParser parameters = getParameterParser(); 264 HttpServletRequest request = getRequest(); 265 266 if (parameters != null && parameters.getRequest() != request) 267 { 268 parameters.setRequest(request); 269 } 270 271 return parameters; 272 } 273 274 /** 275 * Gets the cookies. 276 * 277 * @return a cookie parser. 278 */ 279 @Override 280 public CookieParser getCookies() 281 { 282 // Parse the cookies first, if not yet done. 283 CookieParser cookies = getCookieParser(); 284 HttpServletRequest request = getRequest(); 285 286 if (cookies != null && cookies.getRequest() != request) 287 { 288 cookies.setData(request, getResponse()); 289 } 290 291 return cookies; 292 } 293 294 /** 295 * Gets the servlet request. 296 * 297 * @return the request. 298 */ 299 @Override 300 public HttpServletRequest getRequest() 301 { 302 return get(Turbine.class, HttpServletRequest.class); 303 } 304 305 /** 306 * Gets the servlet response. 307 * 308 * @return the response. 309 */ 310 @Override 311 public HttpServletResponse getResponse() 312 { 313 return get(Turbine.class, HttpServletResponse.class); 314 } 315 316 /** 317 * Gets the servlet session information. 318 * 319 * @return the session. 320 */ 321 @Override 322 public HttpSession getSession() 323 { 324 return getRequest().getSession(); 325 } 326 327 /** 328 * Gets the servlet configuration used during servlet init. 329 * 330 * @return the configuration. 331 */ 332 @Override 333 public ServletConfig getServletConfig() 334 { 335 return get(Turbine.class, ServletConfig.class); 336 } 337 338 /** 339 * Gets the servlet context used during servlet init. 340 * 341 * @return the context. 342 */ 343 @Override 344 public ServletContext getServletContext() 345 { 346 return get(Turbine.class, ServletContext.class); 347 } 348 349 /** 350 * Gets the access control list. 351 * 352 * @return the access control list. 353 */ 354 @Override 355 public <A extends AccessControlList> A getACL() 356 { 357 @SuppressWarnings("unchecked") 358 A acl = (A)get(Turbine.class, TurbineAccessControlList.class); 359 return acl; 360 } 361 362 /** 363 * Sets the access control list. 364 * 365 * To delete ACL from session use key {@link TurbineConstants#ACL_SESSION_KEY}. 366 * Invalidate session, if session persist. 367 * 368 * @param acl an access control list. 369 */ 370 @Override 371 public void setACL(AccessControlList acl) 372 { 373 get(Turbine.class).put(TurbineAccessControlList.class, acl); 374 } 375 376 /** 377 * Whether or not an action has been defined. 378 * 379 * @return true if an action has been defined. 380 */ 381 @Override 382 public boolean hasAction() 383 { 384 return StringUtils.isNotEmpty(this.action) 385 && !this.action.equalsIgnoreCase("null"); 386 } 387 388 /** 389 * Gets the action. It returns an empty string if null so 390 * that it is easy to do conditionals on it based on the 391 * equalsIgnoreCase() method. 392 * 393 * @return a string, "" if null. 394 */ 395 @Override 396 public String getAction() 397 { 398 return hasAction() ? this.action : ""; 399 } 400 401 /** 402 * Sets the action for the request. 403 * 404 * @param action a string. 405 */ 406 @Override 407 public void setAction(String action) 408 { 409 this.action = action; 410 } 411 412 /** 413 * If the Layout has not been defined by the screen then set the 414 * layout to be "DefaultLayout". The screen object can also 415 * override this method to provide intelligent determination of 416 * the Layout to execute. You can also define that logic here as 417 * well if you want it to apply on a global scale. For example, 418 * if you wanted to allow someone to define layout "preferences" 419 * where they could dynamically change the layout for the entire 420 * site. 421 * 422 * @return a string. 423 */ 424 425 @Override 426 public String getLayout() 427 { 428 if (this.layout == null) 429 { 430 /* 431 * This will return something if the template 432 * services are running. If we get nothing we 433 * will fall back to the ECS layout. 434 */ 435 TemplateService templateService = (TemplateService)TurbineServices.getInstance().getService(TemplateService.SERVICE_NAME); 436 layout = templateService.getDefaultLayoutName(this); 437 438 if (layout == null) 439 { 440 layout = "DefaultLayout"; 441 } 442 } 443 444 return this.layout; 445 } 446 447 /** 448 * Set the layout for the request. 449 * 450 * @param layout a string. 451 */ 452 @Override 453 public void setLayout(String layout) 454 { 455 this.layout = layout; 456 } 457 458 /** 459 * Convenience method for a template info that 460 * returns the layout template being used. 461 * 462 * @return a string. 463 */ 464 @Override 465 public String getLayoutTemplate() 466 { 467 return getTemplateInfo().getLayoutTemplate(); 468 } 469 470 /** 471 * Modifies the layout template for the screen. This convenience 472 * method allows for a layout to be modified from within a 473 * template. For example; 474 * 475 * $data.setLayoutTemplate("NewLayout.vm") 476 * 477 * @param layout a layout template. 478 */ 479 @Override 480 public void setLayoutTemplate(String layout) 481 { 482 getTemplateInfo().setLayoutTemplate(layout); 483 } 484 485 /** 486 * Whether or not a screen has been defined. 487 * 488 * @return true if a screen has been defined. 489 */ 490 @Override 491 public boolean hasScreen() 492 { 493 return StringUtils.isNotEmpty(this.screen); 494 } 495 496 /** 497 * Gets the screen to execute. 498 * 499 * @return a string. 500 */ 501 @Override 502 public String getScreen() 503 { 504 return hasScreen() ? this.screen : ""; 505 } 506 507 /** 508 * Sets the screen for the request. 509 * 510 * @param screen a string. 511 */ 512 @Override 513 public void setScreen(String screen) 514 { 515 this.screen = screen; 516 } 517 518 /** 519 * Convenience method for a template info that 520 * returns the name of the template being used. 521 * 522 * @return a string. 523 */ 524 @Override 525 public String getScreenTemplate() 526 { 527 return getTemplateInfo().getScreenTemplate(); 528 } 529 530 /** 531 * Sets the screen template for the request. For 532 * example; 533 * 534 * $data.setScreenTemplate("NewScreen.vm") 535 * 536 * @param screen a screen template. 537 */ 538 @Override 539 public void setScreenTemplate(String screen) 540 { 541 getTemplateInfo().setScreenTemplate(screen); 542 } 543 544 /** 545 * Gets the character encoding to use for reading template files. 546 * 547 * @return the template encoding or null if not specified. 548 */ 549 @Override 550 public String getTemplateEncoding() 551 { 552 return templateEncoding; 553 } 554 555 /** 556 * Sets the character encoding to use for reading template files. 557 * 558 * @param encoding the template encoding. 559 */ 560 @Override 561 public void setTemplateEncoding(String encoding) 562 { 563 templateEncoding = encoding; 564 } 565 566 /** 567 * Gets the template info. Creates a new one if needed. 568 * 569 * @return a template info. 570 */ 571 @Override 572 public TemplateInfo getTemplateInfo() 573 { 574 TemplateInfo templateInfo = get(Turbine.class, TemplateInfo.class); 575 576 if (templateInfo == null) 577 { 578 templateInfo = new TemplateInfo(this); 579 get(Turbine.class).put(TemplateInfo.class, templateInfo); 580 } 581 582 return templateInfo; 583 } 584 585 /** 586 * Whether or not a message has been defined. 587 * 588 * @return true if a message has been defined. 589 */ 590 @Override 591 public boolean hasMessage() 592 { 593 StringBuilder message = get(Turbine.class, StringBuilder.class); 594 return message != null && message.length() > 0; 595 } 596 597 /** 598 * Gets the results of an action or another message 599 * to be displayed as a string. 600 * 601 * @return a string. 602 */ 603 @Override 604 public String getMessage() 605 { 606 StringBuilder message = get(Turbine.class, StringBuilder.class); 607 return message == null ? null : message.toString(); 608 } 609 610 /** 611 * Sets the message for the request as a string. 612 * 613 * @param msg a string. 614 */ 615 @Override 616 public void setMessage(String msg) 617 { 618 get(Turbine.class).put(StringBuilder.class, new StringBuilder(msg)); 619 } 620 621 /** 622 * Adds the string to message. If message has prior messages from 623 * other actions or screens, this method can be used to chain them. 624 * 625 * @param msg a string. 626 */ 627 @Override 628 public void addMessage(String msg) 629 { 630 StringBuilder message = get(Turbine.class, StringBuilder.class); 631 if (message == null) 632 { 633 setMessage(msg); 634 } 635 else 636 { 637 message.append(msg); 638 } 639 } 640 641 /** 642 * Gets the results of an action or another message 643 * to be displayed as a string (never null). 644 * 645 * @return a string element. 646 */ 647 @Override 648 public String getMessageAsHTML() 649 { 650 String message = getMessage(); 651 return message == null ? "" : message; 652 } 653 654 /** 655 * Unsets the message for the request. 656 */ 657 @Override 658 public void unsetMessage() 659 { 660 get(Turbine.class).remove(StringBuilder.class); 661 } 662 663 /** 664 * Gets a FormMessages object where all the messages to the 665 * user should be stored. 666 * 667 * @return a FormMessages. 668 */ 669 @Override 670 public FormMessages getMessages() 671 { 672 FormMessages messages = get(Turbine.class, FormMessages.class); 673 if (messages == null) 674 { 675 messages = new FormMessages(); 676 setMessages(messages); 677 } 678 679 return messages; 680 } 681 682 /** 683 * Sets the FormMessages object for the request. 684 * 685 * @param msgs A FormMessages. 686 */ 687 @Override 688 public void setMessages(FormMessages msgs) 689 { 690 get(Turbine.class).put(FormMessages.class, msgs); 691 } 692 693 /** 694 * Gets the title of the page. 695 * 696 * @return a string. 697 */ 698 @Override 699 public String getTitle() 700 { 701 return this.title == null ? "" : this.title; 702 } 703 704 /** 705 * Sets the title of the page. 706 * 707 * @param title a string. 708 */ 709 @Override 710 public void setTitle(String title) 711 { 712 this.title = title; 713 } 714 715 /** 716 * Checks if a user exists in this session. 717 * 718 * @return true if a user exists in this session. 719 */ 720 @Override 721 public boolean userExists() 722 { 723 User user = getUserFromSession(); 724 725 // TODO: Check if this side effect is reasonable 726 get(Turbine.class).put(User.class, user); 727 728 return (user != null); 729 } 730 731 /** 732 * Gets the user. 733 * 734 * @param <T> a type extending {@link User} 735 * 736 * @return a user. 737 */ 738 @Override 739 public <T extends User> T getUser() 740 { 741 @SuppressWarnings("unchecked") 742 T user = (T)get(Turbine.class, User.class); 743 return user; 744 } 745 746 /** 747 * Sets the user. 748 * 749 * @param user a user. 750 */ 751 @Override 752 public void setUser(User user) 753 { 754 log.debug("user set: {}", user::getName); 755 get(Turbine.class).put(User.class, user); 756 } 757 758 /** 759 * Attempts to get the user from the session. If it does 760 * not exist, it returns null. 761 * 762 * @return a user. 763 */ 764 @Override 765 public <T extends User> T getUserFromSession() 766 { 767 return getUserFromSession(getSession()); 768 } 769 770 /** 771 * Allows one to invalidate the user in the default session. 772 * 773 * @return true if user was invalidated. 774 */ 775 @Override 776 public boolean removeUserFromSession() 777 { 778 return removeUserFromSession(getSession()); 779 } 780 781 /** 782 * Checks to see if out is set. 783 * 784 * @return true if out is set. 785 * @deprecated no replacement planned, response writer will not be cached 786 */ 787 @Override 788 @Deprecated 789 public boolean isOutSet() 790 { 791 return outSet; 792 } 793 794 /** 795 * Gets the print writer. First time calling this 796 * will set the print writer via the response. 797 * 798 * @return a print writer. 799 * @throws IOException on failure getting the PrintWriter 800 */ 801 @Override 802 public PrintWriter getOut() 803 throws IOException 804 { 805 // Check to see if null first. 806 if (this.out == null) 807 { 808 setOut(getResponse().getWriter()); 809 } 810 outSet = true; 811 return this.out; 812 } 813 814 /** 815 * Declares that output will be direct to the response stream, 816 * even though getOut() may never be called. Useful for response 817 * mechanisms that may call res.getWriter() themselves 818 * (such as JSP.) 819 */ 820 @Override 821 public void declareDirectResponse() 822 { 823 outSet = true; 824 } 825 826 /** 827 * Gets the locale. If it has not already been defined with 828 * setLocale(), then properties named "locale.default.lang" 829 * and "locale.default.country" are checked from the Resource 830 * Service and the corresponding locale is returned. If these 831 * properties are undefined, JVM's default locale is returned. 832 * 833 * @return the locale. 834 */ 835 @Override 836 public Locale getLocale() 837 { 838 Locale locale = get(Turbine.class, Locale.class); 839 if (locale == null) 840 { 841 locale = LocaleUtils.getDefaultLocale(); 842 } 843 return locale; 844 } 845 846 /** 847 * Sets the locale. 848 * 849 * @param locale the new locale. 850 */ 851 @Override 852 public void setLocale(Locale locale) 853 { 854 get(Turbine.class).put(Locale.class, locale); 855 856 // propagate the locale to the parsers 857 ParameterParser parameters = get(Turbine.class, ParameterParser.class); 858 CookieParser cookies = get(Turbine.class, CookieParser.class); 859 860 if (parameters != null) 861 { 862 parameters.setLocale(locale); 863 } 864 865 if (cookies != null) 866 { 867 cookies.setLocale(locale); 868 } 869 } 870 871 /** 872 * Gets the charset. If it has not already been defined with 873 * setCharSet(), then a property named "locale.default.charset" 874 * is checked from the Resource Service and returned. If this 875 * property is undefined, the default charset of the locale 876 * is returned. If the locale is undefined, null is returned. 877 * 878 * @return the name of the charset or null. 879 */ 880 @Override 881 public String getCharSet() 882 { 883 return getCharset().name(); 884 } 885 886 /** 887 * Sets the charset. 888 * 889 * @param charSet the name of the new charset. 890 */ 891 @Override 892 public void setCharSet(String charSet) 893 { 894 setCharset(Charset.forName(charSet)); 895 } 896 897 /** 898 * Gets the charset. If it has not already been defined with 899 * setCharSet(), then a property named "locale.default.charset" 900 * is checked from the Resource Service and returned. If this 901 * property is undefined, the default charset of the locale 902 * is returned. If the locale is undefined, null is returned. 903 * 904 * @return the charset or null. 905 */ 906 @Override 907 public Charset getCharset() 908 { 909 log.debug("getCharset()"); 910 911 if (charSet == null) 912 { 913 log.debug("Charset was null!"); 914 charSet = LocaleUtils.getDefaultCharset(); 915 } 916 917 return charSet; 918 } 919 920 /** 921 * Sets the charset. 922 * 923 * @param charSet the new charset. 924 */ 925 @Override 926 public void setCharset(Charset charSet) 927 { 928 log.debug("setCharset({})", charSet); 929 this.charSet = charSet; 930 } 931 932 /** 933 * Gets the HTTP content type to return. If a charset 934 * has been specified, it is included in the content type. 935 * If the charset has not been specified and the main type 936 * of the content type is "text", the default charset is 937 * included. If the default charset is undefined, but the 938 * default locale is defined and it is not the US locale, 939 * a locale specific charset is included. 940 * 941 * @return the content type or an empty string. 942 */ 943 @Override 944 public String getContentType() 945 { 946 if (StringUtils.isNotEmpty(contentType)) 947 { 948 if (charSet == null) 949 { 950 if (contentType.startsWith("text/")) 951 { 952 return contentType + "; charset=" + LocaleUtils.getDefaultCharset(); 953 } 954 955 return contentType; 956 } 957 else 958 { 959 return contentType + "; charset=" + charSet.name(); 960 } 961 } 962 963 return ""; 964 } 965 966 /** 967 * Sets the HTTP content type to return. 968 * 969 * @param contentType a string. 970 */ 971 @Override 972 public void setContentType(String contentType) 973 { 974 this.contentType = contentType; 975 } 976 977 /** 978 * Gets the redirect URI. If this is set, also make sure to set 979 * the status code to 302. 980 * 981 * @return a string, "" if null. 982 */ 983 @Override 984 public String getRedirectURI() 985 { 986 return (this.redirectURI == null ? "" : redirectURI); 987 } 988 989 /** 990 * Sets the redirect uri. If this is set, also make sure to set 991 * the status code to 302. 992 * 993 * @param ruri a string. 994 */ 995 @Override 996 public void setRedirectURI(String ruri) 997 { 998 this.redirectURI = ruri; 999 } 1000 1001 /** 1002 * Gets the HTTP status code to return. 1003 * 1004 * @return the status. 1005 */ 1006 @Override 1007 public int getStatusCode() 1008 { 1009 return statusCode; 1010 } 1011 1012 /** 1013 * Sets the HTTP status code to return. 1014 * 1015 * @param statusCode the status. 1016 */ 1017 @Override 1018 public void setStatusCode(int statusCode) 1019 { 1020 this.statusCode = statusCode; 1021 } 1022 1023 /** 1024 * Gets an array of system errors. 1025 * 1026 * @return a SystemError[]. 1027 */ 1028 @Override 1029 public SystemError[] getSystemErrors() 1030 { 1031 SystemError[] result = new SystemError[errors.size()]; 1032 errors.toArray(result); 1033 return result; 1034 } 1035 1036 /** 1037 * Adds a critical system error. 1038 * 1039 * @param err a system error. 1040 */ 1041 @Override 1042 public void setSystemError(SystemError err) 1043 { 1044 this.errors.add(err); 1045 } 1046 1047 /** 1048 * Gets JNDI Contexts. 1049 * 1050 * @return a hashmap. 1051 */ 1052 @Override 1053 public Map<String, Context> getJNDIContexts() 1054 { 1055 if (jndiContexts == null) 1056 { 1057 jndiContexts = new HashMap<>(); 1058 } 1059 return jndiContexts; 1060 } 1061 1062 /** 1063 * Sets JNDI Contexts. 1064 * 1065 * @param contexts a hashmap. 1066 */ 1067 @Override 1068 public void setJNDIContexts(Map<String, Context> contexts) 1069 { 1070 this.jndiContexts = contexts; 1071 } 1072 1073 /** 1074 * Gets the cached server scheme. 1075 * 1076 * @return a string. 1077 */ 1078 @Override 1079 public String getServerScheme() 1080 { 1081 return getServerData().getServerScheme(); 1082 } 1083 1084 /** 1085 * Gets the cached server name. 1086 * 1087 * @return a string. 1088 */ 1089 @Override 1090 public String getServerName() 1091 { 1092 return getServerData().getServerName(); 1093 } 1094 1095 /** 1096 * Gets the cached server port. 1097 * 1098 * @return an int. 1099 */ 1100 @Override 1101 public int getServerPort() 1102 { 1103 return getServerData().getServerPort(); 1104 } 1105 1106 /** 1107 * Gets the cached context path. 1108 * 1109 * @return a string. 1110 */ 1111 @Override 1112 public String getContextPath() 1113 { 1114 return getServerData().getContextPath(); 1115 } 1116 1117 /** 1118 * Gets the cached script name. 1119 * 1120 * @return a string. 1121 */ 1122 @Override 1123 public String getScriptName() 1124 { 1125 return getServerData().getScriptName(); 1126 } 1127 1128 /** 1129 * Gets the server data ofy the request. 1130 * 1131 * @return server data. 1132 */ 1133 @Override 1134 public ServerData getServerData() 1135 { 1136 return get(Turbine.class, ServerData.class); 1137 } 1138 1139 /** 1140 * Gets the IP address of the client that sent the request. 1141 * 1142 * @return a string. 1143 */ 1144 @Override 1145 public String getRemoteAddr() 1146 { 1147 if (this.remoteAddr == null) 1148 { 1149 this.remoteAddr = this.getRequest().getRemoteAddr(); 1150 } 1151 1152 return this.remoteAddr; 1153 } 1154 1155 /** 1156 * Gets the qualified name of the client that sent the request. 1157 * 1158 * @return a string. 1159 */ 1160 @Override 1161 public String getRemoteHost() 1162 { 1163 if (this.remoteHost == null) 1164 { 1165 this.remoteHost = this.getRequest().getRemoteHost(); 1166 } 1167 1168 return this.remoteHost; 1169 } 1170 1171 /** 1172 * Get the user agent for the request. The semantics here 1173 * are muddled because RunData caches the value after the 1174 * first invocation. This is different e.g. from getCharSet(). 1175 * 1176 * @return a string. 1177 */ 1178 @Override 1179 public String getUserAgent() 1180 { 1181 if (StringUtils.isEmpty(userAgent)) 1182 { 1183 userAgent = this.getRequest().getHeader("User-Agent"); 1184 } 1185 1186 return userAgent; 1187 } 1188 1189 /** 1190 * Pulls a user object from the session and increments the access 1191 * counter and sets the last access date for the object. 1192 */ 1193 @Override 1194 public void populate() 1195 { 1196 User user = getUserFromSession(); 1197 get(Turbine.class).put(User.class, user); 1198 1199 if (user != null) 1200 { 1201 user.setLastAccessDate(); 1202 user.incrementAccessCounter(); 1203 user.incrementAccessCounterForSession(); 1204 } 1205 } 1206 1207 /** 1208 * Saves a user object into the session. 1209 */ 1210 @Override 1211 public void save() 1212 { 1213 getSession().setAttribute(User.SESSION_KEY, getUser()); 1214 } 1215 1216 /** 1217 * Gets the stack trace if set. 1218 * 1219 * @return the stack trace. 1220 */ 1221 @Override 1222 public String getStackTrace() 1223 { 1224 return stackTrace; 1225 } 1226 1227 /** 1228 * Gets the stack trace exception if set. 1229 * 1230 * @return the stack exception. 1231 */ 1232 @Override 1233 public Throwable getStackTraceException() 1234 { 1235 return stackTraceException; 1236 } 1237 1238 /** 1239 * Sets the stack trace. 1240 * 1241 * @param trace the stack trace. 1242 * @param exp the exception. 1243 */ 1244 @Override 1245 public void setStackTrace(String trace, Throwable exp) 1246 { 1247 stackTrace = trace; 1248 stackTraceException = exp; 1249 } 1250 1251 /** 1252 * Sets a name/value pair in an internal Map that is accessible from the 1253 * Error screen. This is a good way to get debugging information 1254 * when an exception is thrown. 1255 * 1256 * @param name name of the variable 1257 * @param value value of the variable. 1258 */ 1259 @Override 1260 public void setDebugVariable(String name, Object value) 1261 { 1262 this.debugVariables.put(name, value); 1263 } 1264 1265 /** 1266 * Gets a Map of debug variables. 1267 * 1268 * @return a Map of debug variables. 1269 */ 1270 @Override 1271 public Map<String, Object> getDebugVariables() 1272 { 1273 return this.debugVariables; 1274 } 1275 1276 // ********************************************** 1277 // Implementation of the TurbineRunData interface 1278 // ********************************************** 1279 1280 /** 1281 * Gets the parameter parser without parsing the parameters. 1282 * 1283 * @return the parameter parser. 1284 * TODO Does this method make sense? Pulling the parameter out of 1285 * the run data object before setting a request (which happens 1286 * only in getParameters() leads to the Parameter parser having 1287 * no object and thus the default or even an undefined encoding 1288 * instead of the actual request character encoding). 1289 */ 1290 @Override 1291 public ParameterParser getParameterParser() 1292 { 1293 return get(Turbine.class, ParameterParser.class); 1294 } 1295 1296 /** 1297 * Gets the cookie parser without parsing the cookies. 1298 * 1299 * @return the cookie parser. 1300 */ 1301 @Override 1302 public CookieParser getCookieParser() 1303 { 1304 return get(Turbine.class, CookieParser.class); 1305 } 1306 1307 // ******************** 1308 // Miscellaneous setters 1309 // ******************** 1310 1311 /** 1312 * Sets the print writer. 1313 * 1314 * @param out a print writer. 1315 * @deprecated no replacement planned, response writer will not be cached 1316 */ 1317 @Deprecated 1318 protected void setOut(PrintWriter out) 1319 { 1320 this.out = out; 1321 } 1322 1323 /** 1324 * Sets the cached server scheme that is stored in the server data. 1325 * 1326 * @param serverScheme a string. 1327 */ 1328 protected void setServerScheme(String serverScheme) 1329 { 1330 getServerData().setServerScheme(serverScheme); 1331 } 1332 1333 /** 1334 * Sets the cached server same that is stored in the server data. 1335 * 1336 * @param serverName a string. 1337 */ 1338 protected void setServerName(String serverName) 1339 { 1340 getServerData().setServerName(serverName); 1341 } 1342 1343 /** 1344 * Sets the cached server port that is stored in the server data. 1345 * 1346 * @param port an int. 1347 */ 1348 protected void setServerPort(int port) 1349 { 1350 getServerData().setServerPort(port); 1351 } 1352 1353 /** 1354 * Sets the cached context path that is stored in the server data. 1355 * 1356 * @param contextPath a string. 1357 */ 1358 protected void setContextPath(String contextPath) 1359 { 1360 getServerData().setContextPath(contextPath); 1361 } 1362 1363 /** 1364 * Sets the cached script name that is stored in the server data. 1365 * 1366 * @param scriptName a string. 1367 */ 1368 protected void setScriptName(String scriptName) 1369 { 1370 getServerData().setScriptName(scriptName); 1371 } 1372 1373 /** 1374 * Checks whether the object is disposed. 1375 * 1376 * @return true, if the object is disposed. 1377 */ 1378 @Override 1379 public boolean isDisposed() 1380 { 1381 return disposed; 1382 } 1383 1384}