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 534527 2007-05-02 16:10:59Z 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 /***
977 * Gets the charset. If it has not already been defined with
978 * setCharSet(), then a property named "locale.default.charset"
979 * is checked from the Resource Service and returned. If this
980 * property is undefined, the default charset of the locale
981 * is returned. If the locale is undefined, null is returned.
982 *
983 * @return the name of the charset or null.
984 */
985 public String getCharSet()
986 {
987 log.debug("getCharSet()");
988
989 if (StringUtils.isEmpty(charSet))
990 {
991 log.debug("Charset was null!");
992 return getDefaultCharSet();
993 }
994 else
995 {
996 return charSet;
997 }
998 }
999
1000 /***
1001 * Sets the charset.
1002 *
1003 * @param charSet the name of the new charset.
1004 */
1005 public void setCharSet(String charSet)
1006 {
1007 log.debug("setCharSet(" + charSet + ")");
1008 this.charSet = charSet;
1009 }
1010
1011 /***
1012 * Gets the HTTP content type to return. If a charset
1013 * has been specified, it is included in the content type.
1014 * If the charset has not been specified and the main type
1015 * of the content type is "text", the default charset is
1016 * included. If the default charset is undefined, but the
1017 * default locale is defined and it is not the US locale,
1018 * a locale specific charset is included.
1019 *
1020 * @return the content type or an empty string.
1021 */
1022 public String getContentType()
1023 {
1024 if (StringUtils.isNotEmpty(contentType))
1025 {
1026 if (StringUtils.isEmpty(charSet))
1027 {
1028 if (contentType.startsWith("text/"))
1029 {
1030 return contentType + "; charset=" + getDefaultCharSet();
1031 }
1032 }
1033 else
1034 {
1035 return contentType + "; charset=" + charSet;
1036 }
1037 }
1038
1039 return "";
1040 }
1041
1042 /***
1043 * Sets the HTTP content type to return.
1044 *
1045 * @param contentType a string.
1046 */
1047 public void setContentType(String contentType)
1048 {
1049 this.contentType = contentType;
1050 }
1051
1052 /***
1053 * Gets the redirect URI. If this is set, also make sure to set
1054 * the status code to 302.
1055 *
1056 * @return a string, "" if null.
1057 */
1058 public String getRedirectURI()
1059 {
1060 return (this.redirectURI == null ? "" : redirectURI);
1061 }
1062
1063 /***
1064 * Sets the redirect uri. If this is set, also make sure to set
1065 * the status code to 302.
1066 *
1067 * @param ruri a string.
1068 */
1069 public void setRedirectURI(String ruri)
1070 {
1071 this.redirectURI = ruri;
1072 }
1073
1074 /***
1075 * Gets the HTTP status code to return.
1076 *
1077 * @return the status.
1078 */
1079 public int getStatusCode()
1080 {
1081 return statusCode;
1082 }
1083
1084 /***
1085 * Sets the HTTP status code to return.
1086 *
1087 * @param statusCode the status.
1088 */
1089 public void setStatusCode(int statusCode)
1090 {
1091 this.statusCode = statusCode;
1092 }
1093
1094 /***
1095 * Gets an array of system errors.
1096 *
1097 * @return a SystemError[].
1098 */
1099 public SystemError[] getSystemErrors()
1100 {
1101 SystemError[] result = new SystemError[errors.size()];
1102 errors.toArray(result);
1103 return result;
1104 }
1105
1106 /***
1107 * Adds a critical system error.
1108 *
1109 * @param err a system error.
1110 */
1111 public void setSystemError(SystemError err)
1112 {
1113 this.errors.add(err);
1114 }
1115
1116 /***
1117 * Gets JNDI Contexts.
1118 *
1119 * @return a hashtable.
1120 */
1121 public Map getJNDIContexts()
1122 {
1123 if (jndiContexts == null)
1124 jndiContexts = new HashMap();
1125 return jndiContexts;
1126 }
1127
1128 /***
1129 * Sets JNDI Contexts.
1130 *
1131 * @param contexts a hashtable.
1132 */
1133 public void setJNDIContexts(Map contexts)
1134 {
1135 this.jndiContexts = contexts;
1136 }
1137
1138 /***
1139 * Gets the cached server scheme.
1140 *
1141 * @return a string.
1142 */
1143 public String getServerScheme()
1144 {
1145 return getServerData().getServerScheme();
1146 }
1147
1148 /***
1149 * Gets the cached server name.
1150 *
1151 * @return a string.
1152 */
1153 public String getServerName()
1154 {
1155 return getServerData().getServerName();
1156 }
1157
1158 /***
1159 * Gets the cached server port.
1160 *
1161 * @return an int.
1162 */
1163 public int getServerPort()
1164 {
1165 return getServerData().getServerPort();
1166 }
1167
1168 /***
1169 * Gets the cached context path.
1170 *
1171 * @return a string.
1172 */
1173 public String getContextPath()
1174 {
1175 return getServerData().getContextPath();
1176 }
1177
1178 /***
1179 * Gets the cached script name.
1180 *
1181 * @return a string.
1182 */
1183 public String getScriptName()
1184 {
1185 return getServerData().getScriptName();
1186 }
1187
1188 /***
1189 * Gets the server data ofy the request.
1190 *
1191 * @return server data.
1192 */
1193 public ServerData getServerData()
1194 {
1195 return this.serverData;
1196 }
1197
1198 /***
1199 * Gets the IP address of the client that sent the request.
1200 *
1201 * @return a string.
1202 */
1203 public String getRemoteAddr()
1204 {
1205 if (this.remoteAddr == null)
1206 {
1207 this.remoteAddr = this.getRequest().getRemoteAddr();
1208 }
1209
1210 return this.remoteAddr;
1211 }
1212
1213 /***
1214 * Gets the qualified name of the client that sent the request.
1215 *
1216 * @return a string.
1217 */
1218 public String getRemoteHost()
1219 {
1220 if (this.remoteHost == null)
1221 {
1222 this.remoteHost = this.getRequest().getRemoteHost();
1223 }
1224
1225 return this.remoteHost;
1226 }
1227
1228 /***
1229 * Get the user agent for the request. The semantics here
1230 * are muddled because RunData caches the value after the
1231 * first invocation. This is different e.g. from getCharSet().
1232 *
1233 * @return a string.
1234 */
1235 public String getUserAgent()
1236 {
1237 if (StringUtils.isEmpty(userAgent))
1238 {
1239 userAgent = this.getRequest().getHeader("User-Agent");
1240 }
1241
1242 return userAgent;
1243 }
1244
1245 /***
1246 * Pulls a user object from the session and increments the access
1247 * counter and sets the last access date for the object.
1248 */
1249 public void populate()
1250 {
1251 user = getUserFromSession();
1252
1253 if (user != null)
1254 {
1255 user.setLastAccessDate();
1256 user.incrementAccessCounter();
1257 user.incrementAccessCounterForSession();
1258 }
1259 }
1260
1261 /***
1262 * Saves a user object into the session.
1263 */
1264 public void save()
1265 {
1266 getSession().setAttribute(User.SESSION_KEY, user);
1267 }
1268
1269 /***
1270 * Gets the stack trace if set.
1271 *
1272 * @return the stack trace.
1273 */
1274 public String getStackTrace()
1275 {
1276 return stackTrace;
1277 }
1278
1279 /***
1280 * Gets the stack trace exception if set.
1281 *
1282 * @return the stack exception.
1283 */
1284 public Throwable getStackTraceException()
1285 {
1286 return stackTraceException;
1287 }
1288
1289 /***
1290 * Sets the stack trace.
1291 *
1292 * @param trace the stack trace.
1293 * @param exp the exception.
1294 */
1295 public void setStackTrace(String trace, Throwable exp)
1296 {
1297 stackTrace = trace;
1298 stackTraceException = exp;
1299 }
1300
1301 /***
1302 * Gets a Map of debug variables.
1303 *
1304 * @return a Map of debug variables.
1305 * @deprecated use {@link #getDebugVariables} instead
1306 */
1307 public Map getVarDebug()
1308 {
1309 return debugVariables;
1310 }
1311
1312 /***
1313 * Sets a name/value pair in an internal Map that is accessible from the
1314 * Error screen. This is a good way to get debugging information
1315 * when an exception is thrown.
1316 *
1317 * @param name name of the variable
1318 * @param value value of the variable.
1319 */
1320 public void setDebugVariable(String name, Object value)
1321 {
1322 this.debugVariables.put(name, value);
1323 }
1324
1325 /***
1326 * Gets a Map of debug variables.
1327 *
1328 * @return a Map of debug variables.
1329 */
1330 public Map getDebugVariables()
1331 {
1332 return this.debugVariables;
1333 }
1334
1335
1336
1337
1338
1339 /***
1340 * Gets the parameter parser without parsing the parameters.
1341 *
1342 * @return the parameter parser.
1343 * @todo Does this method make sense? Pulling the parameter out of
1344 * the run data object before setting a request (which happens
1345 * only in getParameters() leads to the Parameter parser having
1346 * no object and thus the default or even an undefined encoding
1347 * instead of the actual request character encoding).
1348 */
1349 public ParameterParser getParameterParser()
1350 {
1351 return parameters;
1352 }
1353
1354 /***
1355 * Sets the parameter parser.
1356 *
1357 * @param parser a parameter parser.
1358 */
1359 public void setParameterParser(ParameterParser parser)
1360 {
1361 parameters = parser;
1362 }
1363
1364 /***
1365 * Gets the cookie parser without parsing the cookies.
1366 *
1367 * @return the cookie parser.
1368 */
1369 public CookieParser getCookieParser()
1370 {
1371 return cookies;
1372 }
1373
1374 /***
1375 * Sets the cookie parser.
1376 *
1377 * @param parser a cookie parser.
1378 */
1379 public void setCookieParser(CookieParser parser)
1380 {
1381 cookies = parser;
1382 }
1383
1384 /***
1385 * Sets the servlet request.
1386 *
1387 * @param req a request.
1388 */
1389 public void setRequest(HttpServletRequest req)
1390 {
1391 this.req = req;
1392 }
1393
1394 /***
1395 * Sets the servlet response.
1396 *
1397 * @param res a response.
1398 */
1399 public void setResponse(HttpServletResponse res)
1400 {
1401 this.res = res;
1402 }
1403
1404 /***
1405 * Sets the servlet session information.
1406 *
1407 * @param sess a session.
1408 * @deprecated No replacement. This method no longer does anything.
1409 */
1410 public void setSession(HttpSession sess)
1411 {
1412 }
1413
1414 /***
1415 * Sets the servlet configuration used during servlet init.
1416 *
1417 * @param config a configuration.
1418 */
1419 public void setServletConfig(ServletConfig config)
1420 {
1421 this.config = config;
1422 if (config == null)
1423 {
1424 this.servletContext = null;
1425 }
1426 else
1427 {
1428 this.servletContext = config.getServletContext();
1429 }
1430 }
1431
1432 /***
1433 * Sets the server data of the request.
1434 *
1435 * @param serverData server data.
1436 */
1437 public void setServerData(ServerData serverData)
1438 {
1439 this.serverData = serverData;
1440 }
1441
1442
1443
1444
1445
1446 /***
1447 * Sets the print writer.
1448 *
1449 * @param out a print writer.
1450 * @deprecated no replacement planned, response writer will not be cached
1451 */
1452 protected void setOut(PrintWriter out)
1453 {
1454 this.out = out;
1455 }
1456
1457 /***
1458 * Sets the cached server scheme that is stored in the server data.
1459 *
1460 * @param serverScheme a string.
1461 */
1462 protected void setServerScheme(String serverScheme)
1463 {
1464 getServerData().setServerScheme(serverScheme);
1465 }
1466
1467 /***
1468 * Sets the cached server same that is stored in the server data.
1469 *
1470 * @param serverName a string.
1471 */
1472 protected void setServerName(String serverName)
1473 {
1474 getServerData().setServerName(serverName);
1475 }
1476
1477 /***
1478 * Sets the cached server port that is stored in the server data.
1479 *
1480 * @param port an int.
1481 */
1482 protected void setServerPort(int port)
1483 {
1484 getServerData().setServerPort(port);
1485 }
1486
1487 /***
1488 * Sets the cached context path that is stored in the server data.
1489 *
1490 * @param contextPath a string.
1491 */
1492 protected void setContextPath(String contextPath)
1493 {
1494 getServerData().setContextPath(contextPath);
1495 }
1496
1497 /***
1498 * Sets the cached script name that is stored in the server data.
1499 *
1500 * @param scriptName a string.
1501 */
1502 protected void setScriptName(String scriptName)
1503 {
1504 getServerData().setScriptName(scriptName);
1505 }
1506 }