1 package org.apache.turbine.services.rundata;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.IOException;
23 import java.io.PrintWriter;
24
25 import java.util.ArrayList;
26 import java.util.HashMap;
27 import java.util.List;
28 import java.util.Locale;
29 import java.util.Map;
30
31 import javax.servlet.ServletConfig;
32 import javax.servlet.ServletContext;
33 import javax.servlet.http.HttpServletRequest;
34 import javax.servlet.http.HttpServletResponse;
35 import javax.servlet.http.HttpSession;
36
37 import org.apache.commons.lang.StringUtils;
38
39 import org.apache.commons.logging.Log;
40 import org.apache.commons.logging.LogFactory;
41
42 import org.apache.ecs.Document;
43 import org.apache.ecs.Element;
44 import org.apache.ecs.StringElement;
45
46 import org.apache.turbine.Turbine;
47 import org.apache.turbine.TurbineConstants;
48 import org.apache.turbine.om.security.User;
49 import org.apache.turbine.services.mimetype.TurbineMimeTypes;
50 import org.apache.turbine.services.template.TurbineTemplate;
51 import org.apache.turbine.util.FormMessages;
52 import org.apache.turbine.util.ServerData;
53 import org.apache.turbine.util.SystemError;
54 import org.apache.turbine.util.parser.CookieParser;
55 import org.apache.turbine.util.parser.ParameterParser;
56 import org.apache.turbine.util.pool.RecyclableSupport;
57 import org.apache.turbine.util.security.AccessControlList;
58 import org.apache.turbine.util.template.TemplateInfo;
59
60 /***
61 * DefaultTurbineRunData is the default implementation of the
62 * TurbineRunData interface, which is distributed by the Turbine
63 * RunData service, if another implementation is not defined in
64 * the default or specified RunData configuration.
65 * TurbineRunData is an extension to RunData, which
66 * is an interface to run-rime information that is passed
67 * within Turbine. This provides the threading mechanism for the
68 * entire system because multiple requests can potentially come in
69 * at the same time. Thus, there is only one RunData implementation
70 * for each request that is being serviced.
71 *
72 * <p>DefaultTurbineRunData implements the Recyclable interface making
73 * it possible to pool its instances for recycling.
74 *
75 * @author <a href="mailto:ilkka.priha@simsoft.fi">Ilkka Priha</a>
76 * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
77 * @author <a href="mailto:bhoeneis@ee.ethz.ch">Bernie Hoeneisen</a>
78 * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
79 * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
80 * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
81 * @version $Id: DefaultTurbineRunData.java 645797 2008-04-08 08:51:24Z tv $
82 */
83 public class DefaultTurbineRunData
84 extends RecyclableSupport
85 implements TurbineRunData
86 {
87 /*** The default locale. */
88 private static Locale defaultLocale = null;
89
90 /*** The default charset. */
91 private static String defaultCharSet = null;
92
93 /*** A reference to the GET/POST data parser. */
94 private ParameterParser parameters;
95
96 /*** A reference to a cookie parser. */
97 public CookieParser cookies;
98
99 /*** The servlet request interface. */
100 private HttpServletRequest req;
101
102 /*** The servlet response interface. */
103 private HttpServletResponse res;
104
105 /*** The servlet configuration. */
106 private ServletConfig config;
107
108 /***
109 * The servlet context information.
110 * Note that this is from the "Turbine" Servlet context.
111 */
112 private ServletContext servletContext;
113
114 /*** The access control list. */
115 private AccessControlList acl;
116
117 /*** Determines if there is information in the document or not. */
118 private boolean pageSet;
119
120 /*** This creates an ECS Document. */
121 private Document page;
122
123 /*** Cached action name to execute for this request. */
124 private String action;
125
126 /*** This is the layout that the page will use to render the screen. */
127 private String layout;
128
129 /*** Cached screen name to execute for this request. */
130 private String screen;
131
132 /*** The character encoding of template files. */
133 private String templateEncoding;
134
135 /*** Information used by a Template system (such as Velocity/JSP). */
136 private TemplateInfo templateInfo;
137
138 /*** This is where output messages from actions should go. */
139 private StringElement message;
140
141 /***
142 * This is a dedicated message class where output messages from
143 * actions should go.
144 */
145 private FormMessages messages;
146
147 /*** The user object. */
148 private User user;
149
150 /*** This is what will build the <title></title> of the document. */
151 private String title;
152
153 /*** Determines if there is information in the outputstream or not. */
154 private boolean outSet;
155
156 /***
157 * Cache the output stream because it can be used in many
158 * different places.
159 */
160 private PrintWriter out;
161
162 /*** The locale. */
163 private Locale locale;
164
165 /*** The HTTP charset. */
166 private String charSet;
167
168 /*** The HTTP content type to return. */
169 private String contentType = "text/html";
170
171 /*** If this is set, also set the status code to 302. */
172 private String redirectURI;
173
174 /*** The HTTP status code to return. */
175 private int statusCode = HttpServletResponse.SC_OK;
176
177 /*** This is a List to hold critical system errors. */
178 private List errors = new ArrayList();
179
180 /*** JNDI Contexts. */
181 private Map jndiContexts;
182
183 /*** Holds ServerData (basic properties) about this RunData object. */
184 private ServerData serverData;
185
186 /*** @see #getRemoteAddr() */
187 private String remoteAddr;
188
189 /*** @see #getRemoteHost() */
190 private String remoteHost;
191
192 /*** @see #getUserAgent() */
193 private String userAgent;
194
195 /*** A holder for stack trace. */
196 private String stackTrace;
197
198 /*** A holder ofr stack trace exception. */
199 private Throwable stackTraceException;
200
201 /***
202 * Put things here and they will be shown on the default Error
203 * screen. This is great for debugging variable values when an
204 * exception is thrown.
205 */
206 private Map debugVariables = new HashMap();
207
208 /*** Logging */
209 private static Log log = LogFactory.getLog(DefaultTurbineRunData.class);
210
211 /***
212 * Attempts to get the User object from the session. If it does
213 * not exist, it returns null.
214 *
215 * @param session An HttpSession.
216 * @return A User.
217 */
218 public static User getUserFromSession(HttpSession session)
219 {
220 try
221 {
222 return (User) session.getAttribute(User.SESSION_KEY);
223 }
224 catch (ClassCastException e)
225 {
226 return null;
227 }
228 }
229
230 /***
231 * Allows one to invalidate the user in a session.
232 *
233 * @param session An HttpSession.
234 * @return True if user was invalidated.
235 */
236 public static boolean removeUserFromSession(HttpSession session)
237 {
238 try
239 {
240 session.removeAttribute(User.SESSION_KEY);
241 }
242 catch (Exception e)
243 {
244 return false;
245 }
246 return true;
247 }
248
249 /***
250 * Gets the default locale defined by properties named
251 * "locale.default.lang" and "locale.default.country".
252 *
253 * This changed from earlier Turbine versions that you can
254 * rely on getDefaultLocale() to never return null.
255 *
256 * @return A Locale object.
257 */
258 protected static Locale getDefaultLocale()
259 {
260 if (defaultLocale == null)
261 {
262
263 String lang = Turbine.getConfiguration()
264 .getString(TurbineConstants.LOCALE_DEFAULT_LANGUAGE_KEY,
265 TurbineConstants.LOCALE_DEFAULT_LANGUAGE_DEFAULT);
266
267 String country = Turbine.getConfiguration()
268 .getString(TurbineConstants.LOCALE_DEFAULT_COUNTRY_KEY,
269 TurbineConstants.LOCALE_DEFAULT_COUNTRY_DEFAULT);
270
271
272
273 defaultLocale = new Locale(lang, country);
274 }
275 return defaultLocale;
276 }
277
278 /***
279 * Gets the default charset defined by a property named
280 * "locale.default.charset" or by the specified locale.
281 * If the specified locale is null, the default locale is applied.
282 *
283 * @return the name of the default charset or null.
284 */
285 protected String getDefaultCharSet()
286 {
287 log.debug("getDefaultCharSet()");
288
289 if (defaultCharSet == null)
290 {
291
292 defaultCharSet = Turbine.getConfiguration()
293 .getString(TurbineConstants.LOCALE_DEFAULT_CHARSET_KEY,
294 TurbineConstants.LOCALE_DEFAULT_CHARSET_DEFAULT);
295 log.debug("defaultCharSet = " + defaultCharSet + " (From Properties)");
296 }
297
298 String charset = defaultCharSet;
299
300 if (StringUtils.isEmpty(charset))
301 {
302 log.debug("charset is empty!");
303
304 Locale locale = this.locale;
305 if (locale == null)
306 {
307 locale = getDefaultLocale();
308 log.debug("Locale was null, is now " + locale + " (from getDefaultLocale())");
309 }
310
311 log.debug("Locale is " + locale);
312
313 if (!locale.equals(Locale.US))
314 {
315 log.debug("We have US Locale!");
316 charset = TurbineMimeTypes.getCharSet(locale);
317
318 log.debug("Charset now " + charset);
319 }
320 }
321
322 log.debug("Returning default Charset of " + charset);
323 return charset;
324 }
325
326 /***
327 * Constructs a run data object.
328 */
329 public DefaultTurbineRunData()
330 {
331 super();
332 }
333
334 /***
335 * Recycles a run data object.
336 */
337 public void recycle()
338 {
339 super.recycle();
340 }
341
342 /***
343 * Disposes a run data object.
344 */
345 public void dispose()
346 {
347 parameters = null;
348 cookies = null;
349 req = null;
350 res = null;
351 config = null;
352 servletContext = null;
353 acl = null;
354 pageSet = false;
355 page = null;
356 action = null;
357 layout = null;
358 screen = null;
359 templateEncoding = null;
360 templateInfo = null;
361 message = null;
362 messages = null;
363 user = null;
364 title = null;
365 outSet = false;
366 out = null;
367 locale = null;
368 charSet = null;
369 contentType = "text/html";
370 redirectURI = null;
371 statusCode = HttpServletResponse.SC_OK;
372 errors.clear();
373 jndiContexts = null;
374 serverData = null;
375 remoteAddr = null;
376 remoteHost = null;
377 userAgent = null;
378 stackTrace = null;
379 stackTraceException = null;
380 debugVariables.clear();
381
382 super.dispose();
383 }
384
385
386
387
388
389 /***
390 * Gets the parameters.
391 *
392 * @return a parameter parser.
393 */
394 public ParameterParser getParameters()
395 {
396
397 if ((this.parameters != null) &&
398 (this.parameters.getRequest() != this.req))
399 {
400 this.parameters.setRequest(this.req);
401 }
402 return this.parameters;
403 }
404
405 /***
406 * Gets the cookies.
407 *
408 * @return a cookie parser.
409 */
410 public CookieParser getCookies()
411 {
412
413 if ((this.cookies != null) &&
414 (this.cookies.getRequest() != getRequest()))
415 {
416
417
418
419
420
421
422
423 this.cookies.setRunData(this);
424 }
425 return this.cookies;
426 }
427
428 /***
429 * Gets the servlet request.
430 *
431 * @return the request.
432 */
433 public HttpServletRequest getRequest()
434 {
435 return this.req;
436 }
437
438 /***
439 * Gets the servlet response.
440 *
441 * @return the response.
442 */
443 public HttpServletResponse getResponse()
444 {
445 return this.res;
446 }
447
448 /***
449 * Gets the servlet session information.
450 *
451 * @return the session.
452 */
453 public HttpSession getSession()
454 {
455 return getRequest().getSession();
456 }
457
458 /***
459 * Gets the servlet configuration used during servlet init.
460 *
461 * @return the configuration.
462 */
463 public ServletConfig getServletConfig()
464 {
465 return this.config;
466 }
467
468 /***
469 * Gets the servlet context used during servlet init.
470 *
471 * @return the context.
472 */
473 public ServletContext getServletContext()
474 {
475 return this.servletContext;
476 }
477
478 /***
479 * Gets the access control list.
480 *
481 * @return the access control list.
482 */
483 public AccessControlList getACL()
484 {
485 return acl;
486 }
487
488 /***
489 * Sets the access control list.
490 *
491 * @param acl an access control list.
492 */
493 public void setACL(AccessControlList acl)
494 {
495 this.acl = acl;
496 }
497
498 /***
499 * Checks to see if the page is set.
500 *
501 * @return true if the page is set.
502 * @deprecated no replacement planned, ECS is no longer a requirement
503 */
504 public boolean isPageSet()
505 {
506 return pageSet;
507 }
508
509 /***
510 * Gets the page.
511 *
512 * @return a document.
513 * @deprecated no replacement planned, ECS is no longer a requirement
514 */
515 public Document getPage()
516 {
517 pageSet = true;
518 if (this.page == null)
519 this.page = new Document();
520 return this.page;
521 }
522
523 /***
524 * Whether or not an action has been defined.
525 *
526 * @return true if an action has been defined.
527 */
528 public boolean hasAction()
529 {
530 return (StringUtils.isNotEmpty(this.action)
531 && !this.action.equalsIgnoreCase("null"));
532 }
533
534 /***
535 * Gets the action. It returns an empty string if null so
536 * that it is easy to do conditionals on it based on the
537 * equalsIgnoreCase() method.
538 *
539 * @return a string, "" if null.
540 */
541 public String getAction()
542 {
543 return (hasAction() ? this.action : "");
544 }
545
546 /***
547 * Sets the action for the request.
548 *
549 * @param action a atring.
550 */
551 public void setAction(String action)
552 {
553 this.action = action;
554 }
555
556 /***
557 * If the Layout has not been defined by the screen then set the
558 * layout to be "DefaultLayout". The screen object can also
559 * override this method to provide intelligent determination of
560 * the Layout to execute. You can also define that logic here as
561 * well if you want it to apply on a global scale. For example,
562 * if you wanted to allow someone to define layout "preferences"
563 * where they could dynamicially change the layout for the entire
564 * site.
565 *
566 * @return a string.
567 */
568
569 public String getLayout()
570 {
571 if (this.layout == null)
572 {
573
574
575
576
577
578 layout = TurbineTemplate.getDefaultLayoutName(this);
579
580 if (layout == null)
581 {
582 layout = "DefaultLayout";
583 }
584 }
585
586 return this.layout;
587 }
588
589 /***
590 * Set the layout for the request.
591 *
592 * @param layout a string.
593 */
594 public void setLayout(String layout)
595 {
596 this.layout = layout;
597 }
598
599 /***
600 * Convenience method for a template info that
601 * returns the layout template being used.
602 *
603 * @return a string.
604 */
605 public String getLayoutTemplate()
606 {
607 return getTemplateInfo().getLayoutTemplate();
608 }
609
610 /***
611 * Modifies the layout template for the screen. This convenience
612 * method allows for a layout to be modified from within a
613 * template. For example;
614 *
615 * $data.setLayoutTemplate("NewLayout.vm")
616 *
617 * @param layout a layout template.
618 */
619 public void setLayoutTemplate(String layout)
620 {
621 getTemplateInfo().setLayoutTemplate(layout);
622 }
623
624 /***
625 * Whether or not a screen has been defined.
626 *
627 * @return true if a screen has been defined.
628 */
629 public boolean hasScreen()
630 {
631 return StringUtils.isNotEmpty(this.screen);
632 }
633
634 /***
635 * Gets the screen to execute.
636 *
637 * @return a string.
638 */
639 public String getScreen()
640 {
641 return (hasScreen() ? this.screen : "");
642 }
643
644 /***
645 * Sets the screen for the request.
646 *
647 * @param screen a string.
648 */
649 public void setScreen(String screen)
650 {
651 this.screen = screen;
652 }
653
654 /***
655 * Convenience method for a template info that
656 * returns the name of the template being used.
657 *
658 * @return a string.
659 */
660 public String getScreenTemplate()
661 {
662 return getTemplateInfo().getScreenTemplate();
663 }
664
665 /***
666 * Sets the screen template for the request. For
667 * example;
668 *
669 * $data.setScreenTemplate("NewScreen.vm")
670 *
671 * @param screen a screen template.
672 */
673 public void setScreenTemplate(String screen)
674 {
675 getTemplateInfo().setScreenTemplate(screen);
676 }
677
678 /***
679 * Gets the character encoding to use for reading template files.
680 *
681 * @return the template encoding or null if not specified.
682 */
683 public String getTemplateEncoding()
684 {
685 return templateEncoding;
686 }
687
688 /***
689 * Sets the character encoding to use for reading template files.
690 *
691 * @param encoding the template encoding.
692 */
693 public void setTemplateEncoding(String encoding)
694 {
695 templateEncoding = encoding;
696 }
697
698 /***
699 * Gets the template info. Creates a new one if needed.
700 *
701 * @return a template info.
702 */
703 public TemplateInfo getTemplateInfo()
704 {
705 if (templateInfo == null)
706 {
707 templateInfo = new TemplateInfo(this);
708 }
709 return templateInfo;
710 }
711
712 /***
713 * Whether or not a message has been defined.
714 *
715 * @return true if a message has been defined.
716 */
717 public boolean hasMessage()
718 {
719 return (this.message != null)
720 && StringUtils.isNotEmpty(this.message.toString());
721 }
722
723 /***
724 * Gets the results of an action or another message
725 * to be displayed as a string.
726 *
727 * @return a string.
728 */
729 public String getMessage()
730 {
731 return (this.message == null ? null : this.message.toString());
732 }
733
734 /***
735 * Sets the message for the request as a string.
736 *
737 * @param msg a string.
738 */
739 public void setMessage(String msg)
740 {
741 this.message = new StringElement(msg);
742 }
743
744 /***
745 * Adds the string to message. If message has prior messages from
746 * other actions or screens, this method can be used to chain them.
747 *
748 * @param msg a string.
749 */
750 public void addMessage(String msg)
751 {
752 addMessage(new StringElement(msg));
753 }
754
755 /***
756 * Gets the results of an action or another message
757 * to be displayed as an ECS string element.
758 *
759 * @return a string element.
760 */
761 public StringElement getMessageAsHTML()
762 {
763 return this.message;
764 }
765
766 /***
767 * Sets the message for the request as an ECS element.
768 *
769 * @param msg an element.
770 */
771 public void setMessage(Element msg)
772 {
773 this.message = new StringElement(msg);
774 }
775
776 /***
777 * Adds the ECS element to message. If message has prior messages from
778 * other actions or screens, this method can be used to chain them.
779 *
780 * @param msg an element.
781 */
782 public void addMessage(Element msg)
783 {
784 if (msg != null)
785 {
786 if (message != null)
787 {
788 message.addElement(msg);
789 }
790 else
791 {
792 message = new StringElement(msg);
793 }
794 }
795 }
796
797 /***
798 * Unsets the message for the request.
799 */
800 public void unsetMessage()
801 {
802 this.message = null;
803 }
804
805 /***
806 * Gets a FormMessages object where all the messages to the
807 * user should be stored.
808 *
809 * @return a FormMessages.
810 */
811 public FormMessages getMessages()
812 {
813 if (this.messages == null)
814 {
815 this.messages = new FormMessages();
816 }
817 return this.messages;
818 }
819
820 /***
821 * Sets the FormMessages object for the request.
822 *
823 * @param msgs A FormMessages.
824 */
825 public void setMessages(FormMessages msgs)
826 {
827 this.messages = msgs;
828 }
829
830 /***
831 * Gets the title of the page.
832 *
833 * @return a string.
834 */
835 public String getTitle()
836 {
837 return (this.title == null ? "" : this.title);
838 }
839
840 /***
841 * Sets the title of the page.
842 *
843 * @param title a string.
844 */
845 public void setTitle(String title)
846 {
847 this.title = title;
848 }
849
850 /***
851 * Checks if a user exists in this session.
852 *
853 * @return true if a user exists in this session.
854 */
855 public boolean userExists()
856 {
857 user = getUserFromSession();
858 return (user != null);
859 }
860
861 /***
862 * Gets the user.
863 *
864 * @return a user.
865 */
866 public User getUser()
867 {
868 return this.user;
869 }
870
871 /***
872 * Sets the user.
873 *
874 * @param user a user.
875 */
876 public void setUser(User user)
877 {
878 log.debug("user set: " + user.getName());
879 this.user = user;
880 }
881
882 /***
883 * Attempts to get the user from the session. If it does
884 * not exist, it returns null.
885 *
886 * @return a user.
887 */
888 public User getUserFromSession()
889 {
890 return getUserFromSession(getSession());
891 }
892
893 /***
894 * Allows one to invalidate the user in the default session.
895 *
896 * @return true if user was invalidated.
897 */
898 public boolean removeUserFromSession()
899 {
900 return removeUserFromSession(getSession());
901 }
902
903 /***
904 * Checks to see if out is set.
905 *
906 * @return true if out is set.
907 * @deprecated no replacement planned, response writer will not be cached
908 */
909 public boolean isOutSet()
910 {
911 return outSet;
912 }
913
914 /***
915 * Gets the print writer. First time calling this
916 * will set the print writer via the response.
917 *
918 * @return a print writer.
919 * @throws IOException
920 * @deprecated no replacement planned, response writer will not be cached
921 */
922 public PrintWriter getOut()
923 throws IOException
924 {
925
926 if (this.out == null)
927 {
928 setOut(res.getWriter());
929 }
930 pageSet = false;
931 outSet = true;
932 return this.out;
933 }
934
935 /***
936 * Declares that output will be direct to the response stream,
937 * even though getOut() may never be called. Useful for response
938 * mechanisms that may call res.getWriter() themselves
939 * (such as JSP.)
940 */
941 public void declareDirectResponse()
942 {
943 outSet = true;
944 pageSet = false;
945 }
946
947 /***
948 * Gets the locale. If it has not already been defined with
949 * setLocale(), then properties named "locale.default.lang"
950 * and "locale.default.country" are checked from the Resource
951 * Service and the corresponding locale is returned. If these
952 * properties are undefined, JVM's default locale is returned.
953 *
954 * @return the locale.
955 */
956 public Locale getLocale()
957 {
958 Locale locale = this.locale;
959 if (locale == null)
960 {
961 locale = getDefaultLocale();
962 }
963 return locale;
964 }
965
966 /***
967 * Sets the locale.
968 *
969 * @param locale the new locale.
970 */
971 public void setLocale(Locale locale)
972 {
973 this.locale = locale;
974
975
976 if (this.parameters != null)
977 {
978 parameters.setLocale(locale);
979 }
980
981 if (this.cookies != null)
982 {
983 cookies.setLocale(locale);
984 }
985 }
986
987 /***
988 * Gets the charset. If it has not already been defined with
989 * setCharSet(), then a property named "locale.default.charset"
990 * is checked from the Resource Service and returned. If this
991 * property is undefined, the default charset of the locale
992 * is returned. If the locale is undefined, null is returned.
993 *
994 * @return the name of the charset or null.
995 */
996 public String getCharSet()
997 {
998 log.debug("getCharSet()");
999
1000 if (StringUtils.isEmpty(charSet))
1001 {
1002 log.debug("Charset was null!");
1003 return getDefaultCharSet();
1004 }
1005 else
1006 {
1007 return charSet;
1008 }
1009 }
1010
1011 /***
1012 * Sets the charset.
1013 *
1014 * @param charSet the name of the new charset.
1015 */
1016 public void setCharSet(String charSet)
1017 {
1018 log.debug("setCharSet(" + charSet + ")");
1019 this.charSet = charSet;
1020 }
1021
1022 /***
1023 * Gets the HTTP content type to return. If a charset
1024 * has been specified, it is included in the content type.
1025 * If the charset has not been specified and the main type
1026 * of the content type is "text", the default charset is
1027 * included. If the default charset is undefined, but the
1028 * default locale is defined and it is not the US locale,
1029 * a locale specific charset is included.
1030 *
1031 * @return the content type or an empty string.
1032 */
1033 public String getContentType()
1034 {
1035 if (StringUtils.isNotEmpty(contentType))
1036 {
1037 if (StringUtils.isEmpty(charSet))
1038 {
1039 if (contentType.startsWith("text/"))
1040 {
1041 return contentType + "; charset=" + getDefaultCharSet();
1042 }
1043 }
1044 else
1045 {
1046 return contentType + "; charset=" + charSet;
1047 }
1048 }
1049
1050 return "";
1051 }
1052
1053 /***
1054 * Sets the HTTP content type to return.
1055 *
1056 * @param contentType a string.
1057 */
1058 public void setContentType(String contentType)
1059 {
1060 this.contentType = contentType;
1061 }
1062
1063 /***
1064 * Gets the redirect URI. If this is set, also make sure to set
1065 * the status code to 302.
1066 *
1067 * @return a string, "" if null.
1068 */
1069 public String getRedirectURI()
1070 {
1071 return (this.redirectURI == null ? "" : redirectURI);
1072 }
1073
1074 /***
1075 * Sets the redirect uri. If this is set, also make sure to set
1076 * the status code to 302.
1077 *
1078 * @param ruri a string.
1079 */
1080 public void setRedirectURI(String ruri)
1081 {
1082 this.redirectURI = ruri;
1083 }
1084
1085 /***
1086 * Gets the HTTP status code to return.
1087 *
1088 * @return the status.
1089 */
1090 public int getStatusCode()
1091 {
1092 return statusCode;
1093 }
1094
1095 /***
1096 * Sets the HTTP status code to return.
1097 *
1098 * @param statusCode the status.
1099 */
1100 public void setStatusCode(int statusCode)
1101 {
1102 this.statusCode = statusCode;
1103 }
1104
1105 /***
1106 * Gets an array of system errors.
1107 *
1108 * @return a SystemError[].
1109 */
1110 public SystemError[] getSystemErrors()
1111 {
1112 SystemError[] result = new SystemError[errors.size()];
1113 errors.toArray(result);
1114 return result;
1115 }
1116
1117 /***
1118 * Adds a critical system error.
1119 *
1120 * @param err a system error.
1121 */
1122 public void setSystemError(SystemError err)
1123 {
1124 this.errors.add(err);
1125 }
1126
1127 /***
1128 * Gets JNDI Contexts.
1129 *
1130 * @return a hashtable.
1131 */
1132 public Map getJNDIContexts()
1133 {
1134 if (jndiContexts == null)
1135 jndiContexts = new HashMap();
1136 return jndiContexts;
1137 }
1138
1139 /***
1140 * Sets JNDI Contexts.
1141 *
1142 * @param contexts a hashtable.
1143 */
1144 public void setJNDIContexts(Map contexts)
1145 {
1146 this.jndiContexts = contexts;
1147 }
1148
1149 /***
1150 * Gets the cached server scheme.
1151 *
1152 * @return a string.
1153 */
1154 public String getServerScheme()
1155 {
1156 return getServerData().getServerScheme();
1157 }
1158
1159 /***
1160 * Gets the cached server name.
1161 *
1162 * @return a string.
1163 */
1164 public String getServerName()
1165 {
1166 return getServerData().getServerName();
1167 }
1168
1169 /***
1170 * Gets the cached server port.
1171 *
1172 * @return an int.
1173 */
1174 public int getServerPort()
1175 {
1176 return getServerData().getServerPort();
1177 }
1178
1179 /***
1180 * Gets the cached context path.
1181 *
1182 * @return a string.
1183 */
1184 public String getContextPath()
1185 {
1186 return getServerData().getContextPath();
1187 }
1188
1189 /***
1190 * Gets the cached script name.
1191 *
1192 * @return a string.
1193 */
1194 public String getScriptName()
1195 {
1196 return getServerData().getScriptName();
1197 }
1198
1199 /***
1200 * Gets the server data ofy the request.
1201 *
1202 * @return server data.
1203 */
1204 public ServerData getServerData()
1205 {
1206 return this.serverData;
1207 }
1208
1209 /***
1210 * Gets the IP address of the client that sent the request.
1211 *
1212 * @return a string.
1213 */
1214 public String getRemoteAddr()
1215 {
1216 if (this.remoteAddr == null)
1217 {
1218 this.remoteAddr = this.getRequest().getRemoteAddr();
1219 }
1220
1221 return this.remoteAddr;
1222 }
1223
1224 /***
1225 * Gets the qualified name of the client that sent the request.
1226 *
1227 * @return a string.
1228 */
1229 public String getRemoteHost()
1230 {
1231 if (this.remoteHost == null)
1232 {
1233 this.remoteHost = this.getRequest().getRemoteHost();
1234 }
1235
1236 return this.remoteHost;
1237 }
1238
1239 /***
1240 * Get the user agent for the request. The semantics here
1241 * are muddled because RunData caches the value after the
1242 * first invocation. This is different e.g. from getCharSet().
1243 *
1244 * @return a string.
1245 */
1246 public String getUserAgent()
1247 {
1248 if (StringUtils.isEmpty(userAgent))
1249 {
1250 userAgent = this.getRequest().getHeader("User-Agent");
1251 }
1252
1253 return userAgent;
1254 }
1255
1256 /***
1257 * Pulls a user object from the session and increments the access
1258 * counter and sets the last access date for the object.
1259 */
1260 public void populate()
1261 {
1262 user = getUserFromSession();
1263
1264 if (user != null)
1265 {
1266 user.setLastAccessDate();
1267 user.incrementAccessCounter();
1268 user.incrementAccessCounterForSession();
1269 }
1270 }
1271
1272 /***
1273 * Saves a user object into the session.
1274 */
1275 public void save()
1276 {
1277 getSession().setAttribute(User.SESSION_KEY, user);
1278 }
1279
1280 /***
1281 * Gets the stack trace if set.
1282 *
1283 * @return the stack trace.
1284 */
1285 public String getStackTrace()
1286 {
1287 return stackTrace;
1288 }
1289
1290 /***
1291 * Gets the stack trace exception if set.
1292 *
1293 * @return the stack exception.
1294 */
1295 public Throwable getStackTraceException()
1296 {
1297 return stackTraceException;
1298 }
1299
1300 /***
1301 * Sets the stack trace.
1302 *
1303 * @param trace the stack trace.
1304 * @param exp the exception.
1305 */
1306 public void setStackTrace(String trace, Throwable exp)
1307 {
1308 stackTrace = trace;
1309 stackTraceException = exp;
1310 }
1311
1312 /***
1313 * Gets a Map of debug variables.
1314 *
1315 * @return a Map of debug variables.
1316 * @deprecated use {@link #getDebugVariables} instead
1317 */
1318 public Map getVarDebug()
1319 {
1320 return debugVariables;
1321 }
1322
1323 /***
1324 * Sets a name/value pair in an internal Map that is accessible from the
1325 * Error screen. This is a good way to get debugging information
1326 * when an exception is thrown.
1327 *
1328 * @param name name of the variable
1329 * @param value value of the variable.
1330 */
1331 public void setDebugVariable(String name, Object value)
1332 {
1333 this.debugVariables.put(name, value);
1334 }
1335
1336 /***
1337 * Gets a Map of debug variables.
1338 *
1339 * @return a Map of debug variables.
1340 */
1341 public Map getDebugVariables()
1342 {
1343 return this.debugVariables;
1344 }
1345
1346
1347
1348
1349
1350 /***
1351 * Gets the parameter parser without parsing the parameters.
1352 *
1353 * @return the parameter parser.
1354 * @todo Does this method make sense? Pulling the parameter out of
1355 * the run data object before setting a request (which happens
1356 * only in getParameters() leads to the Parameter parser having
1357 * no object and thus the default or even an undefined encoding
1358 * instead of the actual request character encoding).
1359 */
1360 public ParameterParser getParameterParser()
1361 {
1362 return parameters;
1363 }
1364
1365 /***
1366 * Sets the parameter parser.
1367 *
1368 * @param parser a parameter parser.
1369 */
1370 public void setParameterParser(ParameterParser parser)
1371 {
1372 parameters = parser;
1373 }
1374
1375 /***
1376 * Gets the cookie parser without parsing the cookies.
1377 *
1378 * @return the cookie parser.
1379 */
1380 public CookieParser getCookieParser()
1381 {
1382 return cookies;
1383 }
1384
1385 /***
1386 * Sets the cookie parser.
1387 *
1388 * @param parser a cookie parser.
1389 */
1390 public void setCookieParser(CookieParser parser)
1391 {
1392 cookies = parser;
1393 }
1394
1395 /***
1396 * Sets the servlet request.
1397 *
1398 * @param req a request.
1399 */
1400 public void setRequest(HttpServletRequest req)
1401 {
1402 this.req = req;
1403 }
1404
1405 /***
1406 * Sets the servlet response.
1407 *
1408 * @param res a response.
1409 */
1410 public void setResponse(HttpServletResponse res)
1411 {
1412 this.res = res;
1413 }
1414
1415 /***
1416 * Sets the servlet session information.
1417 *
1418 * @param sess a session.
1419 * @deprecated No replacement. This method no longer does anything.
1420 */
1421 public void setSession(HttpSession sess)
1422 {
1423 }
1424
1425 /***
1426 * Sets the servlet configuration used during servlet init.
1427 *
1428 * @param config a configuration.
1429 */
1430 public void setServletConfig(ServletConfig config)
1431 {
1432 this.config = config;
1433 if (config == null)
1434 {
1435 this.servletContext = null;
1436 }
1437 else
1438 {
1439 this.servletContext = config.getServletContext();
1440 }
1441 }
1442
1443 /***
1444 * Sets the server data of the request.
1445 *
1446 * @param serverData server data.
1447 */
1448 public void setServerData(ServerData serverData)
1449 {
1450 this.serverData = serverData;
1451 }
1452
1453
1454
1455
1456
1457 /***
1458 * Sets the print writer.
1459 *
1460 * @param out a print writer.
1461 * @deprecated no replacement planned, response writer will not be cached
1462 */
1463 protected void setOut(PrintWriter out)
1464 {
1465 this.out = out;
1466 }
1467
1468 /***
1469 * Sets the cached server scheme that is stored in the server data.
1470 *
1471 * @param serverScheme a string.
1472 */
1473 protected void setServerScheme(String serverScheme)
1474 {
1475 getServerData().setServerScheme(serverScheme);
1476 }
1477
1478 /***
1479 * Sets the cached server same that is stored in the server data.
1480 *
1481 * @param serverName a string.
1482 */
1483 protected void setServerName(String serverName)
1484 {
1485 getServerData().setServerName(serverName);
1486 }
1487
1488 /***
1489 * Sets the cached server port that is stored in the server data.
1490 *
1491 * @param port an int.
1492 */
1493 protected void setServerPort(int port)
1494 {
1495 getServerData().setServerPort(port);
1496 }
1497
1498 /***
1499 * Sets the cached context path that is stored in the server data.
1500 *
1501 * @param contextPath a string.
1502 */
1503 protected void setContextPath(String contextPath)
1504 {
1505 getServerData().setContextPath(contextPath);
1506 }
1507
1508 /***
1509 * Sets the cached script name that is stored in the server data.
1510 *
1511 * @param scriptName a string.
1512 */
1513 protected void setScriptName(String scriptName)
1514 {
1515 getServerData().setScriptName(scriptName);
1516 }
1517 }