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